From fe3644204ae62099b9d7de60c4049251d8024df3 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 26 May 2026 23:42:45 -0500 Subject: [PATCH] =?UTF-8?q?refactor:=20remove=20HCL=20definitions=20?= =?UTF-8?q?=E2=80=94=20Template=20repos=20are=20now=20canonical?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delete definitions/ directory (6 default + 48 sync = ~5000 lines of HCL) - Delete lib/Enterprise/DefinitionParser.php - Move manifest-schema.xsd to templates/schemas/ - Add governance.yml template for Template repos - Update RepositorySynchronizer to remove DefinitionParser dependency - Update push_files.php to detect platform from manifest.xml via API - Update auto_detect_platform.php to gracefully handle missing schema dir - Update archive_repo.php to remove sync def cleanup step Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .mokogitea/manifest.xml | 2 +- CLAUDE.md | 3 +- automation/push_files.php | 68 +- cli/archive_repo.php | 14 +- definitions/default/client.tf | 206 --- definitions/default/default-repository.json | 207 --- definitions/default/dolibarr.tf | 657 -------- definitions/default/generic-repository.tf | 1165 -------------- definitions/default/generic.tf | 637 -------- .../default/github-private-repository.tf | 331 ---- definitions/default/joomla.tf | 693 --------- definitions/default/mcp-server.tf | 484 ------ definitions/default/platform.tf | 342 ----- definitions/default/standards.tf | 748 --------- definitions/index.md | 31 - definitions/sync/.github-private.def.tf | 682 --------- definitions/sync/.github.def.tf | 733 --------- definitions/sync/.gitkeep | 0 definitions/sync/Copy-PortablePath.def.tf | 734 --------- definitions/sync/DoliMods.def.tf | 1333 ---------------- definitions/sync/MokoCRM.def.tf | 1335 ----------------- definitions/sync/MokoCassiopeia.def.tf | 1334 ---------------- definitions/sync/MokoDoliAdInsights.def.tf | 1334 ---------------- definitions/sync/MokoDoliArt.def.tf | 1334 ---------------- definitions/sync/MokoDoliAuth.def.tf | 1334 ---------------- definitions/sync/MokoDoliCare.def.tf | 1334 ---------------- definitions/sync/MokoDoliChimp.def.tf | 1334 ---------------- definitions/sync/MokoDoliClaude.def.tf | 1334 ---------------- definitions/sync/MokoDoliCredits.def.tf | 1334 ---------------- definitions/sync/MokoDoliDymo.def.tf | 1334 ---------------- definitions/sync/MokoDoliForm.def.tf | 1334 ---------------- definitions/sync/MokoDoliG.def.tf | 1334 ---------------- definitions/sync/MokoDoliGithub.def.tf | 1334 ---------------- definitions/sync/MokoDoliHRM.def.tf | 1334 ---------------- definitions/sync/MokoDoliMods.def.tf | 400 ----- definitions/sync/MokoDoliMulti.def.tf | 1334 ---------------- definitions/sync/MokoDoliOffline.def.tf | 1334 ---------------- definitions/sync/MokoDoliPhone.com.def.tf | 1334 ---------------- definitions/sync/MokoDoliProjTemplate.def.tf | 1334 ---------------- definitions/sync/MokoDoliRelease.def.tf | 1334 ---------------- definitions/sync/MokoDoliSign.def.tf | 1334 ---------------- definitions/sync/MokoDoliTools.def.tf | 1255 ---------------- definitions/sync/MokoDoliTraining.def.tf | 1334 ---------------- definitions/sync/MokoDolibarr.def.tf | 400 ----- definitions/sync/MokoISOUpdatePortable.def.tf | 734 --------- definitions/sync/MokoJoomHero.def.tf | 1333 ---------------- definitions/sync/MokoJoomTOS.def.tf | 1333 ---------------- .../sync/MokoPerfectPublisher-Discord.def.tf | 734 --------- .../sync/MokoStandards-Template-Client.def.tf | 734 --------- .../MokoStandards-Template-Dolibarr.def.tf | 1334 ---------------- .../MokoStandards-Template-Generic.def.tf | 734 --------- ...Standards-Template-Joomla-Component.def.tf | 1334 ---------------- ...koStandards-Template-Joomla-Library.def.tf | 1334 ---------------- ...okoStandards-Template-Joomla-Module.def.tf | 1334 ---------------- ...koStandards-Template-Joomla-Package.def.tf | 1334 ---------------- ...okoStandards-Template-Joomla-Plugin.def.tf | 1334 ---------------- ...oStandards-Template-Joomla-Template.def.tf | 1334 ---------------- definitions/sync/MokoTesting.def.tf | 734 --------- definitions/sync/MokoWaaS.def.tf | 1334 ---------------- definitions/sync/MokoWaaSAnnounce.def.tf | 1334 ---------------- definitions/sync/MokoWaaSBrand.def.tf | 1286 ---------------- definitions/sync/MokoWinSetup.def.tf | 734 --------- .../sync/PLG_FINDER_MOKOVMSMARTSEARCH.def.tf | 734 --------- .../sync/client-clarksvillefurs.def.tf | 775 ---------- definitions/sync/client-kiddieland.def.tf | 734 --------- definitions/sync/client-vexcreations.def.tf | 1334 ---------------- definitions/sync/joomla-api-mcp.def.tf | 43 - lib/Enterprise/DefinitionParser.php | 501 ------- lib/Enterprise/MokoStandardsParser.php | 2 +- lib/Enterprise/RepositorySynchronizer.php | 5 +- templates/governance.yml | 86 ++ .../schemas}/manifest-schema.xsd | 0 validate/auto_detect_platform.php | 4 +- 73 files changed, 118 insertions(+), 63602 deletions(-) delete mode 100644 definitions/default/client.tf delete mode 100644 definitions/default/default-repository.json delete mode 100644 definitions/default/dolibarr.tf delete mode 100644 definitions/default/generic-repository.tf delete mode 100644 definitions/default/generic.tf delete mode 100644 definitions/default/github-private-repository.tf delete mode 100644 definitions/default/joomla.tf delete mode 100644 definitions/default/mcp-server.tf delete mode 100644 definitions/default/platform.tf delete mode 100644 definitions/default/standards.tf delete mode 100644 definitions/index.md delete mode 100644 definitions/sync/.github-private.def.tf delete mode 100644 definitions/sync/.github.def.tf delete mode 100644 definitions/sync/.gitkeep delete mode 100644 definitions/sync/Copy-PortablePath.def.tf delete mode 100644 definitions/sync/DoliMods.def.tf delete mode 100644 definitions/sync/MokoCRM.def.tf delete mode 100644 definitions/sync/MokoCassiopeia.def.tf delete mode 100644 definitions/sync/MokoDoliAdInsights.def.tf delete mode 100644 definitions/sync/MokoDoliArt.def.tf delete mode 100644 definitions/sync/MokoDoliAuth.def.tf delete mode 100644 definitions/sync/MokoDoliCare.def.tf delete mode 100644 definitions/sync/MokoDoliChimp.def.tf delete mode 100644 definitions/sync/MokoDoliClaude.def.tf delete mode 100644 definitions/sync/MokoDoliCredits.def.tf delete mode 100644 definitions/sync/MokoDoliDymo.def.tf delete mode 100644 definitions/sync/MokoDoliForm.def.tf delete mode 100644 definitions/sync/MokoDoliG.def.tf delete mode 100644 definitions/sync/MokoDoliGithub.def.tf delete mode 100644 definitions/sync/MokoDoliHRM.def.tf delete mode 100644 definitions/sync/MokoDoliMods.def.tf delete mode 100644 definitions/sync/MokoDoliMulti.def.tf delete mode 100644 definitions/sync/MokoDoliOffline.def.tf delete mode 100644 definitions/sync/MokoDoliPhone.com.def.tf delete mode 100644 definitions/sync/MokoDoliProjTemplate.def.tf delete mode 100644 definitions/sync/MokoDoliRelease.def.tf delete mode 100644 definitions/sync/MokoDoliSign.def.tf delete mode 100644 definitions/sync/MokoDoliTools.def.tf delete mode 100644 definitions/sync/MokoDoliTraining.def.tf delete mode 100644 definitions/sync/MokoDolibarr.def.tf delete mode 100644 definitions/sync/MokoISOUpdatePortable.def.tf delete mode 100644 definitions/sync/MokoJoomHero.def.tf delete mode 100644 definitions/sync/MokoJoomTOS.def.tf delete mode 100644 definitions/sync/MokoPerfectPublisher-Discord.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Client.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Dolibarr.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Generic.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Component.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Library.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Module.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Package.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Plugin.def.tf delete mode 100644 definitions/sync/MokoStandards-Template-Joomla-Template.def.tf delete mode 100644 definitions/sync/MokoTesting.def.tf delete mode 100644 definitions/sync/MokoWaaS.def.tf delete mode 100644 definitions/sync/MokoWaaSAnnounce.def.tf delete mode 100644 definitions/sync/MokoWaaSBrand.def.tf delete mode 100644 definitions/sync/MokoWinSetup.def.tf delete mode 100644 definitions/sync/PLG_FINDER_MOKOVMSMARTSEARCH.def.tf delete mode 100644 definitions/sync/client-clarksvillefurs.def.tf delete mode 100644 definitions/sync/client-kiddieland.def.tf delete mode 100644 definitions/sync/client-vexcreations.def.tf delete mode 100644 definitions/sync/joomla-api-mcp.def.tf delete mode 100644 lib/Enterprise/DefinitionParser.php create mode 100644 templates/governance.yml rename {definitions => templates/schemas}/manifest-schema.xsd (100%) diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml index b3c0439..e018be7 100644 --- a/.mokogitea/manifest.xml +++ b/.mokogitea/manifest.xml @@ -6,7 +6,7 @@ --> moko-platform diff --git a/CLAUDE.md b/CLAUDE.md index c8c42c7..676bddc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -44,8 +44,7 @@ composer check | `lib/Enterprise/` | Core library — CliFramework, ApiClient, adapters, validators | | `lib/Enterprise/Plugins/` | 11 platform plugins (Joomla, Dolibarr, Node.js, Python, etc.) | | `deploy/` | SFTP deployment scripts (Joomla, Dolibarr, health checks) | -| `definitions/` | Repository structure definitions (HCL format) | -| `templates/` | Workflow templates, config templates, docs templates | +| `templates/` | Universal templates, configs, governance schema | | `.mokogitea/workflows/` | CI/CD workflows (Gitea Actions) | | `bin/moko` | Unified CLI dispatcher — runs any tool via `php bin/moko ` | diff --git a/automation/push_files.php b/automation/push_files.php index a97bc46..5f7c554 100644 --- a/automation/push_files.php +++ b/automation/push_files.php @@ -26,7 +26,6 @@ use MokoEnterprise\{ AuditLogger, CliFramework, Config, - DefinitionParser, GitPlatformAdapter, MetricsCollector, PlatformAdapterFactory, @@ -59,7 +58,6 @@ class PushFiles extends CliFramework private ApiClient $api; private GitPlatformAdapter $adapter; private AuditLogger $logger; - private DefinitionParser $defParser; private ProjectTypeDetector $typeDetector; /** @@ -154,7 +152,6 @@ class PushFiles extends CliFramework $this->adapter = PlatformAdapterFactory::create($config); $this->api = $this->adapter->getApiClient(); $this->logger = new AuditLogger('push_files'); - $this->defParser = new DefinitionParser(); $this->typeDetector = new ProjectTypeDetector($this->logger); $platform = $this->adapter->getPlatformName(); @@ -198,43 +195,24 @@ class PushFiles extends CliFramework $platform = $this->detectRepoPlatform($org, $repo); $this->log(" {$repo}: platform = {$platform}", 'INFO'); - // Build a destination→source lookup from the definition - $defEntries = $this->defParser->parseForPlatform($platform, $repoRoot); - $destToSource = []; - foreach ($defEntries as $entry) { - $destToSource[$entry['destination']] = $entry['source']; - } - $resolved = []; foreach ($files as $fileSpec) { if (str_contains($fileSpec, ':')) { // Raw source:destination pair [$src, $dest] = explode(':', $fileSpec, 2); - $srcAbs = rtrim($repoRoot, '/') . '/' . ltrim($src, '/'); - if (!file_exists($srcAbs)) { - $this->log(" ⚠️ Source not found for {$repo}: {$src}", 'WARN'); - continue; - } - $resolved[] = ['source' => $srcAbs, 'destination' => $dest]; - $this->log(" ✓ {$dest} (raw: {$src})", 'INFO'); } else { - // Destination path — look up in definition - $dest = ltrim($fileSpec, '/'); - if (isset($destToSource[$dest])) { - $src = $destToSource[$dest]; - $srcAbs = str_starts_with($src, '/') - ? $src - : rtrim($repoRoot, '/') . '/' . ltrim($src, '/'); - if (!file_exists($srcAbs)) { - $this->log(" ⚠️ Template not found for {$repo}: {$src}", 'WARN'); - continue; - } - $resolved[] = ['source' => $srcAbs, 'destination' => $dest]; - $this->log(" ✓ {$dest}", 'INFO'); - } else { - $this->log(" ⚠️ {$dest} not found in {$platform} definition for {$repo}", 'WARN'); - } + // Same path as source and destination + $src = $fileSpec; + $dest = $fileSpec; } + $dest = ltrim($dest, '/'); + $srcAbs = rtrim($repoRoot, '/') . '/' . ltrim($src, '/'); + if (!file_exists($srcAbs)) { + $this->log(" ⚠️ Source not found for {$repo}: {$src}", 'WARN'); + continue; + } + $resolved[] = ['source' => $srcAbs, 'destination' => $dest]; + $this->log(" ✓ {$dest}", 'INFO'); } if (!empty($resolved)) { @@ -246,24 +224,28 @@ class PushFiles extends CliFramework } /** - * Detect platform for a repo by checking its sync def file, falling back - * to the live GitHub API detection used by bulk_sync. + * Detect platform for a repo via manifest or live detection. */ private function detectRepoPlatform(string $org, string $repo): string { - // Check local sync def first — fastest path - $defDir = dirname(__DIR__) . '/definitions/sync'; - $defFile = "{$defDir}/{$repo}.def.tf"; - if (file_exists($defFile)) { - $content = file_get_contents($defFile) ?: ''; - if (preg_match('/detected_platform\s*=\s*"([^"]+)"/', $content, $m)) { - return $m[1]; + // Read platform from repo's .mokogitea/manifest.xml via API + try { + $manifestData = $this->adapter->getFileContent($org, $repo, '.mokogitea/manifest.xml', 'main'); + if (!empty($manifestData)) { + $xml = @simplexml_load_string($manifestData); + if ($xml !== false) { + $platform = (string)($xml->governance->platform ?? ''); + if (!empty($platform)) { + return $platform; + } + } } + } catch (\Exception $e) { + // Fall through to local detection } // Fall back to live detection try { - $repoData = $this->api->get("/repos/{$org}/{$repo}"); $result = $this->typeDetector->detect('.'); return $result['type'] ?? 'default'; } catch (\Exception $e) { diff --git a/cli/archive_repo.php b/cli/archive_repo.php index d71fe33..26b18d5 100644 --- a/cli/archive_repo.php +++ b/cli/archive_repo.php @@ -118,19 +118,7 @@ if (!$dryRun) { echo " (dry-run) would archive {$org}/{$repoName}\n"; } -// ── Step 5: Remove sync definition ────────────────────────────────────── -echo "Step 5: Removing sync definition...\n"; -$defFile = "{$repoRoot}/definitions/sync/{$repoName}.def.tf"; -if (file_exists($defFile)) { - if (!$dryRun) { - unlink($defFile); - echo " Removed: {$defFile}\n"; - } else { - echo " (dry-run) would remove {$defFile}\n"; - } -} else { - echo " No sync definition found\n"; -} +// ── Step 5: (removed — sync definitions no longer used) ───────────────── // ── Step 6: Create archival record ────────────────────────────────────── echo "Step 6: Creating archival record...\n"; diff --git a/definitions/default/client.tf b/definitions/default/client.tf deleted file mode 100644 index e8f95c8..0000000 --- a/definitions/default/client.tf +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Client Repository Structure Definition - * Standard repository structure for managed Joomla client sites (WaaS) - * - * This is NOT a Joomla extension — it's a full managed client site with - * deployment configs, monitoring, SFTP settings, and sync workflows. - * The src/ directory mirrors the Joomla site's public_html. - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Client Site" - description = "Managed Joomla client site — full site structure, not an extension" - repository_type = "client" - platform = "client" - last_updated = "2026-05-09T00:00:00Z" - maintainer = "Moko Consulting" - version = "01.00.00" - schema_version = "1.0" - } - - detection_hints = [ - "scripts/sftp-config/", - "scripts/sync-dev-to-live.sh", - "monitoring/grafana/", - "src/administrator/", - "src/components/", - "src/plugins/", - "src/templates/", - "src/media/templates/site/mokoonyx/" - ] - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Client site overview and deployment info" - required = true - always_overwrite = false - protected = true - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Release history" - required = true - always_overwrite = false - }, - { - name = "LICENSE" - extension = "" - description = "GPL-3.0-or-later license file" - required = true - always_overwrite = true - template = "templates/docs/required/LICENSE" - }, - { - name = "Makefile" - extension = "" - description = "Build and deployment targets (includes minify)" - required = true - always_overwrite = false - }, - { - name = "composer.json" - extension = "json" - description = "PHP dependencies" - required = true - always_overwrite = false - }, - { - name = ".gitignore" - extension = "" - description = "Git ignore rules (must include *.min.css, *.min.js, TODO.md)" - required = true - always_overwrite = false - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Joomla site public_html mirror — deployed via SFTP" - required = true - purpose = "Contains the full Joomla site directory structure" - subdirectories = [ - { name = "administrator", path = "src/administrator", description = "Joomla admin", required = true }, - { name = "components", path = "src/components", description = "Frontend components", required = true }, - { name = "plugins", path = "src/plugins", description = "Plugins", required = true }, - { name = "modules", path = "src/modules", description = "Modules", required = true }, - { name = "templates", path = "src/templates", description = "Templates", required = true }, - { name = "media", path = "src/media", description = "Media assets", required = true }, - { name = "images", path = "src/images", description = "Site images", required = false }, - { name = "language", path = "src/language", description = "Language files", required = false }, - { name = "libraries", path = "src/libraries", description = "Libraries", required = false }, - { name = "layouts", path = "src/layouts", description = "Layouts", required = false } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Deployment, sync, and monitoring scripts" - required = true - purpose = "Contains SFTP configs, sync scripts, and monitoring" - subdirectories = [ - { - name = "sftp-config" - path = "scripts/sftp-config" - description = "SFTP connection configs (dev + live)" - required = true - files = [ - { - name = "sftp-config.dev.json" - extension = "json" - description = "Dev server SFTP connection" - required = true - always_overwrite = false - }, - { - name = "sftp-config.rs.json" - extension = "json" - description = "Live/release server SFTP connection" - required = true - always_overwrite = false - } - ] - } - ] - }, - { - name = "monitoring" - path = "monitoring" - description = "Grafana dashboard templates" - required = true - purpose = "Contains Panopticon-style Grafana dashboard JSON" - subdirectories = [ - { - name = "grafana" - path = "monitoring/grafana" - description = "Grafana dashboard JSON templates" - required = true - files = [ - { - name = "client-joomla-dashboard.json" - extension = "json" - description = "Panopticon-style Grafana dashboard template" - required = true - always_overwrite = true - template = "templates/monitoring/client-joomla-dashboard.json" - } - ] - } - ] - }, - { - name = ".gitea" - path = ".gitea" - description = "Gitea configuration" - required = true - purpose = "Contains Gitea Actions workflows" - subdirectories = [ - { - name = "workflows" - path = ".gitea/workflows" - description = "Gitea Actions CI/CD workflows" - required = true - files = [ - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-release on merge to main" - required = true - always_overwrite = true - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deploy src/ to servers via SFTP" - required = true - always_overwrite = true - }, - { - name = "add-endpoint.yml" - extension = "yml" - description = "Add monitoring endpoint to sites.json" - required = true - always_overwrite = true - } - ] - } - ] - } - ] - } -} - -output "client_structure" { - description = "Client site repository structure definition" - value = local.repository_structure -} diff --git a/definitions/default/default-repository.json b/definitions/default/default-repository.json deleted file mode 100644 index 739f1ab..0000000 --- a/definitions/default/default-repository.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "schemaVersion": "1.0", - "metadata": { - "name": "Default Repository Structure", - "description": "Default repository structure applicable to all repository types with minimal requirements", - "repositoryType": "library", - "platform": "multi-platform", - "lastUpdated": "2026-01-16T00:00:00Z", - "maintainer": "Moko Consulting" - }, - "structure": { - "rootFiles": [ - { - "name": "README.md", - "extension": "md", - "description": "Project overview and documentation", - "requirementStatus": "required", - "audience": "general", - "template": "templates/docs/required/template-README.md" - }, - { - "name": "LICENSE", - "extension": "", - "description": "License file (GPL-3.0-or-later)", - "requirementStatus": "required", - "audience": "general", - "template": "templates/licenses/GPL-3.0" - }, - { - "name": "CHANGELOG.md", - "extension": "md", - "description": "Version history and changes", - "requirementStatus": "required", - "audience": "general", - "template": "templates/docs/required/template-CHANGELOG.md" - }, - { - "name": "CONTRIBUTING.md", - "extension": "md", - "description": "Contribution guidelines", - "requirementStatus": "required", - "audience": "contributor", - "template": "templates/docs/required/template-CONTRIBUTING.md" - }, - { - "name": "SECURITY.md", - "extension": "md", - "description": "Security policy and vulnerability reporting", - "requirementStatus": "required", - "audience": "general", - "template": "templates/docs/required/template-SECURITY.md" - }, - { - "name": "CODE_OF_CONDUCT.md", - "extension": "md", - "description": "Community code of conduct", - "requirementStatus": "suggested", - "audience": "contributor", - "template": "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - "name": ".gitignore", - "extension": "gitignore", - "description": "Git ignore patterns", - "requirementStatus": "required", - "alwaysOverwrite": false, - "audience": "developer" - }, - { - "name": ".gitattributes", - "extension": "gitattributes", - "description": "Git attributes configuration", - "requirementStatus": "required", - "audience": "developer" - }, - { - "name": ".editorconfig", - "extension": "editorconfig", - "description": "Editor configuration for consistent coding style", - "requirementStatus": "required", - "alwaysOverwrite": false, - "audience": "developer" - }, - { - "name": "Makefile", - "description": "Build automation", - "requirementStatus": "suggested", - "audience": "developer" - }, - { - "name": "renovate.json", - "extension": "json", - "description": "Renovate dependency management configuration", - "requirementStatus": "required", - "alwaysOverwrite": false, - "audience": "developer", - "template": "templates/configs/renovate.json" - } - ], - "directories": [ - { - "name": "docs", - "path": "docs", - "description": "Documentation directory", - "requirementStatus": "required", - "purpose": "Contains comprehensive project documentation", - "files": [ - { - "name": "index.md", - "extension": "md", - "description": "Documentation index", - "requirementStatus": "suggested" - } - ] - }, - { - "name": "scripts", - "path": "scripts", - "description": "Build and automation scripts", - "requirementStatus": "required", - "purpose": "Contains scripts for building, testing, and deploying" - }, - { - "name": "src", - "path": "src", - "description": "Source code directory", - "requirementStatus": "required", - "purpose": "Contains application source code" - }, - { - "name": "tests", - "path": "tests", - "description": "Test files", - "requirementStatus": "suggested", - "purpose": "Contains unit tests, integration tests, and test fixtures", - "subdirectories": [ - { - "name": "unit", - "path": "tests/unit", - "description": "Unit tests", - "requirementStatus": "suggested" - }, - { - "name": "integration", - "path": "tests/integration", - "description": "Integration tests", - "requirementStatus": "optional" - } - ] - }, - { - "name": ".github", - "path": ".github", - "description": "Gitea/GitHub Actions configuration (Gitea reads .github/workflows natively)", - "requirementStatus": "required", - "purpose": "Contains CI/CD workflows and repository configuration. Gitea is the primary platform; GitHub is backup only.", - "subdirectories": [ - { - "name": "workflows", - "path": ".github/workflows", - "description": "CI/CD workflows (Gitea-primary, GitHub-compatible)", - "requirementStatus": "required", - "requiredFiles": [ - "auto-assign.yml", - "auto-dev-issue.yml", - "auto-release.yml", - "branch-freeze.yml", - "changelog-validation.yml", - "repository-cleanup.yml", - "sync-version-on-merge.yml", - "cascade-dev.yml", - "gitleaks.yml" - ] - } - ] - }, - { - "name": "node_modules", - "path": "node_modules", - "description": "Node.js dependencies (generated)", - "requirementStatus": "not-allowed", - "purpose": "Generated directory that should not be committed" - }, - { - "name": "vendor", - "path": "vendor", - "description": "PHP dependencies (generated)", - "requirementStatus": "not-allowed", - "purpose": "Generated directory that should not be committed" - }, - { - "name": "build", - "path": "build", - "description": "Build artifacts (generated)", - "requirementStatus": "not-allowed", - "purpose": "Generated directory that should not be committed" - }, - { - "name": "dist", - "path": "dist", - "description": "Distribution files (generated)", - "requirementStatus": "not-allowed", - "purpose": "Generated directory that should not be committed" - } - ] - } -} diff --git a/definitions/default/dolibarr.tf b/definitions/default/dolibarr.tf deleted file mode 100644 index bbaeaf7..0000000 --- a/definitions/default/dolibarr.tf +++ /dev/null @@ -1,657 +0,0 @@ -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "dolibarr" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - audience = "developer" - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - }, - { - name = "renovate.json" - extension = "json" - description = "Renovate dependency management configuration" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/renovate.json" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".mokogitea" - path = ".mokogitea" - description = "Gitea-specific configuration and workflows" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows, manifest.xml, and CI/CD configuration" - subdirectories = [ - { - name = "workflows" - path = ".mokogitea/workflows" - description = "Gitea Actions workflows (universal)" - requirement_status = "required" - files = [ - { - name = "auto-bump.yml" - extension = "yml" - description = "Auto-bump patch version on push to dev" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-bump.yml" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Universal build and release pipeline on merge to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-release.yml" - }, - { - name = "branch-cleanup.yml" - extension = "yml" - description = "Auto-delete merged feature branches after PR merge" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/branch-cleanup.yml" - }, - { - name = "cascade-dev.yml" - extension = "yml" - description = "Forward-merge main to dev and pre-release branches on push to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cascade-dev.yml" - }, - { - name = "cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of retired workflows, stale branches, and old runs" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cleanup.yml" - }, - { - name = "gitleaks.yml" - extension = "yml" - description = "Secret scanning — detect leaked credentials, API keys, and tokens" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/gitleaks.yml" - }, - { - name = "issue-branch.yml" - extension = "yml" - description = "Auto-create feature branch from issue assignment" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/issue-branch.yml" - }, - { - name = "notify.yml" - extension = "yml" - description = "Notification workflow for release and CI events" - requirement_status = "suggested" - always_overwrite = true - template = ".mokogitea/workflows/notify.yml" - }, - { - name = "pr-check.yml" - extension = "yml" - description = "Pull request validation checks" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pr-check.yml" - }, - { - name = "pre-release.yml" - extension = "yml" - description = "Manual pre-release builds for dev/alpha/beta/rc channels" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pre-release.yml" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health checks and standards validation" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/repo-health.yml" - }, - { - name = "security-audit.yml" - extension = "yml" - description = "Dependency and security audit workflow" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/security-audit.yml" - }, - { - name = "update-server.yml" - extension = "yml" - description = "Update server XML feed with stability channel entries" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/update-server.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".mokogitea/ISSUE_TEMPLATE" - description = "Issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - files = [ - { - name = "manifest.xml" - extension = "xml" - description = "Repository manifest — version, platform, governance metadata" - requirement_status = "required" - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/default/generic-repository.tf b/definitions/default/generic-repository.tf deleted file mode 100644 index 48aa63c..0000000 --- a/definitions/default/generic-repository.tf +++ /dev/null @@ -1,1165 +0,0 @@ -/** - * Generic Repository Structure Definition - * Standard repository structure for generic projects and libraries - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Generic Repository" - description = "Standard repository structure for generic projects and libraries" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - required = true - audience = "general" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.generic" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "suggested" - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - audience = "developer" - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Source code" - requirement_status = "suggested" - purpose = "Contains application/library source code" - }, - { - name = "docs" - path = "docs" - description = "Documentation" - required = true - purpose = "Contains comprehensive documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{PRIMARY_LANGUAGE}}` | The dominant programming language (check file extensions in the repository) | - > | `{{PLATFORM_TYPE}}` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. — infer from repo structure | - > - > --- - - # {{REPO_NAME}} — 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: {{REPO_URL}} - Primary language: **{{PRIMARY_LANGUAGE}}** - Platform type: **{{PLATFORM_TYPE}}** - - --- - - ## Primary Language - - **{{PRIMARY_LANGUAGE}} is the primary language for this repository.** Follow the conventions documented in [MokoStandards coding-style-guide](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md). - - YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`. - - --- - - ## File Header — Always Required on New Files - - Every new file needs a copyright header as its first content. Use the minimal form unless the file is a policy doc, README, or public API. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - declare(strict_types=1); - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in the README.md `FILE INFORMATION` block governs all other version references. - - Update the version in `README.md` only — the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `04.00.04`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). This applies to all `actions/checkout`, `gh` CLI calls, and any step that talks to the GitHub API. - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these in workflows - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - PHP scripts read the token with: `getenv('GH_TOKEN') ?: getenv('GITHUB_TOKEN')` — `GH_TOKEN` is always preferred; `GITHUB_TOKEN` is accepted only as a local-dev fallback. - - --- - - ## Composer Package (PHP repositories) - - This repository requires the MokoStandards enterprise library. The `composer.json` must include: - - ```json - { - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/mokoconsulting-tech/MokoStandards" - } - ], - "require": { - "mokoconsulting/mokostandards": "^4.0" - } - } - ``` - - Run `composer install` after adding the dependency. See [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) for full instructions. - - --- - - ## PHP Script Pattern - - All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`. - - ```php - #!/usr/bin/env php - setDescription('One-line description'); - $this->addArgument('--path', 'Repository root', '.'); - $this->addArgument('--dry-run', 'Preview without writing', false); - } - - protected function run(): int - { - $path = $this->getArgument('--path'); - $dryRun = (bool) $this->getArgument('--dry-run'); - - $this->log('INFO', "Processing: {$path}"); - return 0; - } - } - - $script = new MyScript('my_script', 'One-line description'); - exit($script->execute()); - ``` - - **Key rules:** - - Abstract methods to implement: `configure()` and `run()` — **not** `execute()` - - `execute()` is the **public entry point** that orchestrates setup (arg parsing, `initialize()`) and then calls your `run()` implementation; call it at the bottom with `exit($script->execute())` - - Entry point at the bottom: `$script->execute()` — **not** `$script->run()` - - Constructor always takes `(string $name, string $description = '')`; pass the description here — `setDescription()` inside `configure()` is only needed to override it - - `log(string $level, string $message)` — level is the **first** argument (INFO / SUCCESS / WARNING / ERROR) - - `$this->dryRun` and `$this->verbose` are set automatically from `--dry-run` / `--verbose` - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$repo_path` | - | PHP constant | `UPPER_SNAKE_CASE` | `DEFAULT_THRESHOLD` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `bulk-repo-sync.yml` | - | Markdown doc | `kebab-case.md` | `coding-style-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - Examples: - - `feat(module): add user preference caching` - - `fix(api): handle null response from external service` - - `docs(readme): update installation instructions` - - `chore(deps): bump phpunit to 11.x` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - - ✅ `dev/1.2.0/add-feature` - - ✅ `patch/1.2.1/fix-bug` - - ❌ `feature/my-thing` — rejected by branch protection - - --- - - ## Keeping Documentation Current - - Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale. - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class | - | New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent | - | New or changed GitHub Actions workflow | `docs/workflows/.md` | - | New or changed policy | Corresponding file under `docs/policy/` | - | New library class or major feature | `CHANGELOG.md` entry under `Added` | - | Bug fix | `CHANGELOG.md` entry under `Fixed` | - | Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change | - | Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block | - | **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge | - - If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR. - - --- - - ## Key Constraints - - - Never commit directly to `main` — all changes go via PR, squash-merged - - Never skip the FILE INFORMATION block on a new file - - Never use bare `catch (\Throwable $e) {}` without logging or re-throwing - - Never hardcode version numbers in body text — update `README.md` and let automation propagate - - Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN` - - Never extend `CliBase` in PHP scripts — extend `MokoStandards\Enterprise\CliFramework` - - Never call `$script->run()` as the entry point — call `$script->execute()` - - Policy documents and guides must not be mixed - - --- - - ## MokoStandards Reference - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies: - - | Document | Purpose | - |----------|---------| - | [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type | - | [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions | - | [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow | - | [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) | PHP script requirements and CliFramework usage | - | [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) | Installing `mokoconsulting/mokostandards` via Composer | - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{PRIMARY_LANGUAGE}}` | The dominant programming language (check file extensions in the repository) | - > | `{{PLATFORM_TYPE}}` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. — infer from repo structure | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **{{PLATFORM_TYPE}}** repository. - - {{REPO_DESCRIPTION}} - - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Primary source code - ├── docs/ # Documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── ISSUE_TEMPLATE/ # Issue templates (inherited from mokoconsulting-tech/.github-private) - │ ├── copilot-instructions.md # GitHub Copilot custom instructions - │ ├── CLAUDE.md # This file — Claude AI assistant context - │ └── override.tf # Repository-specific health-check overrides - ├── README.md # Project overview — version source of truth - ├── CHANGELOG.md # Version history - ├── CONTRIBUTING.md # Contribution guidelines - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **{{PRIMARY_LANGUAGE}}** is the primary language for this repository. - - YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`. - - --- - - # Composer Package (PHP repositories) - - This repository requires the MokoStandards enterprise library. The package is installed from the private GitHub VCS source. - - `composer.json` must contain: - - ```json - { - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/mokoconsulting-tech/MokoStandards" - } - ], - "require": { - "mokoconsulting/mokostandards": "^4.0" - } - } - ``` - - Install or update with: - - ```bash - composer install # first time - composer update mokoconsulting/mokostandards # upgrade - ``` - - --- - - # PHP Script Pattern - - All PHP scripts must extend `MokoStandards\Enterprise\CliFramework` — **never** use a standalone class or the legacy `CliBase`. - - ```php - #!/usr/bin/env php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Scripts - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /api/my_script.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of what this script does - */ - - 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 of what this script does'); - $this->addArgument('--path', 'Repository root path', '.'); - $this->addArgument('--dry-run', 'Preview changes without writing', false); - } - - protected function run(): int - { - $path = $this->getArgument('--path'); - $dryRun = (bool) $this->getArgument('--dry-run'); - - // implementation … - $this->log('INFO', "Processing: {$path}"); - - return 0; - } - } - - $script = new MyScript('my_script', 'One-line description of what this script does'); - exit($script->execute()); - ``` - - **CliFramework interface summary:** - - | Member | Purpose | - |--------|---------| - | `configure(): void` | Abstract — register arguments with `addArgument()` | - | `run(): int` | Abstract — main script logic; return the exit code | - | `initialize(): void` | Optional hook — runs after arg-parse, before `run()` | - | `execute(array $argv = []): int` | **Public entry point** — call this at the bottom; it calls `configure()`, parses argv, then calls `run()` | - | `addArgument(string $name, string $desc, mixed $default)` | Register a CLI argument | - | `getArgument(string $name): mixed` | Read a parsed or default argument value | - | `log(string $level, string $message)` | Structured log — levels: INFO SUCCESS WARNING ERROR DEBUG | - | `error(string $message, int $code = 1): never` | Log error and exit | - | `$this->dryRun` | `true` when `--dry-run` is passed | - | `$this->verbose` | `true` when `--verbose` / `-v` is passed | - - **Forbidden patterns in PHP:** - - ```php - // ❌ Wrong — legacy base class, not namespaced - class MyScript extends CliBase { … } - - // ❌ Wrong — standalone class with no framework - class MyScript { public function run() { … } } - - // ❌ Wrong — method names and entry-point transposed - protected function execute(): int { … } // should be run() - exit($script->run()); // should be execute() - - // ✅ Correct - class MyScript extends CliFramework { - protected function configure(): void { … } - protected function run(): int { … } - } - $script = new MyScript('name', 'description'); - exit($script->execute()); - ``` - - --- - - # 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 to all badges and `FILE INFORMATION` headers automatically on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in the `README.md` `FILE INFORMATION` block governs all other version references. - - Update `README.md` only — the `sync-version-on-merge` workflow propagates it to all badges and `FILE INFORMATION` headers automatically on merge to `main`. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - ## Minimal header - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - declare(strict_types=1); - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$user_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `UserService.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `code-quality.yml` | - | Markdown doc | `kebab-case.md` | `coding-style-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow in this repository must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct — always use GH_TOKEN - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale. - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class | - | New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent | - | New or changed GitHub Actions workflow | `docs/workflows/.md` | - | New or changed policy | Corresponding file under `docs/policy/` | - | New library class or major feature | `CHANGELOG.md` entry under `Added` | - | Bug fix | `CHANGELOG.md` entry under `Fixed` | - | Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change | - | Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block | - | **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge | - - If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR. - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **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` instead. - - **Never use `exit($script->run())`** — the correct entry point is `exit($script->execute())`. - - --- - - # Key Policy Documents (MokoStandards) - - | 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 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 | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "suggested" - files = [ - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/codeql-analysis.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-project)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/default/generic.tf b/definitions/default/generic.tf deleted file mode 100644 index 1d2caa7..0000000 --- a/definitions/default/generic.tf +++ /dev/null @@ -1,637 +0,0 @@ -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - }, - { - name = "renovate.json" - extension = "json" - description = "Renovate dependency management configuration" - requirement_status = "required" - always_overwrite = false - audience = "developer" - template = "templates/configs/renovate.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".mokogitea" - path = ".mokogitea" - description = "Gitea-specific configuration and workflows" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows, manifest.xml, and CI/CD configuration" - subdirectories = [ - { - name = "workflows" - path = ".mokogitea/workflows" - description = "Gitea Actions workflows (universal)" - requirement_status = "required" - files = [ - { - name = "auto-bump.yml" - extension = "yml" - description = "Auto-bump patch version on push to dev" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-bump.yml" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Universal build and release pipeline on merge to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-release.yml" - }, - { - name = "branch-cleanup.yml" - extension = "yml" - description = "Auto-delete merged feature branches after PR merge" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/branch-cleanup.yml" - }, - { - name = "cascade-dev.yml" - extension = "yml" - description = "Forward-merge main to dev and pre-release branches on push to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cascade-dev.yml" - }, - { - name = "cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of retired workflows, stale branches, and old runs" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cleanup.yml" - }, - { - name = "gitleaks.yml" - extension = "yml" - description = "Secret scanning — detect leaked credentials, API keys, and tokens" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/gitleaks.yml" - }, - { - name = "issue-branch.yml" - extension = "yml" - description = "Auto-create feature branch from issue assignment" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/issue-branch.yml" - }, - { - name = "notify.yml" - extension = "yml" - description = "Notification workflow for release and CI events" - requirement_status = "suggested" - always_overwrite = true - template = ".mokogitea/workflows/notify.yml" - }, - { - name = "pr-check.yml" - extension = "yml" - description = "Pull request validation checks" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pr-check.yml" - }, - { - name = "pre-release.yml" - extension = "yml" - description = "Manual pre-release builds for dev/alpha/beta/rc channels" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pre-release.yml" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health checks and standards validation" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/repo-health.yml" - }, - { - name = "security-audit.yml" - extension = "yml" - description = "Dependency and security audit workflow" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/security-audit.yml" - }, - { - name = "update-server.yml" - extension = "yml" - description = "Update server XML feed with stability channel entries" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/update-server.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".mokogitea/ISSUE_TEMPLATE" - description = "Issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - files = [ - { - name = "manifest.xml" - extension = "xml" - description = "Repository manifest — version, platform, governance metadata" - requirement_status = "required" - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 0 - dismiss_stale_reviews = true - block_on_rejected_reviews = true - restrict_pushes = true - push_whitelist = ["jmiller"] - enable_force_push = true - force_push_whitelist = ["jmiller"] - enforce_admins = false - }, - { - branch_pattern = "dev" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "rc/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "beta/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "alpha/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/default/github-private-repository.tf b/definitions/default/github-private-repository.tf deleted file mode 100644 index a57a3b5..0000000 --- a/definitions/default/github-private-repository.tf +++ /dev/null @@ -1,331 +0,0 @@ -/** - * .github-private Repository Structure Definition - * Org-level private repository containing universal GitHub Actions workflows, - * helper scripts, and default issue templates for all governed repositories. - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - * - * NOTES - * ───── - * • GitHub reads ISSUE_TEMPLATE/ from this repo as org-wide defaults for any - * governed repo that does not supply its own templates. - * • Workflows in .github/workflows/ support both standalone execution and - * workflow_call so governed repos can invoke them as reusable workflows via - * `uses: mokoconsulting-tech/.github-private/.github/workflows/.yml@main`. - * • This repo is EXCLUDED from bulk-repo-sync — it manages its own content - * independently as GitHub's org-level defaults repo. - */ - -locals { - github_private_repository_structure = { - metadata = { - name = ".github-private" - description = "Private GitHub org defaults — universal workflows, issue templates, and helper scripts" - repository_type = "github-private" - platform = "github-private" - last_updated = "2026-03-12T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - visibility = "private" - sync_priority = -1 - exclude_from_sync = true - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Repository overview — purpose, contents, and how governed repos use this repo" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and private vulnerability reporting" - required = true - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - audience = "contributor" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - audience = "contributor" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Governance policy and decision-making process" - required = true - always_overwrite = true - audience = "general" - template = "templates/docs/required/GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - - directories = [ - { - name = "ISSUE_TEMPLATE" - path = "ISSUE_TEMPLATE" - description = "Org-default issue templates — applied to all governed repos without their own templates" - requirement_status = "required" - purpose = "GitHub reads ISSUE_TEMPLATE/ from this repo as org-wide defaults" - files = [ - { - name = "config.yml" - extension = "yml" - description = "Issue template chooser — disables blank issues and lists contact links" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/ISSUE_TEMPLATE/config.yml.template" - }, - { - name = "bug_report.md" - extension = "md" - description = "Bug report issue template" - requirement_status = "required" - always_overwrite = false - template = "templates/github-private/ISSUE_TEMPLATE/bug_report.md.template" - }, - { - name = "feature_request.md" - extension = "md" - description = "Feature request issue template" - requirement_status = "required" - always_overwrite = false - template = "templates/github-private/ISSUE_TEMPLATE/feature_request.md.template" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Helper scripts used by universal workflows and available as git hooks" - requirement_status = "required" - purpose = "Reusable Bash utilities for commit-message and PR-title validation" - files = [ - { - name = "check-pr-title.sh" - extension = "sh" - description = "Validates PR title follows conventional-commit format" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/scripts/check-pr-title.sh.template" - }, - { - name = "check-commit-msg.sh" - extension = "sh" - description = "Validates individual commit messages follow conventional-commit format; usable as a git commit-msg hook" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/scripts/check-commit-msg.sh.template" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration for .github-private itself" - requirement_status = "required" - purpose = "Contains CI workflows for this repo and reusable workflows callable org-wide" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "CI + universal reusable workflows; callable via uses: mokoconsulting-tech/.github-private/.github/workflows/.yml@main" - requirement_status = "required" - files = [ - { - name = "stale.yml" - extension = "yml" - description = "Marks stale issues and pull requests; standalone (schedule) and reusable (workflow_call)" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/workflows/stale.yml.template" - }, - { - name = "auto-assign.yml" - extension = "yml" - description = "Auto-assigns PR author and logs CODEOWNERS status; standalone and reusable" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/workflows/auto-assign.yml.template" - }, - { - name = "pr-labeler.yml" - extension = "yml" - description = "Labels PRs from branch name and validates PR title format; standalone and reusable" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/workflows/pr-labeler.yml.template" - }, - { - name = "welcome.yml" - extension = "yml" - description = "Posts welcome message on first-time contributor PRs and issues; standalone and reusable" - requirement_status = "required" - always_overwrite = true - template = "templates/github-private/workflows/welcome.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation — required for bulk sync and workflow execution" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PATH_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /.github-private)" - required = false - scope = "repo" - } - ] - - repository_settings = { - visibility = "private" - has_issues = true - has_projects = false - has_wiki = false - has_discussions = false - allow_squash_merge = true - allow_merge_commit = false - allow_rebase_merge = true - delete_branch_on_merge = true - } - } - } -} diff --git a/definitions/default/joomla.tf b/definitions/default/joomla.tf deleted file mode 100644 index 1e4e07e..0000000 --- a/definitions/default/joomla.tf +++ /dev/null @@ -1,693 +0,0 @@ -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "joomla" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; managed by release workflow, never overwritten by sync" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - - - https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip - - - https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip - - - - 8.1 - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - audience = "developer" - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - }, - { - name = "renovate.json" - extension = "json" - description = "Renovate dependency management configuration" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/renovate.json" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".mokogitea" - path = ".mokogitea" - description = "Gitea-specific configuration and workflows" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows, manifest.xml, and CI/CD configuration" - subdirectories = [ - { - name = "workflows" - path = ".mokogitea/workflows" - description = "Gitea Actions workflows (universal)" - requirement_status = "required" - files = [ - { - name = "auto-bump.yml" - extension = "yml" - description = "Auto-bump patch version on push to dev" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-bump.yml" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Universal build and release pipeline on merge to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-release.yml" - }, - { - name = "branch-cleanup.yml" - extension = "yml" - description = "Auto-delete merged feature branches after PR merge" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/branch-cleanup.yml" - }, - { - name = "cascade-dev.yml" - extension = "yml" - description = "Forward-merge main to dev and pre-release branches on push to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cascade-dev.yml" - }, - { - name = "cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of retired workflows, stale branches, and old runs" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cleanup.yml" - }, - { - name = "gitleaks.yml" - extension = "yml" - description = "Secret scanning — detect leaked credentials, API keys, and tokens" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/gitleaks.yml" - }, - { - name = "issue-branch.yml" - extension = "yml" - description = "Auto-create feature branch from issue assignment" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/issue-branch.yml" - }, - { - name = "notify.yml" - extension = "yml" - description = "Notification workflow for release and CI events" - requirement_status = "suggested" - always_overwrite = true - template = ".mokogitea/workflows/notify.yml" - }, - { - name = "pr-check.yml" - extension = "yml" - description = "Pull request validation checks" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pr-check.yml" - }, - { - name = "pre-release.yml" - extension = "yml" - description = "Manual pre-release builds for dev/alpha/beta/rc channels" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pre-release.yml" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health checks and standards validation" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/repo-health.yml" - }, - { - name = "security-audit.yml" - extension = "yml" - description = "Dependency and security audit workflow" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/security-audit.yml" - }, - { - name = "update-server.yml" - extension = "yml" - description = "Update server XML feed with stability channel entries" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/update-server.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".mokogitea/ISSUE_TEMPLATE" - description = "Issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - files = [ - { - name = "manifest.xml" - extension = "xml" - description = "Repository manifest — version, platform, governance metadata" - requirement_status = "required" - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/default/mcp-server.tf b/definitions/default/mcp-server.tf deleted file mode 100644 index a6a21b3..0000000 --- a/definitions/default/mcp-server.tf +++ /dev/null @@ -1,484 +0,0 @@ -/** - * MCP Server Repository Structure Definition - * Standard repository structure for Model Context Protocol (MCP) server projects - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MCP Server" - description = "Standard repository structure for Model Context Protocol (MCP) server projects — TypeScript/Node.js MCP servers that expose external APIs as AI assistant tools" - repository_type = "mcp-server" - platform = "mcp-server" - last_updated = "2026-05-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "04.06.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview with tool reference table, install, and configuration" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "package.json" - extension = "json" - description = "Node.js project manifest — @mokoconsulting scoped, MCP SDK + Zod dependencies" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "tsconfig.json" - extension = "json" - description = "TypeScript configuration — ES2022 target, Node16 module, strict mode" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "config.example.json" - extension = "json" - description = "Example multi-connection configuration file" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".gitmessage" - extension = "gitmessage" - description = "Conventional commit message template" - requirement_status = "required" - always_overwrite = true - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation — install, build, dev, clean, setup, start targets" - requirement_status = "required" - always_overwrite = false - audience = "developer" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "TypeScript source code" - requirement_status = "required" - purpose = "Contains MCP server entry point, API client, config loader, and type definitions" - files = [ - { - name = "index.ts" - extension = "ts" - description = "MCP server entry point — registers all API tools with McpServer" - requirement_status = "required" - }, - { - name = "client.ts" - extension = "ts" - description = "HTTP client wrapper for the target API (GET/POST/PUT/DELETE)" - requirement_status = "required" - }, - { - name = "config.ts" - extension = "ts" - description = "Configuration loader — reads ~/.{project}.json with multi-connection support" - requirement_status = "required" - }, - { - name = "types.ts" - extension = "ts" - description = "TypeScript interfaces for connection, config, and API response types" - requirement_status = "required" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Setup and utility scripts" - requirement_status = "required" - purpose = "Contains interactive setup wizard and repo-specific helpers" - files = [ - { - name = "setup.mjs" - extension = "mjs" - description = "Interactive setup wizard — prompts for API connection details and writes config" - requirement_status = "required" - always_overwrite = false - protected = true - } - ] - }, - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - } - ] - }, - { - name = ".gitea" - path = ".gitea" - description = "Gitea-specific configuration" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows and platform configuration" - files = [ - { - name = ".mokostandards" - description = "MokoStandards platform declaration — must contain 'platform: mcp-server'" - requirement_status = "required" - always_overwrite = false - } - ] - subdirectories = [ - { - name = "workflows" - path = ".gitea/workflows" - description = "Gitea Actions workflows" - requirement_status = "required" - files = [ - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create release on push to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "auto-assign.yml" - extension = "yml" - description = "Auto-assign issues and PRs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-assign.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/standards-compliance.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/codeql-analysis.yml.template" - }, - { - name = "changelog-validation.yml" - extension = "yml" - description = "CHANGELOG validation on PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/changelog-validation.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of stale branches and workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "Deployment to development server" - requirement_status = "suggested" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "Deployment to demo server on merge to main" - requirement_status = "suggested" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "copilot-agent.yml" - extension = "yml" - description = "Copilot agent workflow for automated code review" - requirement_status = "optional" - always_overwrite = true - template = "templates/workflows/shared/copilot-agent.yml.template" - }, - { - name = "mcp-build-test.yml" - extension = "yml" - description = "MCP server build validation — TypeScript compile, dist verification, tool count" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/mcp/mcp-build-test.yml.template" - }, - { - name = "mcp-sdk-check.yml" - extension = "yml" - description = "Weekly check for MCP SDK and Zod updates — creates issue when new version available" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/mcp/mcp-sdk-check.yml.template" - }, - { - name = "mcp-tool-inventory.yml" - extension = "yml" - description = "Generate tool inventory report on push to main" - requirement_status = "suggested" - always_overwrite = true - template = "templates/workflows/mcp/mcp-tool-inventory.yml.template" - } - ] - } - ] - }, - { - name = "dist" - path = "dist" - description = "Compiled JavaScript output (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level Gitea PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "Gitea Actions workflows" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "20" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - }, - { - name = "new-tool" - color = "5319e7" - description = "New MCP tool/endpoint to add" - }, - { - name = "api-change" - color = "fbca04" - description = "Upstream API changed — tool needs update" - } - ] - } - } -} diff --git a/definitions/default/platform.tf b/definitions/default/platform.tf deleted file mode 100644 index 527ffe0..0000000 --- a/definitions/default/platform.tf +++ /dev/null @@ -1,342 +0,0 @@ -/** - * Dolibarr Platform Structure Definition - * Standard repository structure for the full Dolibarr ERP/CRM installation - * - * This is distinct from dolibarr — it defines the ENTIRE Dolibarr platform - * (htdocs/, not src/). It does NOT have a module descriptor, numero, or - * publish-to-mokodolimods workflow. - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Dolibarr Platform" - description = "Full Dolibarr ERP/CRM installation — htdocs/ root, not a module" - repository_type = "platform" - platform = "dolibarr" - last_updated = "2026-03-31T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "LICENSE" - extension = "" - description = "GPL-3.0-or-later license file" - required = true - always_overwrite = true - template = "templates/docs/required/LICENSE" - }, - { - name = "composer.json" - extension = "json" - description = "Composer package definition" - required = true - always_overwrite = false - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis configuration" - required = true - always_overwrite = true - template = "templates/configs/phpstan.neon" - }, - { - name = "Makefile" - extension = "" - description = "Build automation targets" - required = true - always_overwrite = true - template = "templates/configs/Makefile" - }, - { - name = "src/.ftpignore" - extension = "" - description = "Files excluded from SFTP deployment" - required = true - always_overwrite = true - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "renovate.json" - extension = "json" - description = "Renovate dependency management configuration" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/renovate.json" - } - ] - - directories = [ - { - name = "htdocs" - path = "htdocs" - description = "Dolibarr web root — entire platform" - required = true - purpose = "Contains the full Dolibarr installation including core, custom modules, and themes" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation" - files = [ - { - name = "update-server.md" - extension = "md" - description = "Dolibarr update server (update.txt) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = ".mokogitea" - path = ".mokogitea" - description = "Gitea-specific configuration and workflows" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows, manifest.xml, and CI/CD configuration" - subdirectories = [ - { - name = "workflows" - path = ".mokogitea/workflows" - description = "Gitea Actions workflows (universal)" - requirement_status = "required" - files = [ - { - name = "auto-bump.yml" - extension = "yml" - description = "Auto-bump patch version on push to dev" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-bump.yml" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Universal build and release pipeline on merge to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-release.yml" - }, - { - name = "branch-cleanup.yml" - extension = "yml" - description = "Auto-delete merged feature branches after PR merge" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/branch-cleanup.yml" - }, - { - name = "cascade-dev.yml" - extension = "yml" - description = "Forward-merge main to dev and pre-release branches on push to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cascade-dev.yml" - }, - { - name = "cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of retired workflows, stale branches, and old runs" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cleanup.yml" - }, - { - name = "gitleaks.yml" - extension = "yml" - description = "Secret scanning — detect leaked credentials, API keys, and tokens" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/gitleaks.yml" - }, - { - name = "issue-branch.yml" - extension = "yml" - description = "Auto-create feature branch from issue assignment" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/issue-branch.yml" - }, - { - name = "notify.yml" - extension = "yml" - description = "Notification workflow for release and CI events" - requirement_status = "suggested" - always_overwrite = true - template = ".mokogitea/workflows/notify.yml" - }, - { - name = "pr-check.yml" - extension = "yml" - description = "Pull request validation checks" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pr-check.yml" - }, - { - name = "pre-release.yml" - extension = "yml" - description = "Manual pre-release builds for dev/alpha/beta/rc channels" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pre-release.yml" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health checks and standards validation" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/repo-health.yml" - }, - { - name = "security-audit.yml" - extension = "yml" - description = "Dependency and security audit workflow" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/security-audit.yml" - }, - { - name = "update-server.yml" - extension = "yml" - description = "Update server XML feed with stability channel entries" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/update-server.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".mokogitea/ISSUE_TEMPLATE" - description = "Issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - files = [ - { - name = "manifest.xml" - extension = "xml" - description = "Repository manifest — version, platform, governance metadata" - requirement_status = "required" - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - } - ] - } -} - -output "crm_platform_structure" { - description = "Dolibarr Platform repository structure definition" - value = local.repository_structure -} diff --git a/definitions/default/standards.tf b/definitions/default/standards.tf deleted file mode 100644 index 791f717..0000000 --- a/definitions/default/standards.tf +++ /dev/null @@ -1,748 +0,0 @@ -/** - * MokoStandards Repository Structure Definition - * Repository structure definition for the MokoStandards standards and templates repository - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoStandards Repository" - description = "Repository structure definition for MokoStandards - organizational standards, templates, and automation" - repository_type = "standards" - platform = "standards" - last_updated = "2026-03-03T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Repository overview and documentation" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - required = true - audience = "general" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = false - protected = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - always_overwrite = false - protected = true - audience = "contributor" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "CITATION.cff" - extension = "cff" - description = "Citation file format for academic references" - required = true - audience = "general" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".gitmessage" - extension = "gitmessage" - description = "Git commit message template" - required = true - audience = "developer" - }, - { - name = ".git-blame-ignore-revs" - extension = "git-blame-ignore-revs" - description = "Git blame ignore revisions" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".mailmap" - extension = "mailmap" - description = "Git mailmap for contributor attribution" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = ".eslintrc.json" - extension = "json" - description = "ESLint configuration for JavaScript" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".prettierrc.json" - extension = "json" - description = "Prettier configuration for code formatting" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".markdownlint.json" - extension = "json" - description = "Markdown linting configuration" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".yamllint" - extension = "yamllint" - description = "YAML linting configuration" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".pylintrc" - extension = "pylintrc" - description = "Python linting configuration" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".htmlhintrc" - extension = "htmlhintrc" - description = "HTML linting configuration" - requirement_status = "suggested" - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "PHP dependency management" - requirement_status = "suggested" - audience = "developer" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest — generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - requirement_status = "required" - always_overwrite = false - audience = "developer" - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "renovate.json" - extension = "json" - description = "Renovate dependency management configuration" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/renovate.json" - } - ] - - directories = [ - { - name = "api" - path = "api" - description = "API scripts and automation" - required = true - purpose = "Contains all operational scripts - validation, automation, build, release, etc." - subdirectories = [ - { - name = "validate" - path = "api/validate" - description = "Validation scripts" - required = true - purpose = "Scripts for validating repository structure, health, and compliance" - }, - { - name = "automation" - path = "api/automation" - description = "Automation scripts" - required = true - purpose = "Scripts for bulk operations and repository synchronization" - }, - { - name = "build" - path = "api/build" - description = "Build scripts" - requirement_status = "suggested" - purpose = "Scripts for building and packaging" - }, - { - name = "release" - path = "api/release" - description = "Release scripts" - requirement_status = "suggested" - purpose = "Scripts for release management" - }, - { - name = "tests" - path = "api/tests" - description = "Test scripts" - requirement_status = "suggested" - purpose = "Test scripts and test data" - }, - { - name = "maintenance" - path = "api/maintenance" - description = "Maintenance scripts" - requirement_status = "suggested" - purpose = "Scripts for repository maintenance tasks" - }, - { - name = "definitions" - path = "api/definitions" - description = "Repository structure definitions" - required = true - purpose = "HCL/Terraform definition files for different repository types" - }, - { - name = "lib" - path = "api/lib" - description = "Shared libraries" - requirement_status = "suggested" - purpose = "Shared code libraries and utilities" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Documentation" - required = true - purpose = "Comprehensive documentation for standards, guides, policies, and references" - subdirectories = [ - { - name = "guide" - path = "docs/guide" - description = "User guides" - requirement_status = "suggested" - }, - { - name = "reference" - path = "docs/reference" - description = "Reference documentation" - requirement_status = "suggested" - }, - { - name = "policy" - path = "docs/policy" - description = "Policies and standards" - requirement_status = "suggested" - }, - { - name = "workflows" - path = "docs/workflows" - description = "Workflow documentation" - requirement_status = "suggested" - }, - { - name = "security" - path = "docs/security" - description = "Security documentation" - requirement_status = "suggested" - }, - { - name = "development" - path = "docs/development" - description = "Development documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files" - required = true - purpose = "Template files for workflows, configs, documentation, and projects" - subdirectories = [ - { - name = "workflows" - path = "templates/workflows" - description = "GitHub Actions workflow templates" - required = true - }, - { - name = "github" - path = "templates/github" - description = "GitHub configuration templates" - required = true - }, - { - name = "docs" - path = "templates/docs" - description = "Documentation templates" - requirement_status = "suggested" - }, - { - name = "configs" - path = "templates/configs" - description = "Configuration file templates" - requirement_status = "suggested" - }, - { - name = "licenses" - path = "templates/licenses" - description = "License templates" - requirement_status = "suggested" - }, - { - name = "projects" - path = "templates/projects" - description = "Project definition templates" - requirement_status = "suggested" - }, - { - name = "terraform" - path = "templates/terraform" - description = "Terraform configuration templates" - requirement_status = "suggested" - }, - { - name = "scripts" - path = "templates/scripts" - description = "Script templates" - requirement_status = "suggested" - } - ] - }, - { - name = "logs" - path = "logs" - description = "Log files" - requirement_status = "suggested" - purpose = "Storage for operation logs, audit trails, and metrics" - subdirectories = [ - { - name = "audit" - path = "logs/audit" - description = "Audit logs" - requirement_status = "suggested" - }, - { - name = "automation" - path = "logs/automation" - description = "Automation logs" - requirement_status = "suggested" - }, - { - name = "validation" - path = "logs/validation" - description = "Validation logs" - requirement_status = "suggested" - } - ] - }, - { - name = ".mokogitea" - path = ".mokogitea" - description = "Gitea-specific configuration and workflows" - requirement_status = "required" - purpose = "Contains Gitea Actions workflows, manifest.xml, and CI/CD configuration" - subdirectories = [ - { - name = "workflows" - path = ".mokogitea/workflows" - description = "Gitea Actions workflows (universal)" - requirement_status = "required" - files = [ - { - name = "auto-bump.yml" - extension = "yml" - description = "Auto-bump patch version on push to dev" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-bump.yml" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Universal build and release pipeline on merge to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/auto-release.yml" - }, - { - name = "branch-cleanup.yml" - extension = "yml" - description = "Auto-delete merged feature branches after PR merge" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/branch-cleanup.yml" - }, - { - name = "cascade-dev.yml" - extension = "yml" - description = "Forward-merge main to dev and pre-release branches on push to main" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cascade-dev.yml" - }, - { - name = "cleanup.yml" - extension = "yml" - description = "Scheduled cleanup of retired workflows, stale branches, and old runs" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/cleanup.yml" - }, - { - name = "gitleaks.yml" - extension = "yml" - description = "Secret scanning — detect leaked credentials, API keys, and tokens" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/gitleaks.yml" - }, - { - name = "issue-branch.yml" - extension = "yml" - description = "Auto-create feature branch from issue assignment" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/issue-branch.yml" - }, - { - name = "notify.yml" - extension = "yml" - description = "Notification workflow for release and CI events" - requirement_status = "suggested" - always_overwrite = true - template = ".mokogitea/workflows/notify.yml" - }, - { - name = "pr-check.yml" - extension = "yml" - description = "Pull request validation checks" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pr-check.yml" - }, - { - name = "pre-release.yml" - extension = "yml" - description = "Manual pre-release builds for dev/alpha/beta/rc channels" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/pre-release.yml" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health checks and standards validation" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/repo-health.yml" - }, - { - name = "security-audit.yml" - extension = "yml" - description = "Dependency and security audit workflow" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/security-audit.yml" - }, - { - name = "update-server.yml" - extension = "yml" - description = "Update server XML feed with stability channel entries" - requirement_status = "required" - always_overwrite = true - template = ".mokogitea/workflows/update-server.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".mokogitea/ISSUE_TEMPLATE" - description = "Issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - files = [ - { - name = "manifest.xml" - extension = "xml" - description = "Repository manifest — version, platform, governance metadata" - requirement_status = "required" - always_overwrite = false - template = "managed-by-sync" - source_type = "programmatic" - } - ] - }, - { - name = ".checkpoints" - path = ".checkpoints" - description = "Checkpoint files for long-running operations" - requirement_status = "optional" - purpose = "Stores checkpoint data for resumable operations" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation — configure in org Actions secrets" - required = true - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "STANDARDS_VERSION" - description = "Current MokoStandards version" - required = false - }, - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /mokostandards)" - required = false - scope = "repo" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 0 - dismiss_stale_reviews = true - block_on_rejected_reviews = true - restrict_pushes = true - push_whitelist = ["jmiller"] - enable_force_push = true - force_push_whitelist = ["jmiller"] - enforce_admins = false - }, - { - branch_pattern = "dev" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "rc/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "beta/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - }, - { - branch_pattern = "alpha/*" - require_pull_request = false - required_approvals = 0 - restrict_pushes = false - enable_force_push = true - force_push_whitelist = ["jmiller"] - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = true - allow_squash_merge = true - allow_merge_commit = false - allow_rebase_merge = true - delete_branch_on_merge = true - } - - labels = [ - { name = "bulk-sync-success", color = "0e8a16", description = "Bulk sync completed successfully" }, - { name = "bulk-sync-failure", color = "d73a4a", description = "Bulk sync failed" }, - { name = "standards-update", color = "fbca04", description = "Standards update" }, - { name = "template-update", color = "d4c5f9", description = "Template file update" }, - { name = "documentation", color = "0075ca", description = "Documentation changes" }, - { name = "automation", color = "5319e7", description = "Automation scripts" } - ] - } - } -} diff --git a/definitions/index.md b/definitions/index.md deleted file mode 100644 index 829bb18..0000000 --- a/definitions/index.md +++ /dev/null @@ -1,31 +0,0 @@ - - -# Docs Index: /api/definitions - -## Purpose - -This index provides navigation to documentation within this folder. - -## Documents - -- [README](./README.md) - -## Metadata - -- **Document Type:** index -- **Auto-generated:** This file is automatically generated by rebuild_indexes.py - -## Revision History - -| Date | Author | Change | Notes | -| ---------- | ------------------ | ----------------- | ------------------------------------------ | -| Auto | rebuild_indexes.py | Automated update | Generated by documentation index automation | diff --git a/definitions/sync/.github-private.def.tf b/definitions/sync/.github-private.def.tf deleted file mode 100644 index 1f42b57..0000000 --- a/definitions/sync/.github-private.def.tf +++ /dev/null @@ -1,682 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/.github-private - * - * Auto-generated by MokoStandards bulk sync on 2026-03-24T19:30:16+00:00 - * Platform : default-repository - * Description: This is the private organization-level configuration repository for mokoconsulting-tech. It provides centralized community health files, templates, and standards that apply across all private repositories in the organization. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/.github-private" - default_branch = "main" - detected_platform = "default-repository" - description = "This is the private organization-level configuration repository for mokoconsulting-tech. It provides centralized community health files, templates, and standards that apply across all private repositories in the organization." - sync_timestamp = "2026-03-24T19:30:16+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 39 - created_files = 0 - updated_files = 28 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/ci.yml" action = "updated" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/ci.yml" action = "updated" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/repo-health.yml" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/repo-health.yml" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci.yml" - extension = "yml" - description = "Continuous integration workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "ci.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "ci.yml" - create_path = true - template = "templates/workflows/generic/ci.yml.template" - }, - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health monitoring" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "repo_health.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "repo-health.yml" - create_path = true - template = "templates/workflows/generic/repo_health.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/.github.def.tf b/definitions/sync/.github.def.tf deleted file mode 100644 index d0018d5..0000000 --- a/definitions/sync/.github.def.tf +++ /dev/null @@ -1,733 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/.github - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T21:05:55+00:00 - * Platform : default-repository - * Description: - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/.github" - default_branch = "main" - detected_platform = "default-repository" - description = "" - sync_timestamp = "2026-04-02T21:05:55+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 42 - updated_files = 5 - skipped_files = 6 - } - - synced_files = [ - { path = "LICENSE" action = "created" }, - { path = "CONTRIBUTING.md" action = "created" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "created" }, - { path = "ROADMAP.md" action = "created" }, - { path = "Makefile" action = "created" }, - { path = "composer.json" action = "created" }, - { path = "docs/index.md" action = "created" }, - { path = "docs/INSTALLATION.md" action = "created" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "created" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "created" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/workflows/deploy-dev.yml" action = "created" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "created" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "created" }, - { path = ".github/CODEOWNERS" action = "created" }, - { path = "composer.json" action = "enterprise dependency added" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/.gitkeep b/definitions/sync/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/definitions/sync/Copy-PortablePath.def.tf b/definitions/sync/Copy-PortablePath.def.tf deleted file mode 100644 index 4db368a..0000000 --- a/definitions/sync/Copy-PortablePath.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/Copy-PortablePath - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:20:12+00:00 - * Platform : default-repository - * Description: Copy Portable Path is a lightweight PowerShell utility that adds two context menu items to Windows Explorer — Copy Relative Path and Copy Absolute Path — both using forward slashes for cross-platform compatibility. Supports multiple selections, optional MSYS/WSL /c/... style, and installs per-user without admin rights. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/Copy-PortablePath" - default_branch = "main" - detected_platform = "default-repository" - description = "Copy Portable Path is a lightweight PowerShell utility that adds two context menu items to Windows Explorer — Copy Relative Path and Copy Absolute Path — both using forward slashes for cross-platform compatibility. Supports multiple selections, optional MSYS/WSL /c/... style, and installs per-user without admin rights." - sync_timestamp = "2026-04-02T15:20:12+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/Copy-PortablePath/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/DoliMods.def.tf b/definitions/sync/DoliMods.def.tf deleted file mode 100644 index 14ee660..0000000 --- a/definitions/sync/DoliMods.def.tf +++ /dev/null @@ -1,1333 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/DoliMods - * - * Auto-generated by MokoStandards bulk sync on 2026-03-30T07:47:30+00:00 - * Platform : crm-module - * Description: The DoliMods is the repository of the Dolibarr ERP CRM modules, developed by the DoliCloud.com team. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/DoliMods" - default_branch = "master" - detected_platform = "crm-module" - description = "The DoliMods is the repository of the Dolibarr ERP CRM modules, developed by the DoliCloud.com team." - sync_timestamp = "2026-03-30T07:47:30+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 44 - created_files = 1 - updated_files = 38 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "updated" }, - { path = "docs/update-server.md" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = "update.txt" action = "updated" }, - { path = "composer.json" action = "enterprise dependency added" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoCRM.def.tf b/definitions/sync/MokoCRM.def.tf deleted file mode 100644 index a14d6be..0000000 --- a/definitions/sync/MokoCRM.def.tf +++ /dev/null @@ -1,1335 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoCRM - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:41:53+00:00 - * Platform : crm-module - * Description: White-label CRM module for Dolibarr ERP Rebrands Dolibarr as **MokoCRM** and adds CRM-specific extrafields, dictionaries, email templates, and admin tools — all without modifying Dolibarr core. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoCRM" - default_branch = "main" - detected_platform = "crm-module" - description = "White-label CRM module for Dolibarr ERP Rebrands Dolibarr as **MokoCRM** and adds CRM-specific extrafields, dictionaries, email templates, and admin tools — all without modifying Dolibarr core." - sync_timestamp = "2026-04-02T15:41:53+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 1 - updated_files = 39 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "updated" }, - { path = "composer.json" action = "enterprise dependency added" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoCassiopeia.def.tf b/definitions/sync/MokoCassiopeia.def.tf deleted file mode 100644 index b77616e..0000000 --- a/definitions/sync/MokoCassiopeia.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoCassiopeia - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:18:42+00:00 - * Platform : waas-component - * Description: A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoCassiopeia" - default_branch = "main" - detected_platform = "waas-component" - description = "A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks." - sync_timestamp = "2026-04-02T15:18:42+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 2 - updated_files = 36 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliAdInsights.def.tf b/definitions/sync/MokoDoliAdInsights.def.tf deleted file mode 100644 index ab1018b..0000000 --- a/definitions/sync/MokoDoliAdInsights.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliAdInsights - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:37:10+00:00 - * Platform : crm-module - * Description: A Dolibarr module used to bridge multiple advertising services (Google Ads, Meta Ads, LinkedIn Ads, etc.) reporting with Claude AI analysis - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliAdInsights" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module used to bridge multiple advertising services (Google Ads, Meta Ads, LinkedIn Ads, etc.) reporting with Claude AI analysis" - sync_timestamp = "2026-04-02T15:37:10+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliArt.def.tf b/definitions/sync/MokoDoliArt.def.tf deleted file mode 100644 index 9674ee1..0000000 --- a/definitions/sync/MokoDoliArt.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliArt - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:38:24+00:00 - * Platform : crm-module - * Description: A Dolibarr module used to send proofs of art to clients for approval. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliArt" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module used to send proofs of art to clients for approval." - sync_timestamp = "2026-04-02T15:38:24+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliAuth.def.tf b/definitions/sync/MokoDoliAuth.def.tf deleted file mode 100644 index 2af8989..0000000 --- a/definitions/sync/MokoDoliAuth.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliAuth - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:27:06+00:00 - * Platform : crm-module - * Description: A Dolibarr authentication suite - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliAuth" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr authentication suite" - sync_timestamp = "2026-04-02T15:27:06+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 6 - updated_files = 34 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "created" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliCare.def.tf b/definitions/sync/MokoDoliCare.def.tf deleted file mode 100644 index aa0e90c..0000000 --- a/definitions/sync/MokoDoliCare.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliCare - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:34:55+00:00 - * Platform : crm-module - * Description: A childcare management software built on Dolibarr. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliCare" - default_branch = "main" - detected_platform = "crm-module" - description = "A childcare management software built on Dolibarr." - sync_timestamp = "2026-04-02T15:34:55+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliChimp.def.tf b/definitions/sync/MokoDoliChimp.def.tf deleted file mode 100644 index 735b0a4..0000000 --- a/definitions/sync/MokoDoliChimp.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliChimp - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:20:54+00:00 - * Platform : crm-module - * Description: - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliChimp" - default_branch = "main" - detected_platform = "crm-module" - description = "" - sync_timestamp = "2026-04-02T15:20:54+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliClaude.def.tf b/definitions/sync/MokoDoliClaude.def.tf deleted file mode 100644 index 0f6893f..0000000 --- a/definitions/sync/MokoDoliClaude.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliClaude - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:39:01+00:00 - * Platform : crm-module - * Description: A connector for Dolibarr and Claude - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliClaude" - default_branch = "main" - detected_platform = "crm-module" - description = "A connector for Dolibarr and Claude" - sync_timestamp = "2026-04-02T15:39:01+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliCredits.def.tf b/definitions/sync/MokoDoliCredits.def.tf deleted file mode 100644 index b1a9e01..0000000 --- a/definitions/sync/MokoDoliCredits.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliCredits - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:32:33+00:00 - * Platform : crm-module - * Description: - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliCredits" - default_branch = "main" - detected_platform = "crm-module" - description = "" - sync_timestamp = "2026-04-02T15:32:33+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliDymo.def.tf b/definitions/sync/MokoDoliDymo.def.tf deleted file mode 100644 index cfa3fa2..0000000 --- a/definitions/sync/MokoDoliDymo.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliDymo - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T21:06:43+00:00 - * Platform : crm-module - * Description: A module to design label documents for Dymo LabelWriter - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliDymo" - default_branch = "main" - detected_platform = "crm-module" - description = "A module to design label documents for Dymo LabelWriter" - sync_timestamp = "2026-04-02T21:06:43+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 12 - updated_files = 28 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "created" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "created" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliForm.def.tf b/definitions/sync/MokoDoliForm.def.tf deleted file mode 100644 index 5cc9646..0000000 --- a/definitions/sync/MokoDoliForm.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliForm - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:22:50+00:00 - * Platform : crm-module - * Description: MokoDoliForm is a Dolibarr module that automates client onboarding by creating a Customer third party, a primary Contact, and a Ticket in a single atomic transaction. It also includes a public-facing form with a customizable template and CSS, powered by a dedicated service account for external submissions. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliForm" - default_branch = "main" - detected_platform = "crm-module" - description = "MokoDoliForm is a Dolibarr module that automates client onboarding by creating a Customer third party, a primary Contact, and a Ticket in a single atomic transaction. It also includes a public-facing form with a customizable template and CSS, powered by a dedicated service account for external submissions." - sync_timestamp = "2026-04-02T15:22:50+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliG.def.tf b/definitions/sync/MokoDoliG.def.tf deleted file mode 100644 index 0ca343c..0000000 --- a/definitions/sync/MokoDoliG.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliG - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:24:00+00:00 - * Platform : crm-module - * Description: A Dolibarr module to extend the interface to Google Workspace. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliG" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module to extend the interface to Google Workspace." - sync_timestamp = "2026-04-02T15:24:00+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliGithub.def.tf b/definitions/sync/MokoDoliGithub.def.tf deleted file mode 100644 index 396aa7b..0000000 --- a/definitions/sync/MokoDoliGithub.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliGithub - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:44:27+00:00 - * Platform : crm-module - * Description: A Dolibarr module to bridge to Github - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliGithub" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module to bridge to Github" - sync_timestamp = "2026-04-02T15:44:27+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliHRM.def.tf b/definitions/sync/MokoDoliHRM.def.tf deleted file mode 100644 index 64032b0..0000000 --- a/definitions/sync/MokoDoliHRM.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliHRM - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:25:55+00:00 - * Platform : crm-module - * Description: - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliHRM" - default_branch = "main" - detected_platform = "crm-module" - description = "" - sync_timestamp = "2026-04-02T15:25:55+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 6 - updated_files = 34 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "created" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliMods.def.tf b/definitions/sync/MokoDoliMods.def.tf deleted file mode 100644 index 768ab50..0000000 --- a/definitions/sync/MokoDoliMods.def.tf +++ /dev/null @@ -1,400 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliMods - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:19:29+00:00 - * Platform : crm-platform - * Description: The DoliMods is the repository of the Dolibarr ERP CRM modules, developed by the DoliCloud.com team. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-platform.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliMods" - default_branch = "main" - detected_platform = "crm-platform" - description = "The DoliMods is the repository of the Dolibarr ERP CRM modules, developed by the DoliCloud.com team." - sync_timestamp = "2026-04-02T15:19:29+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-platform.tf" - } - - sync_stats = { - total_files = 53 - created_files = 3 - updated_files = 40 - skipped_files = 10 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/deploy-dev.yml" action = "updated" }, - { path = ".github/deploy-demo.yml" action = "updated" }, - { path = ".github/deploy-rs.yml" action = "updated" }, - { path = ".github/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/auto-release.yml" action = "updated" }, - { path = ".github/repository-cleanup.yml" action = "updated" }, - { path = ".github/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoDoliMods/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Dolibarr Platform Structure Definition - * Standard repository structure for the full Dolibarr ERP/CRM installation - * - * This is distinct from crm-module — it defines the ENTIRE Dolibarr platform - * (htdocs/, not src/). It does NOT have a module descriptor, numero, or - * publish-to-mokodolimods workflow. - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Dolibarr Platform" - description = "Full Dolibarr ERP/CRM installation — htdocs/ root, not a module" - repository_type = "crm-platform" - platform = "dolibarr" - last_updated = "2026-03-31T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "LICENSE" - extension = "" - description = "GPL-3.0-or-later license file" - required = true - always_overwrite = true - template = "templates/docs/required/LICENSE" - }, - { - name = "composer.json" - extension = "json" - description = "Composer package definition" - required = true - always_overwrite = false - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis configuration" - required = true - always_overwrite = true - template = "templates/configs/phpstan.neon" - }, - { - name = "Makefile" - extension = "" - description = "Build automation targets" - required = true - always_overwrite = true - template = "templates/configs/Makefile" - }, - { - name = "src/.ftpignore" - extension = "" - description = "Files excluded from SFTP deployment" - required = true - always_overwrite = true - template = "templates/configs/ftp_ignore" - }, - { - name = ".mokostandards" - extension = "" - description = "MokoStandards platform identifier" - required = true - always_overwrite = true - template = "templates/configs/mokostandards.yml.template" - } - ] - - directories = [ - { - name = "htdocs" - path = "htdocs" - description = "Dolibarr web root — entire platform" - required = true - purpose = "Contains the full Dolibarr installation including core, custom modules, and themes" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation" - files = [ - { - name = "update-server.md" - extension = "md" - description = "Dolibarr update server (update.txt) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub configuration" - required = true - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment to dev server (htdocs/)" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment to demo server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment to release staging server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on minor version" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: retired workflows, stale branches" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue on dev/rc branch creation" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr platform health checks (shared guardrails, no module-specific checks)" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - } - ] - } -} - -output "crm_platform_structure" { - description = "Dolibarr Platform repository structure definition" - value = local.repository_structure -} diff --git a/definitions/sync/MokoDoliMulti.def.tf b/definitions/sync/MokoDoliMulti.def.tf deleted file mode 100644 index 0fdf2b2..0000000 --- a/definitions/sync/MokoDoliMulti.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliMulti - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:21:37+00:00 - * Platform : crm-module - * Description: Domain‑based multi‑tenant orchestration for Dolibarr using one codebase and per‑tenant configuration, documents, and databases mapped by virtual host. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliMulti" - default_branch = "main" - detected_platform = "crm-module" - description = "Domain‑based multi‑tenant orchestration for Dolibarr using one codebase and per‑tenant configuration, documents, and databases mapped by virtual host." - sync_timestamp = "2026-04-02T15:21:37+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliOffline.def.tf b/definitions/sync/MokoDoliOffline.def.tf deleted file mode 100644 index 099b0bc..0000000 --- a/definitions/sync/MokoDoliOffline.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliOffline - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:26:31+00:00 - * Platform : crm-module - * Description: A Dolibarr module enabling offline mode and PWA. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliOffline" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module enabling offline mode and PWA." - sync_timestamp = "2026-04-02T15:26:31+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliPhone.com.def.tf b/definitions/sync/MokoDoliPhone.com.def.tf deleted file mode 100644 index d3a37c3..0000000 --- a/definitions/sync/MokoDoliPhone.com.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliPhone.com - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:43:53+00:00 - * Platform : crm-module - * Description: A Dolibarr module to bridge to Phone.com service - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliPhone.com" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module to bridge to Phone.com service" - sync_timestamp = "2026-04-02T15:43:53+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliProjTemplate.def.tf b/definitions/sync/MokoDoliProjTemplate.def.tf deleted file mode 100644 index 99aaf15..0000000 --- a/definitions/sync/MokoDoliProjTemplate.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliProjTemplate - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:37:44+00:00 - * Platform : crm-module - * Description: A Dolibarr module designed to provide project templates. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliProjTemplate" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module designed to provide project templates." - sync_timestamp = "2026-04-02T15:37:44+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliRelease.def.tf b/definitions/sync/MokoDoliRelease.def.tf deleted file mode 100644 index fffe5dc..0000000 --- a/definitions/sync/MokoDoliRelease.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliRelease - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:24:35+00:00 - * Platform : crm-module - * Description: A Dolibarr module for monitoring and managing remote deployments, software releases, and license keys for Dolibarr and Joomla installations. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliRelease" - default_branch = "main" - detected_platform = "crm-module" - description = "A Dolibarr module for monitoring and managing remote deployments, software releases, and license keys for Dolibarr and Joomla installations." - sync_timestamp = "2026-04-02T15:24:35+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliSign.def.tf b/definitions/sync/MokoDoliSign.def.tf deleted file mode 100644 index 2ffede7..0000000 --- a/definitions/sync/MokoDoliSign.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliSign - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:22:14+00:00 - * Platform : crm-module - * Description: MokoDoliSign is a Dolibarr module that adds secure electronic signature functionality into your - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliSign" - default_branch = "main" - detected_platform = "crm-module" - description = "MokoDoliSign is a Dolibarr module that adds secure electronic signature functionality into your " - sync_timestamp = "2026-04-02T15:22:14+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliTools.def.tf b/definitions/sync/MokoDoliTools.def.tf deleted file mode 100644 index de4aa3c..0000000 --- a/definitions/sync/MokoDoliTools.def.tf +++ /dev/null @@ -1,1255 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliTools - * - * Auto-generated by MokoStandards bulk sync on 2026-03-26T23:14:46+00:00 - * Platform : crm-module - * Description: MokoDoliTools extends Dolibarr with curated defaults, a lightweight UI layer, and an admin toolkit. It adds Setup, Tools (Secure & Repair, Health Checks, Environment Info), and DBAdmin pages; supports entity-aware visibility; ships with en_US only; and emphasizes safe-by-default operations for multi-entity deployments. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliTools" - default_branch = "main" - detected_platform = "crm-module" - description = "MokoDoliTools extends Dolibarr with curated defaults, a lightweight UI layer, and an admin toolkit. It adds Setup, Tools (Secure & Repair, Health Checks, Environment Info), and DBAdmin pages; supports entity-aware visibility; ships with en_US only; and emphasizes safe-by-default operations for multi-entity deployments." - sync_timestamp = "2026-03-26T23:14:46+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 37 - created_files = 5 - updated_files = 28 - skipped_files = 4 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "created" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - ```php - // In src/core/modules/mod{{MODULE_CLASS}}.class.php - public $version = '01.02.04'; // Must match README.md version - ``` - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - } - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "One-time cleanup: reset labels, strip issue template headers, delete old branches — self-deletes after run" - requirement_status = "suggested" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDoliTraining.def.tf b/definitions/sync/MokoDoliTraining.def.tf deleted file mode 100644 index c4a711b..0000000 --- a/definitions/sync/MokoDoliTraining.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDoliTraining - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:43:21+00:00 - * Platform : crm-module - * Description: A deployable module to install training data into Dolibarr and reset on command. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDoliTraining" - default_branch = "main" - detected_platform = "crm-module" - description = "A deployable module to install training data into Dolibarr and reset on command." - sync_timestamp = "2026-04-02T15:43:21+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 5 - updated_files = 35 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "created" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoDolibarr.def.tf b/definitions/sync/MokoDolibarr.def.tf deleted file mode 100644 index 7b521f3..0000000 --- a/definitions/sync/MokoDolibarr.def.tf +++ /dev/null @@ -1,400 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoDolibarr - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:42:39+00:00 - * Platform : crm-platform - * Description: Dolibarr ERP CRM is a modern software package to manage your company or foundation\'s activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). it\'s an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-platform.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoDolibarr" - default_branch = "main" - detected_platform = "crm-platform" - description = "Dolibarr ERP CRM is a modern software package to manage your company or foundation\'s activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). it\'s an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers." - sync_timestamp = "2026-04-02T15:42:39+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-platform.tf" - } - - sync_stats = { - total_files = 53 - created_files = 16 - updated_files = 29 - skipped_files = 8 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "CONTRIBUTING.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "created" }, - { path = "ROADMAP.md" action = "created" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "created" }, - { path = "docs/INSTALLATION.md" action = "created" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoDolibarr/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Dolibarr Platform Structure Definition - * Standard repository structure for the full Dolibarr ERP/CRM installation - * - * This is distinct from crm-module — it defines the ENTIRE Dolibarr platform - * (htdocs/, not src/). It does NOT have a module descriptor, numero, or - * publish-to-mokodolimods workflow. - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Dolibarr Platform" - description = "Full Dolibarr ERP/CRM installation — htdocs/ root, not a module" - repository_type = "crm-platform" - platform = "dolibarr" - last_updated = "2026-03-31T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "LICENSE" - extension = "" - description = "GPL-3.0-or-later license file" - required = true - always_overwrite = true - template = "templates/docs/required/LICENSE" - }, - { - name = "composer.json" - extension = "json" - description = "Composer package definition" - required = true - always_overwrite = false - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis configuration" - required = true - always_overwrite = true - template = "templates/configs/phpstan.neon" - }, - { - name = "Makefile" - extension = "" - description = "Build automation targets" - required = true - always_overwrite = true - template = "templates/configs/Makefile" - }, - { - name = "src/.ftpignore" - extension = "" - description = "Files excluded from SFTP deployment" - required = true - always_overwrite = true - template = "templates/configs/ftp_ignore" - }, - { - name = ".mokostandards" - extension = "" - description = "MokoStandards platform identifier" - required = true - always_overwrite = true - template = "templates/configs/mokostandards.yml.template" - } - ] - - directories = [ - { - name = "htdocs" - path = "htdocs" - description = "Dolibarr web root — entire platform" - required = true - purpose = "Contains the full Dolibarr installation including core, custom modules, and themes" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation" - files = [ - { - name = "update-server.md" - extension = "md" - description = "Dolibarr update server (update.txt) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub configuration" - required = true - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment to dev server (htdocs/)" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment to demo server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment to release staging server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on minor version" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: retired workflows, stale branches" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue on dev/rc branch creation" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr platform health checks (shared guardrails, no module-specific checks)" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - } - ] - } -} - -output "crm_platform_structure" { - description = "Dolibarr Platform repository structure definition" - value = local.repository_structure -} diff --git a/definitions/sync/MokoISOUpdatePortable.def.tf b/definitions/sync/MokoISOUpdatePortable.def.tf deleted file mode 100644 index d3352bd..0000000 --- a/definitions/sync/MokoISOUpdatePortable.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoISOUpdatePortable - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:33:45+00:00 - * Platform : default-repository - * Description: A PortableApp that keeps ISOs of selected systems up to date. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoISOUpdatePortable" - default_branch = "main" - detected_platform = "default-repository" - description = "A PortableApp that keeps ISOs of selected systems up to date." - sync_timestamp = "2026-04-02T15:33:45+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoISOUpdatePortable/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/MokoJoomHero.def.tf b/definitions/sync/MokoJoomHero.def.tf deleted file mode 100644 index 5cea674..0000000 --- a/definitions/sync/MokoJoomHero.def.tf +++ /dev/null @@ -1,1333 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoJoomHero - * - * Auto-generated by MokoStandards bulk sync on 2026-03-31T12:31:52+00:00 - * Platform : waas-component - * Description: A Joomla Module designed to provide a random image from a folder with content on top as a Hero. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoJoomHero" - default_branch = "main" - detected_platform = "waas-component" - description = "A Joomla Module designed to provide a random image from a folder with content on top as a Hero." - sync_timestamp = "2026-03-31T12:31:52+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 40 - created_files = 9 - updated_files = 28 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoJoomTOS.def.tf b/definitions/sync/MokoJoomTOS.def.tf deleted file mode 100644 index 0d69bd6..0000000 --- a/definitions/sync/MokoJoomTOS.def.tf +++ /dev/null @@ -1,1333 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoJoomTOS - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:35:55+00:00 - * Platform : waas-component - * Description: A component to present a sites Term of Service and privacy policy even through offline. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoJoomTOS" - default_branch = "main" - detected_platform = "waas-component" - description = "A component to present a sites Term of Service and privacy policy even through offline." - sync_timestamp = "2026-04-02T15:35:55+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 0 - updated_files = 38 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "updated" }, - { path = "docs/update-server.md" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoPerfectPublisher-Discord.def.tf b/definitions/sync/MokoPerfectPublisher-Discord.def.tf deleted file mode 100644 index 3084631..0000000 --- a/definitions/sync/MokoPerfectPublisher-Discord.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoPerfectPublisher-Discord - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T21:05:10+00:00 - * Platform : default-repository - * Description: A Perfect Publisher plugin to post to Discord - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoPerfectPublisher-Discord" - default_branch = "main" - detected_platform = "default-repository" - description = "A Perfect Publisher plugin to post to Discord" - sync_timestamp = "2026-04-02T21:05:10+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoPerfectPublisher-Discord/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Client.def.tf b/definitions/sync/MokoStandards-Template-Client.def.tf deleted file mode 100644 index 6561152..0000000 --- a/definitions/sync/MokoStandards-Template-Client.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Client - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:40:35+00:00 - * Platform : default-repository - * Description: A template repo for clients of Moko Consulting - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Client" - default_branch = "main" - detected_platform = "default-repository" - description = "A template repo for clients of Moko Consulting" - sync_timestamp = "2026-04-02T15:40:35+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoStandards-Template-Client/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Dolibarr.def.tf b/definitions/sync/MokoStandards-Template-Dolibarr.def.tf deleted file mode 100644 index f29430d..0000000 --- a/definitions/sync/MokoStandards-Template-Dolibarr.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Dolibarr - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:28:18+00:00 - * Platform : crm-module - * Description: A repo template for a Dolibarr module coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/crm-module.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Dolibarr" - default_branch = "main" - detected_platform = "crm-module" - description = "A repo template for a Dolibarr module coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:28:18+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/crm-module.tf" - } - - sync_stats = { - total_files = 45 - created_files = 0 - updated_files = 40 - skipped_files = 5 - } - - synced_files = [ - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "LICENSE" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "src/.ftpignore" action = "updated" }, - { path = ".mokostandards" action = "updated" }, - { path = "docs/update-server.md" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/ci-dolibarr.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/publish-to-mokodolimods.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_issue.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/dolibarr_module_id_request.md" action = "updated" }, - { path = "src/img/object_favicon_256.png" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = "update.txt" action = "updated" }, - { path = "composer.json" action = "enterprise dependency added" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "src/ChangeLog.md" reason = "CHANGELOG — never overwritten" }, - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = "src/README.md" reason = "README — never overwritten" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoCRM Module Structure Definition - * Standard repository structure for MokoCRM (Dolibarr) modules - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoCRM Module" - description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" - platform = "dolibarr" - last_updated = "2026-01-07T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - stub_content = <<-EOT -# {MODULE_NAME} - -## For Developers - -This README is for developers contributing to this module. - -### Development Setup - -1. Clone this repository -2. Install dependencies: `make install-dev` -3. Run tests: `make test` - -### Building - -```bash -make build -``` - -### Testing - -```bash -make test -make lint -``` - -### Contributing - -See CONTRIBUTING.md for contribution guidelines. - -## For End Users - -End user documentation is available in `src/README.md` after installation. - -## License - -See LICENSE file for details. -EOT - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Dolibarr/CRM modules" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "ChangeLog.md" - extension = "md" - description = "Version history and changes" - required = true - always_overwrite = false - audience = "general" - destination_path = "src" - stub_content = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n- Initial release\n" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.dolibarr.json" - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Dolibarr class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.dolibarr.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.dolibarr.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.dolibarr.template" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - audience = "developer" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "src/.ftpignore" - description = "SFTP upload exclusion rules — gitignore syntax" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/ftp_ignore" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Module source code for deployment" - required = true - purpose = "Contains the actual module code that gets deployed to Dolibarr" - files = [ - { - name = "README.md" - extension = "md" - description = "End-user documentation deployed with the module" - required = true - always_overwrite = false - protected = true - audience = "end-user" - stub_content = <<-EOT -# {MODULE_NAME} - -## For End Users - -This module provides {MODULE_DESCRIPTION}. - -### Installation - -1. Navigate to Home → Setup → Modules/Applications -2. Find "{MODULE_NAME}" in the list -3. Click "Activate" - -### Configuration - -After activation, configure the module: -1. Go to Home → Setup → Modules/Applications -2. Click on the module settings icon -3. Configure as needed - -### Usage - -{USAGE_INSTRUCTIONS} - -### Support - -For support, contact: {SUPPORT_EMAIL} - -## Version - -Current version: {VERSION} - -See CHANGELOG.md for version history. -EOT - }, - { - name = "core/modules/mod{ModuleName}.class.php" - extension = "php" - description = "Main module descriptor file" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "core" - path = "src/core" - description = "Core module files" - required = true - }, - { - name = "langs" - path = "src/langs" - description = "Language translation files" - required = true - }, - { - name = "sql" - path = "src/sql" - description = "Database schema files" - requirement_status = "suggested" - }, - { - name = "css" - path = "src/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "src/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "class" - path = "src/class" - description = "PHP class files" - requirement_status = "suggested" - }, - { - name = "lib" - path = "src/lib" - description = "Library files" - requirement_status = "suggested" - } - ] - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Developer guide for Dolibarr module update checks using update.txt" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-dolibarr.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific build and deployment scripts (not synced)" - required = true - purpose = "Contains scripts written specifically for this repository — CI helpers, deploy hooks, etc. MokoStandards does not sync files into this directory." - files = [ - { - name = "index.md" - extension = "md" - description = "Scripts documentation" - requirement_status = "required" - }, - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = "templates" - path = "templates" - description = "Template files for code generation" - requirement_status = "suggested" - purpose = "Contains templates used by build scripts" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > | `{{PRIMARY_LANGUAGE}}` | Primary programming language (usually `PHP`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoCRM** (Dolibarr) module 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: {{REPO_URL}} - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** - Platform: **Dolibarr / MokoCRM** - - --- - - ## Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - ## Version Management - - **`README.md` is the single source of truth for the repository version.** - - - **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03` → `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Module Version Alignment - - The version in `README.md` **must always match** the `$this->version` property in the main module descriptor class (`src/core/modules/mod{{MODULE_CLASS}}.class.php`). - - - On `dev/**` branches: `$this->version = 'development'` (set automatically by deploy-dev workflow) - - On merge to main: `$this->version` is set to the real version by the auto-release workflow - - **Never manually set `$this->version`** — the workflows handle it - - ### Module Update Server (update.txt) - - Every Dolibarr module must wire up `$this->url_last_version` so the admin panel can check for updates. - - **In `src/core/modules/mod{{MODULE_CLASS}}.class.php` constructor**, add: - - ```php - $this->version = 'development'; - $this->url_last_version = 'https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.txt'; - ``` - - **How it works:** - 1. The `auto-release.yml` workflow writes `update.txt` to the repo root on every GitHub Release - 2. `update.txt` contains the latest version from `README.md` - 3. Dolibarr fetches `$this->url_last_version` and compares against the installed version - - **Add this method** to the module descriptor to parse the JSON response: - - ```php - public function getLatestVersion(): string - { - if (empty($this->url_last_version)) { - return ''; - } - $content = @file_get_contents($this->url_last_version); - if ($content === false) { - return ''; - } - $data = json_decode($content, true); - return $data['version'] ?? ''; - } - ``` - - **update.txt format** (auto-generated, do not edit manually): - ```json - { - "version": "01.02.03", - "tag": "v01.02.03", - "repo": "mokoconsulting-tech/{{REPO_NAME}}", - "release_url": "https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/tag/v01.02.03", - "updated": "2026-03-27T00:00:00Z" - } - ``` - - Full guide: [docs/guide/crm/dolibarr-update-check.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-update-check.md) - - --- - - ## Dolibarr Module Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source code (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/ - │ │ └── {{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ │ ├── llx_{{MODULE_NAME}}.sql - │ │ └── llx_{{MODULE_NAME}}.key.sql - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## Module Descriptor Class Pattern - - The main module descriptor (`src/core/modules/mod{{MODULE_CLASS}}.class.php`) must follow this pattern: - - ```php - db = $db; - $this->numero = {{MODULE_ID}}; // Unique module ID — do not change - $this->rights_class = '{{MODULE_NAME}}'; - $this->family = 'crm'; - $this->module_position = '50'; - $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = 'Description of {{MODULE_NAME}} module'; - $this->version = 'XX.YY.ZZ'; // Must match README.md version - $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); - $this->picto = 'object_favicon_256.png@mokocrm'; - $this->editor_name = 'Moko Consulting'; - $this->editor_url = 'https://mokoconsulting.tech'; // Must be an external online web site - $this->editor_squarred_logo = 'object_favicon_256.png@mokocrm'; - } - } - ``` - - **Key rules for the module descriptor:** - - `$this->numero` is a globally unique ID registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) — **never change it**. - - `$this->version` must exactly match the version in `README.md`. - - Register new modules in the module registry before using any ID. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 a local-dev fallback only. - - --- - - ## 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 | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm-development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed public PHP method | PHPDoc block; `docs/api/` index for that class | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - ## 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 change `$this->numero` (module ID) — it is permanently registered in the module registry - - 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 let the module descriptor `$this->version` and `README.md` version go out of sync - - Never register a new module ID without first checking module-registry.md for the next available ID - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Dolibarr/CRM edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.dolibarr.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{MODULE_NAME}}` | The module name as used in Dolibarr (lowercase, e.g. `mymodule`) — from the `langs/en_US/*.lang` filename or `$this->rights_class` in the module descriptor | - > | `{{MODULE_CLASS}}` | PascalCase module class name (e.g. `MyModule`) — from the `src/core/modules/mod*.class.php` filename | - > | `{{MODULE_ID}}` | The `$this->numero` value in `src/core/modules/mod*.class.php`; check [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) if creating a new module | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoCRM** (Dolibarr) module repository. - - {{REPO_DESCRIPTION}} - - Module name: **{{MODULE_NAME}}** - Module class: **{{MODULE_CLASS}}** - Module ID: **{{MODULE_ID}}** *(unique, immutable — registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md))* - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── src/ # Module source (deployed to Dolibarr) - │ ├── README.md # End-user documentation - │ ├── core/ - │ │ └── modules/ - │ │ └── mod{{MODULE_CLASS}}.class.php # Main module descriptor - │ ├── langs/ - │ │ └── en_US/{{MODULE_NAME}}.lang - │ ├── sql/ # Database schema - │ ├── class/ # PHP class files - │ └── lib/ # Library files - ├── docs/ # Technical documentation - ├── scripts/ # Build and maintenance scripts - ├── tests/ # Test suite - │ ├── unit/ - │ └── integration/ - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - # Primary Language - - **PHP** (≥ 8.1) is the primary language for this Dolibarr module. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Dolibarr Version Alignment - - Two artefacts must always carry the same version: - - | Artefact | Location | - |----------|----------| - | `README.md` | `FILE INFORMATION VERSION` field + badge | - | Module descriptor | `$this->version` in `src/core/modules/mod{{MODULE_CLASS}}.class.php` | - - --- - - # Module Descriptor Class - - The file `src/core/modules/mod{{MODULE_CLASS}}.class.php` is the Dolibarr module descriptor. The key properties: - - ```php - public $numero = {{MODULE_ID}}; // IMMUTABLE — never change; registered globally - public $version = 'XX.YY.ZZ'; // Must match README.md version exactly - ``` - - **`$numero` is permanent.** It was registered in [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) when this module was created. Changing it would break all Dolibarr installations that have this module activated. - - Before creating a new module, always check the registry for the next available ID. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/class/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - ``` - - **Markdown / YAML / Shell:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$module_name` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `ApiClient.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `ci-dolibarr.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - 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 a local-dev fallback only. - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed module version | Update `$this->version` in module descriptor; bump `README.md` | - | 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` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never change `$this->numero`** — the module ID is permanent and globally registered. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never register a new module ID** without first consulting module-registry.md. - - **Never let `$this->version` and `README.md` version diverge.** - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] `$this->version` in module descriptor updated to match - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [module-registry.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/development/crm/module-registry.md) | Dolibarr module ID registry — check before reserving a new ID | - | [crm/development-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/crm/development-standards.md) | MokoCRM Dolibarr module development standards | - | [dolibarr-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/crm/dolibarr-development-guide.md) | MokoCRM full development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-dolibarr.yml" - extension = "yml" - description = "Dolibarr-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/ci-dolibarr.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "publish-to-mokodolimods.yml" - extension = "yml" - description = "On release, copies src/ to htdocs/custom/$DEV_FTP_SUFFIX in mokodolimods and opens a PR" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/publish-to-mokodolimods.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Dolibarr module health checks — descriptor, numero, url_last_version, repo artifacts" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/dolibarr/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "dolibarr_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_issue.md" - }, - { - name = "dolibarr_module_id_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/dolibarr_module_id_request.md" - } - ] - } - ] - }, - { - name = "img" - path = "src/img" - description = "Module image assets including Dolibarr picto" - requirement_status = "required" - purpose = "Contains the module picto displayed in the Dolibarr UI" - files = [ - { - name = "object_favicon_256.png" - extension = "png" - description = "Moko Consulting picto shown in Dolibarr module list (256 px); object_ prefix follows Dolibarr icon naming convention" - requirement_status = "required" - always_overwrite = true - template = "templates/images/primary/favicon_256.png" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-module)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Generic.def.tf b/definitions/sync/MokoStandards-Template-Generic.def.tf deleted file mode 100644 index f2e0a95..0000000 --- a/definitions/sync/MokoStandards-Template-Generic.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Generic - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:27:41+00:00 - * Platform : default-repository - * Description: A repo template for a generic coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Generic" - default_branch = "main" - detected_platform = "default-repository" - description = "A repo template for a generic coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:27:41+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoStandards-Template-Generic/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Component.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Component.def.tf deleted file mode 100644 index b5f4357..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Component.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Component - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:30:04+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Component coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Component" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Component coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:30:04+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 3 - updated_files = 35 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Library.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Library.def.tf deleted file mode 100644 index e902c04..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Library.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Library - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:31:13+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Library coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Library" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Library coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:31:13+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 3 - updated_files = 35 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Module.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Module.def.tf deleted file mode 100644 index 228b4bc..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Module.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Module - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:29:31+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Module coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Module" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Module coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:29:31+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 4 - updated_files = 34 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Package.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Package.def.tf deleted file mode 100644 index cb3c00c..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Package.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Package - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:30:39+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Package coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Package" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Package coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:30:39+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 3 - updated_files = 35 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Plugin.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Plugin.def.tf deleted file mode 100644 index 80373b9..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Plugin.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Plugin - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:31:55+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Plugin coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Plugin" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Plugin coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:31:55+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 3 - updated_files = 35 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoStandards-Template-Joomla-Template.def.tf b/definitions/sync/MokoStandards-Template-Joomla-Template.def.tf deleted file mode 100644 index 450bddb..0000000 --- a/definitions/sync/MokoStandards-Template-Joomla-Template.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoStandards-Template-Joomla-Template - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:28:58+00:00 - * Platform : waas-component - * Description: A repo template for a Joomla Template coding project according to MokoStandards - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoStandards-Template-Joomla-Template" - default_branch = "main" - detected_platform = "waas-component" - description = "A repo template for a Joomla Template coding project according to MokoStandards" - sync_timestamp = "2026-04-02T15:28:58+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 6 - updated_files = 32 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "created" }, - { path = "CONTRIBUTING.md" action = "created" }, - { path = "update.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "update.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/update.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (update.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## update.xml — Required in Repo Root - - `update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `update.xml` — old entries must be preserved below. - - The `` in `update.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `update.xml`. - - Must include `` block pointing to this repo's `update.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `update.xml` version; bump README.md version | - | New release | Prepend `` block to `update.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── update.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `update.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # update.xml — Required in Repo Root - - `update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/update.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `update.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `update.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` | - | New release | Prepend `` to `update.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `update.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoTesting.def.tf b/definitions/sync/MokoTesting.def.tf deleted file mode 100644 index 758adc0..0000000 --- a/definitions/sync/MokoTesting.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoTesting - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:23:26+00:00 - * Platform : default-repository - * Description: Testign grond for Moko Consulting - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoTesting" - default_branch = "main" - detected_platform = "default-repository" - description = "Testign grond for Moko Consulting" - sync_timestamp = "2026-04-02T15:23:26+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoTesting/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/MokoWaaS.def.tf b/definitions/sync/MokoWaaS.def.tf deleted file mode 100644 index 71b54f3..0000000 --- a/definitions/sync/MokoWaaS.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoWaaS - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:25:11+00:00 - * Platform : waas-component - * Description: MokoWaaS is a Joomla 5.x system plugin that provides a comprehensive identity override layer for the MokoWaaS platform. It ensures consistent branding, terminology, and user experience across all Joomla administrative and frontend interfaces. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoWaaS" - default_branch = "main" - detected_platform = "waas-component" - description = "MokoWaaS is a Joomla 5.x system plugin that provides a comprehensive identity override layer for the MokoWaaS platform. It ensures consistent branding, terminology, and user experience across all Joomla administrative and frontend interfaces." - sync_timestamp = "2026-04-02T15:25:11+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 3 - updated_files = 35 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoWaaSAnnounce.def.tf b/definitions/sync/MokoWaaSAnnounce.def.tf deleted file mode 100644 index 55ad625..0000000 --- a/definitions/sync/MokoWaaSAnnounce.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoWaaSAnnounce - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:36:02+00:00 - * Platform : waas-component - * Description: A centralized system to make announcements via admin module for Joomla - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoWaaSAnnounce" - default_branch = "main" - detected_platform = "waas-component" - description = "A centralized system to make announcements via admin module for Joomla " - sync_timestamp = "2026-04-02T15:36:02+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 41 - created_files = 4 - updated_files = 34 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "created" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoWaaSBrand.def.tf b/definitions/sync/MokoWaaSBrand.def.tf deleted file mode 100644 index 3ef5892..0000000 --- a/definitions/sync/MokoWaaSBrand.def.tf +++ /dev/null @@ -1,1286 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoWaaSBrand - * - * Auto-generated by MokoStandards bulk sync on 2026-03-25T02:20:31+00:00 - * Platform : waas-component - * Description: - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoWaaSBrand" - default_branch = "main" - detected_platform = "waas-component" - description = "" - sync_timestamp = "2026-03-25T02:20:31+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 32 - created_files = 3 - updated_files = 27 - skipped_files = 2 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "updates.xml" action = "updated" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = ".mokostandards" action = "updated" }, - { path = ".github/copilot.yml" action = "updated" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "updated" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/MokoWinSetup.def.tf b/definitions/sync/MokoWinSetup.def.tf deleted file mode 100644 index 8457783..0000000 --- a/definitions/sync/MokoWinSetup.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/MokoWinSetup - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:39:49+00:00 - * Platform : default-repository - * Description: A setup script for Windows - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/MokoWinSetup" - default_branch = "main" - detected_platform = "default-repository" - description = "A setup script for Windows" - sync_timestamp = "2026-04-02T15:39:49+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/MokoWinSetup/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/PLG_FINDER_MOKOVMSMARTSEARCH.def.tf b/definitions/sync/PLG_FINDER_MOKOVMSMARTSEARCH.def.tf deleted file mode 100644 index dab759f..0000000 --- a/definitions/sync/PLG_FINDER_MOKOVMSMARTSEARCH.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/PLG_FINDER_MOKOVMSMARTSEARCH - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:33:10+00:00 - * Platform : default-repository - * Description: Virtuemart Smart serachPlugin - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/PLG_FINDER_MOKOVMSMARTSEARCH" - default_branch = "main" - detected_platform = "default-repository" - description = "Virtuemart Smart serachPlugin " - sync_timestamp = "2026-04-02T15:33:10+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/PLG_FINDER_MOKOVMSMARTSEARCH/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/client-clarksvillefurs.def.tf b/definitions/sync/client-clarksvillefurs.def.tf deleted file mode 100644 index 0f672ab..0000000 --- a/definitions/sync/client-clarksvillefurs.def.tf +++ /dev/null @@ -1,775 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/client-clarksvillefurs - * - * Auto-generated by MokoStandards bulk sync on 2026-03-30T08:30:51+00:00 - * Platform : default-repository - * Description: The Clarksville Furs implementation of MokoCassiopeia - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/client-clarksvillefurs" - default_branch = "main" - detected_platform = "default-repository" - description = "The Clarksville Furs implementation of MokoCassiopeia" - sync_timestamp = "2026-03-30T08:30:51+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 56 - created_files = 16 - updated_files = 22 - skipped_files = 18 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/ci.yml" action = "updated" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/workflows/deploy-dev.yml" action = "created" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "created" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/repo-health.yml" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/ci.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/ci.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/ci.yml does not match 1f2449072e0d3304fb645b2ef45526fcf978783e\",\"documentation_url\":\"https (truncated...) -" }, - { path = ".github/workflows/test.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/test.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/test.yml does not match 5c7b0f5639c622d5c910a066fe2415b69a49918d\",\"documentation_url\":\"htt (truncated...) -" }, - { path = ".github/workflows/code-quality.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/code-quality.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/code-quality.yml does not match f510c81073d573669477a96a646d3a8383e77b6b\",\"documentation_u (truncated...) -" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 04c7ef91744b3e482f495e592f268a7448dafe74\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/deploy.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/deploy.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/deploy.yml does not match 4895e597d4ee56a976c8792ab80da574bcfa23c8\",\"documentation_url\":\"h (truncated...) -" }, - { path = ".github/workflows/repo-health.yml" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/standards-compliance.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-clarksvillefurs/contents/.github/workflows/standards-compliance.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/standards-compliance.yml does not match bc0516a1dbc8b2acfcf3189ac28be497c1a8c93e\",\"documen (truncated...) -" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci.yml" - extension = "yml" - description = "Continuous integration workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "ci.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "ci.yml" - create_path = true - template = "templates/workflows/generic/ci.yml.template" - }, - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "repo-health.yml" - extension = "yml" - description = "Repository health monitoring" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "repo_health.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "repo-health.yml" - create_path = true - template = "templates/workflows/generic/repo_health.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/client-kiddieland.def.tf b/definitions/sync/client-kiddieland.def.tf deleted file mode 100644 index 2101863..0000000 --- a/definitions/sync/client-kiddieland.def.tf +++ /dev/null @@ -1,734 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/client-kiddieland - * - * Auto-generated by MokoStandards bulk sync on 2026-04-02T15:41:12+00:00 - * Platform : default-repository - * Description: Client repo for Kiddieland Child Care Center - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/client-kiddieland" - default_branch = "main" - detected_platform = "default-repository" - description = "Client repo for Kiddieland Child Care Center" - sync_timestamp = "2026-04-02T15:41:12+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 53 - created_files = 11 - updated_files = 31 - skipped_files = 11 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "Makefile" action = "updated" }, - { path = "composer.json" action = "updated" }, - { path = "docs/index.md" action = "updated" }, - { path = "docs/INSTALLATION.md" action = "updated" }, - { path = ".github/workflows/test.yml" action = "created" }, - { path = ".github/workflows/code-quality.yml" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/deploy-dev.yml" action = "created" }, - { path = ".github/deploy-demo.yml" action = "created" }, - { path = ".github/deploy-rs.yml" action = "created" }, - { path = ".github/sync-version-on-merge.yml" action = "created" }, - { path = ".github/auto-release.yml" action = "created" }, - { path = ".github/repository-cleanup.yml" action = "created" }, - { path = ".github/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/test.yml" action = "updated" }, - { path = ".github/workflows/code-quality.yml" action = "updated" }, - { path = ".github/workflows/deploy.yml" action = "updated" }, - { path = ".github/workflows/standards-compliance.yml" action = "updated" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "updated" }, - { path = ".github/workflows/deploy-dev.yml" action = "updated" }, - { path = ".github/workflows/deploy-demo.yml" action = "updated" }, - { path = ".github/workflows/deploy-rs.yml" action = "updated" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "updated" }, - { path = ".github/workflows/auto-release.yml" action = "updated" }, - { path = ".github/workflows/repository-cleanup.yml" action = "updated" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "updated" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "updated" }, - { path = ".github/CODEOWNERS" action = "updated" }, - ] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - { path = "GOVERNANCE.md" reason = "Source file not found" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/codeql-analysis.yml" reason = "API error: Request failed after 3 attempts: Client error: `PUT https://api.github.com/repos/mokoconsulting-tech/client-kiddieland/contents/.github/workflows/codeql-analysis.yml` resulted in a `409 Conflict` response: -{\"message\":\".github/workflows/codeql-analysis.yml does not match 3f50896ddc3f73cd5863338e95067692ee0e52e6\",\"documentatio (truncated...) -" }, - { path = ".github/workflows/release-cycle.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * Default Repository Structure Definition - * Default repository structure applicable to all repository types with minimal requirements - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Default Repository Structure" - description = "Default repository structure applicable to all repository types with minimal requirements" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-16T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-README.md" - source_type = "template" - destination_path = "." - destination_filename = "README.md" - create_path = false - template = "templates/docs/required/template-README.md" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - requirement_status = "required" - audience = "general" - source_path = "templates/licenses" - source_filename = "GPL-3.0" - source_type = "template" - destination_path = "." - destination_filename = "LICENSE" - create_path = false - template = "templates/licenses/GPL-3.0" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-CHANGELOG.md" - source_type = "template" - destination_path = "." - destination_filename = "CHANGELOG.md" - create_path = false - template = "templates/docs/required/template-CHANGELOG.md" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/required" - source_filename = "template-CONTRIBUTING.md" - source_type = "template" - destination_path = "." - destination_filename = "CONTRIBUTING.md" - create_path = false - template = "templates/docs/required/template-CONTRIBUTING.md" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-SECURITY.md" - source_type = "template" - destination_path = "." - destination_filename = "SECURITY.md" - create_path = false - template = "templates/docs/required/template-SECURITY.md" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - requirement_status = "required" - always_overwrite = false - protected = true - audience = "contributor" - source_path = "templates/docs/extra" - source_filename = "template-CODE_OF_CONDUCT.md" - source_type = "template" - destination_path = "." - destination_filename = "CODE_OF_CONDUCT.md" - create_path = false - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-ROADMAP.md" - source_type = "template" - destination_path = "." - destination_filename = "ROADMAP.md" - create_path = false - template = "templates/docs/extra/template-ROADMAP.md" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance model and decision-making process" - requirement_status = "suggested" - always_overwrite = false - protected = true - audience = "general" - source_path = "templates/docs/extra" - source_filename = "template-GOVERNANCE.md" - source_type = "template" - destination_path = "." - destination_filename = "GOVERNANCE.md" - create_path = false - template = "templates/docs/extra/template-GOVERNANCE.md" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - requirement_status = "required" - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - requirement_status = "required" - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "required" - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.generic.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.generic.template" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - } - ] - - directories = [ - { - name = "docs" - path = "docs" - description = "Documentation directory" - requirement_status = "required" - purpose = "Contains comprehensive project documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - template = "templates/docs/index.md" - }, - { - name = "INSTALLATION.md" - extension = "md" - description = "Installation and setup instructions" - requirement_status = "required" - audience = "general" - source_path = "templates/docs/required" - source_filename = "template-INSTALLATION.md" - source_type = "template" - destination_path = "docs" - destination_filename = "INSTALLATION.md" - create_path = true - template = "templates/docs/required/template-INSTALLATION.md" - }, - { - name = "API.md" - extension = "md" - description = "API documentation" - requirement_status = "suggested" - }, - { - name = "ARCHITECTURE.md" - extension = "md" - description = "Architecture documentation" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration" - requirement_status = "optional" - always_overwrite = false - } - ] - }, - { - name = "src" - path = "src" - description = "Source code directory" - requirement_status = "required" - purpose = "Contains application source code" - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - requirement_status = "suggested" - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "optional" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "required" - purpose = "Contains GitHub Actions workflows and configuration" - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "test.yml" - extension = "yml" - description = "Comprehensive testing workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "test.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "test.yml" - create_path = true - template = "templates/workflows/generic/test.yml.template" - }, - { - name = "code-quality.yml" - extension = "yml" - description = "Code quality and linting workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "code-quality.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "code-quality.yml" - create_path = true - template = "templates/workflows/generic/code-quality.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "codeql-analysis.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "codeql-analysis.yml" - create_path = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "deploy.yml" - extension = "yml" - description = "Deployment workflow" - requirement_status = "optional" - always_overwrite = true - source_path = "templates/workflows/generic" - source_filename = "deploy.yml.template" - source_type = "template" - destination_path = ".github/workflows" - destination_filename = "deploy.yml" - create_path = true - template = "templates/workflows/generic/deploy.yml.template" - }, - { - name = "release-cycle.yml" - extension = "yml" - description = "Release management workflow with automated release flow" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "release-cycle.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "release-cycle.yml" - create_path = true - template = ".github/workflows/release-cycle.yml" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - source_path = ".github/workflows" - source_filename = "standards-compliance.yml" - source_type = "copy" - destination_path = ".github/workflows" - destination_filename = "standards-compliance.yml" - create_path = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "node_modules" - path = "node_modules" - description = "Node.js dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "vendor" - path = "vendor" - description = "PHP dependencies (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "build" - path = "build" - description = "Build artifacts (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - }, - { - name = "dist" - path = "dist" - description = "Distribution files (generated)" - requirement_status = "not-allowed" - purpose = "Generated directory that should not be committed" - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT — configure in org Actions secrets" - required = true - scope = "organisation" - used_in = "GitHub Actions workflows" - }, - { - name = "CODECOV_TOKEN" - description = "Codecov upload token for code coverage reporting" - required = false - scope = "repository" - used_in = "CI workflow code coverage step" - } - ] - - variables = [ - { - name = "NODE_VERSION" - description = "Node.js version for CI/CD" - default_value = "18" - required = false - scope = "repository" - }, - { - name = "PYTHON_VERSION" - description = "Python version for CI/CD" - default_value = "3.9" - required = false - scope = "repository" - } - ] - - branch_protections = [ - { - branch_pattern = "main" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci", "code-quality"] - enforce_admins = false - restrict_pushes = true - }, - { - branch_pattern = "master" - require_pull_request = true - required_approvals = 1 - require_code_owner_review = false - dismiss_stale_reviews = true - require_status_checks = true - required_status_checks = ["ci"] - enforce_admins = false - restrict_pushes = true - } - ] - - repository_settings = { - has_issues = true - has_projects = true - has_wiki = false - has_discussions = false - allow_merge_commit = true - allow_squash_merge = true - allow_rebase_merge = false - delete_branch_on_merge = true - allow_auto_merge = false - } - - labels = [ - { - name = "bug" - color = "d73a4a" - description = "Something isn't working" - }, - { - name = "enhancement" - color = "a2eeef" - description = "New feature or request" - }, - { - name = "documentation" - color = "0075ca" - description = "Improvements or additions to documentation" - }, - { - name = "security" - color = "ee0701" - description = "Security vulnerability or concern" - } - ] - } - } -} diff --git a/definitions/sync/client-vexcreations.def.tf b/definitions/sync/client-vexcreations.def.tf deleted file mode 100644 index f48aa8d..0000000 --- a/definitions/sync/client-vexcreations.def.tf +++ /dev/null @@ -1,1334 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/client-vexcreations - * - * Auto-generated by MokoStandards bulk sync on 2026-03-30T10:48:52+00:00 - * Platform : waas-component - * Description: A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks. - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/waas-component.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/client-vexcreations" - default_branch = "main" - detected_platform = "waas-component" - description = "A modern enhancement layer for Joomla’s Cassiopeia template. Moko-Cassiopeia adds Font Awesome 7, Bootstrap 5 helpers, an automatic Table of Contents (TOC) utility, and optional expansions including Google Tag Manager and Google Analytics (GA4) hooks." - sync_timestamp = "2026-03-30T10:48:52+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/waas-component.tf" - } - - sync_stats = { - total_files = 40 - created_files = 30 - updated_files = 7 - skipped_files = 3 - } - - synced_files = [ - { path = "LICENSE" action = "updated" }, - { path = "SECURITY.md" action = "updated" }, - { path = "CODE_OF_CONDUCT.md" action = "updated" }, - { path = "CONTRIBUTING.md" action = "updated" }, - { path = "updates.xml" action = "created" }, - { path = "phpstan.neon" action = "updated" }, - { path = "Makefile" action = "created" }, - { path = ".gitignore" action = "updated" }, - { path = "composer.json" action = "created" }, - { path = ".mokostandards" action = "created" }, - { path = "docs/update-server.md" action = "created" }, - { path = ".github/copilot.yml" action = "created" }, - { path = ".github/copilot-instructions.md" action = "updated" }, - { path = ".github/CLAUDE.md" action = "created" }, - { path = ".github/workflows/codeql-analysis.yml" action = "created" }, - { path = ".github/workflows/standards-compliance.yml" action = "created" }, - { path = ".github/workflows/enterprise-firewall-setup.yml" action = "created" }, - { path = ".github/workflows/deploy-dev.yml" action = "created" }, - { path = ".github/workflows/deploy-demo.yml" action = "created" }, - { path = ".github/workflows/deploy-rs.yml" action = "created" }, - { path = ".github/workflows/sync-version-on-merge.yml" action = "created" }, - { path = ".github/workflows/auto-release.yml" action = "created" }, - { path = ".github/workflows/repository-cleanup.yml" action = "created" }, - { path = ".github/workflows/auto-dev-issue.yml" action = "created" }, - { path = ".github/workflows/repo_health.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/config.yml" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/adr.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/bug_report.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/documentation.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/enterprise_support.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/feature_request.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/firewall-request.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/question.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/request-license.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/rfc.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/security.md" action = "created" }, - { path = ".github/ISSUE_TEMPLATE/joomla_issue.md" action = "created" }, - { path = "composer.json" action = "enterprise dependency added" }, - { path = ".github/.mokostandards" action = "migrated from root" }, - ] - - skipped_files = [ - { path = "GOVERNANCE.md" reason = "Preserved (always_overwrite=false)" }, - { path = ".github/workflows/ci-joomla.yml" reason = "Source file not found" }, - { path = ".github/workflows/custom/README.md" reason = "README — never overwritten" }, - ] - } -} - -# ---- Base platform definition (reference copy) ---- -/** - * MokoWaaS Component Structure Definition - * Standard repository structure for MokoWaaS (Joomla) components - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "MokoWaaS Component" - description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" - platform = "mokowaas" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "05.00.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla/WaaS components" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - always_overwrite = true - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version" - required = true - always_overwrite = false - audience = "developer" - template = "templates/joomla/updates.xml.template" - stub_content = <<-MOKO_END - - - - {{EXTENSION_NAME}} - {{REPO_NAME}} — Moko Consulting Joomla extension - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - {{VERSION}} - {{REPO_URL}}/releases/tag/{{VERSION}} - - {{DOWNLOAD_URL}} - - - 7.4 - Moko Consulting - {{MAINTAINER_URL}} - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation using MokoStandards templates" - required = true - always_overwrite = true - audience = "developer" - source_path = "templates/makefiles" - source_filename = "Makefile.joomla.template" - source_type = "template" - destination_path = "." - destination_filename = "Makefile" - create_path = false - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla development - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - validation_rules = [ - { - type = "content-pattern" - description = "Must contain sftp-config pattern to ignore SFTP sync configuration files" - pattern = "sftp-config" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.css pattern to ignore custom user CSS overrides" - pattern = "user\\.css" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain user.js pattern to ignore custom user JavaScript overrides" - pattern = "user\\.js" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain modulebuilder.txt pattern to ignore Joomla Module Builder artifacts" - pattern = "modulebuilder\\.txt" - severity = "error" - }, - { - type = "content-pattern" - description = "Must contain colors_custom.css pattern to ignore custom color scheme overrides" - pattern = "colors_custom\\.css" - severity = "error" - } - ] - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest — requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.joomla.json" - }, - { - name = ".mokostandards" - extension = "yml" - description = "MokoStandards governance attachment — links this repo back to the standards source" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/mokostandards.yml.template" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process — auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "site" - path = "site" - description = "Component frontend (site) code" - required = true - purpose = "Contains frontend component code deployed to site" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main site controller" - required = true - audience = "developer" - }, - { - name = "manifest.xml" - extension = "xml" - description = "Component manifest for site" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "site/controllers" - description = "Site controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "site/models" - description = "Site models" - requirement_status = "suggested" - }, - { - name = "views" - path = "site/views" - description = "Site views" - required = true - } - ] - }, - { - name = "admin" - path = "admin" - description = "Component backend (admin) code" - required = true - purpose = "Contains backend component code for administrator" - files = [ - { - name = "controller.php" - extension = "php" - description = "Main admin controller" - required = true - audience = "developer" - } - ] - subdirectories = [ - { - name = "controllers" - path = "admin/controllers" - description = "Admin controllers" - requirement_status = "suggested" - }, - { - name = "models" - path = "admin/models" - description = "Admin models" - requirement_status = "suggested" - }, - { - name = "views" - path = "admin/views" - description = "Admin views" - required = true - }, - { - name = "sql" - path = "admin/sql" - description = "Database schema files" - requirement_status = "suggested" - } - ] - }, - { - name = "media" - path = "media" - description = "Media files (CSS, JS, images)" - requirement_status = "suggested" - purpose = "Contains static assets" - subdirectories = [ - { - name = "css" - path = "media/css" - description = "Stylesheets" - requirement_status = "suggested" - }, - { - name = "js" - path = "media/js" - description = "JavaScript files" - requirement_status = "suggested" - }, - { - name = "images" - path = "media/images" - description = "Image files" - requirement_status = "suggested" - } - ] - }, - { - name = "language" - path = "language" - description = "Language translation files" - required = true - purpose = "Contains language INI files" - }, - { - name = "docs" - path = "docs" - description = "Developer and technical documentation" - required = true - purpose = "Contains technical documentation, API docs, architecture diagrams" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - required = true - }, - { - name = "update-server.md" - extension = "md" - description = "Joomla update server (updates.xml) documentation" - required = true - always_overwrite = true - template = "templates/docs/required/template-update-server-joomla.md" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts — not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - required = true - purpose = "Contains unit tests, integration tests, and test fixtures" - subdirectories = [ - { - name = "unit" - path = "tests/unit" - description = "Unit tests" - required = true - }, - { - name = "integration" - path = "tests/integration" - description = "Integration tests" - requirement_status = "suggested" - } - ] - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/mokogitea/copilot-instructions.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # {{REPO_NAME}} — GitHub Copilot Custom Instructions - - ## What This Repo Is - - This is a **Moko Consulting MokoWaaS** (Joomla) 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: {{REPO_URL}} - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Platform: **Joomla 4.x / MokoWaaS** - - --- - - ## Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. JavaScript may be used for frontend enhancements. YAML uses 2-space indentation. 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. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell / XML:** Use the appropriate comment syntax 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 `README.md` governs all other version references. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - The version in `README.md` **must always match** the `` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically. - - ```xml - - 01.02.04 - - - - - {{EXTENSION_NAME}} - 01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - - - - ``` - - --- - - ## Joomla Extension Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required, see below) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images (deployed to /media/{{EXTENSION_ELEMENT}}/) - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ - │ ├── copilot-instructions.md # This file - │ └── CLAUDE.md - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - ├── LICENSE # GPL-3.0-or-later - └── Makefile # Build automation - ``` - - --- - - ## updates.xml — Required in Repo Root - - `updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension. - - The `manifest.xml` must reference it via: - ```xml - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release must prepend a new `` block at the top of `updates.xml` — old entries must be preserved below. - - The `` in `updates.xml` must exactly match `` in `manifest.xml` and the version in `README.md`. - - The `` must be a publicly accessible direct download link (GitHub Releases asset URL). - - `` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it. - - --- - - ## manifest.xml Rules - - - Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`). - - `` tag must be kept in sync with `README.md` version and `updates.xml`. - - Must include `` block pointing to this repo's `updates.xml`. - - Must include `` and `` sections. - - Joomla 4.x requires `Moko\{{EXTENSION_NAME}}` for namespaced extensions. - - --- - - ## GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - 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 }} - ``` - - --- - - ## 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 | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - - --- - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyController` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - --- - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - --- - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - ## Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed manifest.xml | Update `updates.xml` version; bump README.md version | - | New release | Prepend `` block to `updates.xml`; update CHANGELOG.md; bump README.md version | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - ## 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 add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files - - 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 let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards — Joomla/WaaS edition" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/mokogitea/CLAUDE.joomla.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{EXTENSION_NAME}}` | The `` element in `manifest.xml` at the repository root | - > | `{{EXTENSION_TYPE}}` | The `type` attribute of the `` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) | - > | `{{EXTENSION_ELEMENT}}` | The `` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **MokoWaaS** (Joomla) extension repository. - - {{REPO_DESCRIPTION}} - - Extension name: **{{EXTENSION_NAME}}** - Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`) - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - ├── manifest.xml # Joomla installer manifest (root — required) - ├── updates.xml # Update server manifest (root — required) - ├── site/ # Frontend (site) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ └── views/ - ├── admin/ # Backend (admin) code - │ ├── controller.php - │ ├── controllers/ - │ ├── models/ - │ ├── views/ - │ └── sql/ - ├── language/ # Language INI files - ├── media/ # CSS, JS, images - ├── docs/ # Technical documentation - ├── tests/ # Test suite - ├── .github/ - │ ├── workflows/ # CI/CD workflows (synced from MokoStandards) - │ ├── copilot-instructions.md - │ └── CLAUDE.md # This file - ├── README.md # Version source of truth - ├── CHANGELOG.md - ├── CONTRIBUTING.md - └── LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **PHP** (≥ 7.4) is the primary language for this Joomla extension. YAML uses 2-space indentation. All other text files use tabs per `.editorconfig`. - - --- - - # 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 to all `FILE INFORMATION` headers automatically on merge. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text — use the badge or FILE INFORMATION header only. - - ### Joomla Version Alignment - - Three files must **always have the same version**: - - | File | Where the version lives | - |------|------------------------| - | `README.md` | `FILE INFORMATION` block + badge | - | `manifest.xml` | `` tag | - | `updates.xml` | `` in the most recent `` block | - - The `make release` command / release workflow syncs all three automatically. - - --- - - # updates.xml — Required in Repo Root - - `updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via: - - ```xml - - - - {{REPO_URL}}/raw/main/updates.xml - - - ``` - - **Rules:** - - Every release prepends a new `` block at the top — older entries are preserved. - - `` in `updates.xml` must exactly match `` in `manifest.xml` and `README.md`. - - `` must be a publicly accessible GitHub Releases asset URL. - - `` — backslash is literal (Joomla regex syntax). - - Example `updates.xml` entry for a new release: - ```xml - - - {{EXTENSION_NAME}} - {{REPO_NAME}} - {{EXTENSION_ELEMENT}} - {{EXTENSION_TYPE}} - 01.02.04 - {{REPO_URL}}/releases/tag/01.02.04 - - - {{REPO_URL}}/releases/download/01.02.04/{{EXTENSION_ELEMENT}}-01.02.04.zip - - - - 7.4 - Moko Consulting - https://mokoconsulting.tech - - - ``` - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.{{EXTENSION_TYPE}} - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /site/controllers/item.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - defined('_JEXEC') or die; - ``` - - **Markdown / YAML / Shell / XML:** Use the appropriate comment syntax with the same fields. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `ItemModel` | - | PHP method / function | `camelCase` | `getItems()` | - | PHP variable | `$snake_case` | `$item_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_ITEMS` | - | PHP class file | `PascalCase.php` | `ItemModel.php` | - | YAML workflow | `kebab-case.yml` | `ci-joomla.yml` | - | Markdown doc | `kebab-case.md` | `installation-guide.md` | - - ## Commit Messages - - Format: `(): ` — imperative, lower-case subject, no trailing period. - - Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `dependabot/` - - --- - - # GitHub Actions — Token Usage - - Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # ✅ Correct - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # ❌ Wrong — never use these - token: ${{ github.token }} - token: ${{ secrets.GITHUB_TOKEN }} - ``` - - --- - - # Keeping Documentation Current - - | Change type | Documentation to update | - |-------------|------------------------| - | New or renamed PHP class/method | PHPDoc block; `docs/api/` entry | - | New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` | - | New release | Prepend `` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` | - | New or changed workflow | `docs/workflows/.md` | - | 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 | - - --- - - # What NOT to Do - - - **Never commit directly to `main`** — all changes go through a PR. - - **Never hardcode version numbers** in body text — update `README.md` and let automation propagate. - - **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.** - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw. - - **Never mix tabs and spaces** within a file — follow `.editorconfig`. - - **Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows** — always use `secrets.GH_TOKEN`. - - **Never remove `defined('_JEXEC') or die;`** from web-accessible PHP files. - - --- - - # PR Checklist - - Before opening a PR, verify: - - - [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`) - - [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry - - [ ] FILE INFORMATION headers updated in modified files - - [ ] CHANGELOG.md updated - - [ ] Tests pass - - --- - - # Key Policy Documents (MokoStandards) - - | 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 conventions | - | [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | - | [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "required" - files = [ - { - name = "ci-joomla.yml" - extension = "yml" - description = "Joomla-specific CI workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/ci-joomla.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - }, - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "repo_health.yml" - extension = "yml" - description = "Joomla-specific repository health check workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/joomla/repo_health.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/security.md" - }, - { - name = "joomla_issue.md" - always_overwrite = true - template = "templates/mokogitea/ISSUE_TEMPLATE/joomla_issue.md" - } - ] - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-extension)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/sync/joomla-api-mcp.def.tf b/definitions/sync/joomla-api-mcp.def.tf deleted file mode 100644 index 0c7ed5b..0000000 --- a/definitions/sync/joomla-api-mcp.def.tf +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Repository Sync Tracking Definition: mokoconsulting-tech/joomla-api-mcp - * - * Auto-generated by MokoStandards bulk sync on 2026-04-23T00:00:00+00:00 - * Platform : default-repository - * Description: MCP server for Joomla Web Services API operations - * - * DO NOT EDIT MANUALLY — this file is regenerated on every successful sync. - * To change what gets synced, edit api/definitions/default/default-repository.tf - * and re-run the bulk-repo-sync workflow. - */ - -locals { - sync_record = { - metadata = { - repo = "mokoconsulting-tech/joomla-api-mcp" - default_branch = "main" - detected_platform = "default-repository" - description = "MCP server for Joomla Web Services API operations" - sync_timestamp = "2026-04-23T00:00:00+00:00" - source_repo = "mokoconsulting-tech/MokoStandards" - base_definition = "api/definitions/default/default-repository.tf" - } - - sync_stats = { - total_files = 0 - created_files = 0 - updated_files = 0 - skipped_files = 0 - } - - synced_files = [] - - skipped_files = [ - { path = "README.md" reason = "README — never overwritten" }, - { path = "CHANGELOG.md" reason = "CHANGELOG — never overwritten" }, - { path = "CONTRIBUTING.md" reason = "Preserved (always_overwrite=false)" }, - { path = "SECURITY.md" reason = "Preserved (always_overwrite=false)" }, - { path = "CODE_OF_CONDUCT.md" reason = "Preserved (always_overwrite=false)" }, - { path = "ROADMAP.md" reason = "Preserved (always_overwrite=false)" }, - ] - } -} diff --git a/lib/Enterprise/DefinitionParser.php b/lib/Enterprise/DefinitionParser.php deleted file mode 100644 index bebbcf2..0000000 --- a/lib/Enterprise/DefinitionParser.php +++ /dev/null @@ -1,501 +0,0 @@ - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: MokoStandards.Enterprise - * INGROUP: MokoStandards - * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform - * PATH: /lib/Enterprise/DefinitionParser.php - * BRIEF: Parses Terraform HCL repository definition files into a flat sync-file list - */ - -declare(strict_types=1); - -namespace MokoEnterprise; - -/** - * Definition Parser - * - * Parses the Terraform HCL repository definition files stored in - * definitions/default/ and returns a flat list of file sync entries. - * - * File blocks that carry either a `template` field (external file path) or a - * `stub_content` heredoc (inline content) are returned — these are the files - * that the bulk-sync process should push to remote repositories. - * - * When both `stub_content` and `template` are present in the same block, - * `stub_content` takes priority (the definition file is authoritative). - * - * Each returned entry is an associative array with one of two shapes: - * - * External-file entry (legacy, uses `template` path): - * 'source' => string — path relative to the MokoStandards repo root - * 'destination' => string — path in the target repository - * 'always_overwrite' => bool — true: overwrite existing file; false: create-only - * - * Inline-content entry (uses `stub_content` heredoc): - * 'inline_content' => string — rendered template content (ready to push) - * 'destination' => string — path in the target repository - * 'always_overwrite' => bool — true: overwrite existing file; false: create-only - * - * @since 04.00.00 - */ -class DefinitionParser -{ - /** Map platform slug → definition file basename */ - private const PLATFORM_DEFINITION_MAP = [ - 'crm-module' => 'crm-module.tf', - 'waas-component' => 'waas-component.tf', - 'generic-repository' => 'generic-repository.tf', - 'default-repository' => 'default-repository.tf', - 'standards' => 'standards-repository.tf', - ]; - - /** Default definition used when platform has no specific file */ - private const FALLBACK_DEFINITION = 'default-repository.tf'; - - /** Directory containing the base definition files */ - private const DEFINITIONS_DIR = 'definitions/default'; - - // ----------------------------------------------------------------------- - // Public API - // ----------------------------------------------------------------------- - - /** - * Parse a definition file by platform slug. - * - * @param string $platform e.g. 'crm-module', 'waas-component' - * @param string $repoRoot Absolute path to the MokoStandards repository root - * @return array - */ - public function parseForPlatform(string $platform, string $repoRoot): array - { - $basename = self::PLATFORM_DEFINITION_MAP[$platform] ?? self::FALLBACK_DEFINITION; - $path = rtrim($repoRoot, '/') . '/' . self::DEFINITIONS_DIR . '/' . $basename; - - if (!file_exists($path)) { - $fallback = rtrim($repoRoot, '/') . '/' . self::DEFINITIONS_DIR . '/' . self::FALLBACK_DEFINITION; - if (!file_exists($fallback)) { - return []; - } - $path = $fallback; - } - - return $this->parseFile($path); - } - - /** - * Parse a definition file at an explicit filesystem path. - * - * @param string $filePath Absolute path to the .tf definition file - * @return array - */ - public function parseFile(string $filePath): array - { - if (!file_exists($filePath)) { - return []; - } - - $content = file_get_contents($filePath); - if ($content === false) { - return []; - } - - return $this->parse($content); - } - - /** - * Parse raw HCL content. - * - * @param string $content Raw .tf file content - * @return array - */ - public function parse(string $content): array - { - $entries = []; - - // root_files = [ { ... }, ... ] - $rootFilesContent = $this->extractNamedArray($content, 'root_files'); - if ($rootFilesContent !== null) { - $entries = array_merge($entries, $this->parseFileBlocks($rootFilesContent, '')); - } - - // directories = [ { ... }, ... ] - $dirsContent = $this->extractNamedArray($content, 'directories'); - if ($dirsContent !== null) { - $entries = array_merge($entries, $this->parseDirectories($dirsContent)); - } - - return $entries; - } - - // ----------------------------------------------------------------------- - // Internal parsing helpers - // ----------------------------------------------------------------------- - - /** - * Locate `name = [` inside $content and return the content between the - * outermost `[` and its matching `]`, or null if not found. - */ - private function extractNamedArray(string $content, string $name): ?string - { - $pattern = '/\b' . preg_quote($name, '/') . '\s*=\s*\[/'; - - // Build a mask of heredoc regions so the regex doesn't match inside them. - // Replace heredoc content with spaces (preserving offsets) before matching. - $masked = $content; - $len = strlen($content); - $i = 0; - while ($i < $len - 1) { - if ($content[$i] === '<' && $content[$i + 1] === '<') { - $heredocEnd = $this->skipHeredoc($content, $i, $len); - // Blank out the heredoc region in the masked copy - for ($k = $i; $k < $heredocEnd && $k < $len; $k++) { - $masked[$k] = ($content[$k] === "\n") ? "\n" : ' '; - } - $i = $heredocEnd; - continue; - } - $i++; - } - - if (!preg_match($pattern, $masked, $match, PREG_OFFSET_CAPTURE)) { - return null; - } - // Position of the `[` at the end of the matched string — use original content - $openPos = $match[0][1] + strlen($match[0][0]) - 1; - return $this->extractBetweenPair($content, $openPos, '[', ']'); - } - - /** - * Starting at $pos (which must hold $open), walk forward counting depth - * until the matching $close is found. Returns the content between them - * (exclusive), or null on malformed input. - */ - private function extractBetweenPair(string $content, int $pos, string $open, string $close): ?string - { - if (!isset($content[$pos]) || $content[$pos] !== $open) { - return null; - } - - $depth = 0; - $start = $pos; - $len = strlen($content); - - for ($i = $pos; $i < $len; $i++) { - // Skip heredoc regions — they contain unbalanced brackets in markdown/code - if ($content[$i] === '<' && isset($content[$i + 1]) && $content[$i + 1] === '<') { - $i = $this->skipHeredoc($content, $i, $len) - 1; // -1 because for loop increments - continue; - } - if ($content[$i] === $open) { - $depth++; - } elseif ($content[$i] === $close) { - $depth--; - if ($depth === 0) { - return substr($content, $start + 1, $i - $start - 1); - } - } - } - - return null; // unterminated - } - - /** - * Split $content into top-level `{ … }` blocks (depth 1 only). - * - * Heredoc sections (`<<-WORD … WORD` and `<skipHeredoc($content, $i, $len); - continue; - } - - if ($content[$i] === '{') { - if ($depth === 0) { - $start = $i; - } - $depth++; - } elseif ($content[$i] === '}') { - $depth--; - if ($depth === 0 && $start !== null) { - $blocks[] = substr($content, $start + 1, $i - $start - 1); - $start = null; - } - } - $i++; - } - - return $blocks; - } - - /** - * Advance past a HCL heredoc starting at position $i. - * - * Supports both `< - */ - private function parseFileBlocks(string $arrayContent, string $dirPath): array - { - $entries = []; - foreach ($this->splitBlocks($arrayContent) as $block) { - $entry = $this->parseFileBlock($block, $dirPath); - if ($entry !== null) { - $entries[] = $entry; - } - } - return $entries; - } - - /** - * Parse a single file block `{ name = "…", template = "…", … }` or - * `{ name = "…", stub_content = <<-EOT … EOT, … }`. - * - * When a `stub_content` heredoc is present it takes priority over a - * `template` file-path reference. Returns null when the block has - * neither (structural-only entry that should not be synced). - * - * @return array{source?: string, inline_content?: string, destination: string, always_overwrite: bool}|null - */ - private function parseFileBlock(string $block, string $dirPath): ?array - { - // --- try stub_content heredoc first (preferred) --- - $inlineContent = $this->extractHeredoc($block, 'stub_content'); - - // --- fall back to stub_content as a quoted string (e.g. "line1\nline2") --- - if ($inlineContent === null) { - if (preg_match('/\bstub_content\s*=\s*"((?:[^"\\\\]|\\\\.)*)"/', $block, $m)) { - $inlineContent = stripcslashes($m[1]); - } - } - - // --- fall back to external template path --- - $source = null; - if ($inlineContent === null) { - if (!preg_match('/\btemplate\s*=\s*"([^"]+)"/', $block, $m)) { - return null; // neither inline content nor template → structural entry - } - $source = $m[1]; - } - - // name is required - if (!preg_match('/\bname\s*=\s*"([^"]+)"/', $block, $m)) { - return null; - } - $filename = $m[1]; - - // destination_filename overrides name - if (preg_match('/\bdestination_filename\s*=\s*"([^"]+)"/', $block, $m)) { - $filename = $m[1]; - } - - // destination_path overrides dirPath - if (preg_match('/\bdestination_path\s*=\s*"([^"]+)"/', $block, $m)) { - $dp = trim($m[1], '/'); - $destination = ($dp === '' || $dp === '.') ? $filename : "{$dp}/{$filename}"; - } else { - $destination = $dirPath === '' ? $filename : "{$dirPath}/{$filename}"; - } - - // always_overwrite — default true for all template-driven files - $alwaysOverwrite = true; - if (preg_match('/\balways_overwrite\s*=\s*(true|false)\b/', $block, $m)) { - $alwaysOverwrite = ($m[1] === 'true'); - } - - // protected — when true, file is never overwritten even with --force - $protected = false; - if (preg_match('/\bprotected\s*=\s*(true|false)\b/', $block, $m)) { - $protected = ($m[1] === 'true'); - } - - if ($inlineContent !== null) { - return [ - 'inline_content' => $inlineContent, - 'destination' => $destination, - 'always_overwrite' => $alwaysOverwrite, - 'protected' => $protected, - ]; - } - - return [ - 'source' => $source, - 'destination' => $destination, - 'always_overwrite' => $alwaysOverwrite, - 'protected' => $protected, - ]; - } - - /** - * Extract a heredoc value for the given field name from a block string. - * - * Handles both `< (strlen($l) >= $minIndent) ? substr($l, $minIndent) : $l, - $lines - ); - $rawContent = implode("\n", $lines); - } - - return $rawContent; - } - - /** - * Walk the `directories = [ … ]` array, descending into every - * `subdirectories` block recursively. - * - * @return array - */ - private function parseDirectories(string $dirsArrayContent): array - { - $entries = []; - foreach ($this->splitBlocks($dirsArrayContent) as $block) { - $entries = array_merge($entries, $this->parseDirectoryBlock($block)); - } - return $entries; - } - - /** - * Process one directory block: extract its path, parse its files, and - * recurse into any subdirectories. - * - * @return array - */ - private function parseDirectoryBlock(string $block): array - { - $entries = []; - - // Determine the path prefix for files inside this directory - $dirPath = ''; - if (preg_match('/\bpath\s*=\s*"([^"]+)"/', $block, $m)) { - $dirPath = $m[1]; - } - - // files = [ … ] inside this directory - $filesContent = $this->extractNamedArray($block, 'files'); - if ($filesContent !== null) { - $entries = array_merge($entries, $this->parseFileBlocks($filesContent, $dirPath)); - } - - // subdirectories = [ … ] — recurse - $subdirsContent = $this->extractNamedArray($block, 'subdirectories'); - if ($subdirsContent !== null) { - foreach ($this->splitBlocks($subdirsContent) as $subBlock) { - $entries = array_merge($entries, $this->parseDirectoryBlock($subBlock)); - } - } - - return $entries; - } -} diff --git a/lib/Enterprise/MokoStandardsParser.php b/lib/Enterprise/MokoStandardsParser.php index 2cd032a..842f0f0 100644 --- a/lib/Enterprise/MokoStandardsParser.php +++ b/lib/Enterprise/MokoStandardsParser.php @@ -37,7 +37,7 @@ class MokoStandardsParser public const NAMESPACE_URI = 'https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API'; public const STANDARDS_SOURCE = 'https://git.mokoconsulting.tech/MokoConsulting/MokoStandards'; - /** Valid platform slugs — must match definitions/default/*.tf filenames. */ + /** Valid platform slugs — must match Template-* repo names. */ public const VALID_PLATFORMS = [ 'default-repository', 'crm-module', diff --git a/lib/Enterprise/RepositorySynchronizer.php b/lib/Enterprise/RepositorySynchronizer.php index 9cb16d2..b89ee60 100644 --- a/lib/Enterprise/RepositorySynchronizer.php +++ b/lib/Enterprise/RepositorySynchronizer.php @@ -32,6 +32,7 @@ use RuntimeException; */ class RepositorySynchronizer { + /** @deprecated Sync definitions removed — Template repos are now canonical */ private const SYNC_DEFINITION_DIR = 'definitions/sync'; /** Override file path — resolved at runtime via adapter's getMetadataDir(). */ private const SYNC_OVERRIDE_FILE_SUFFIX = 'override.tf'; @@ -45,7 +46,6 @@ class RepositorySynchronizer private AuditLogger $logger; private MetricsCollector $metrics; private CheckpointManager $checkpoints; - private DefinitionParser $definitionParser; private MokoStandardsParser $manifestParser; /** @@ -55,7 +55,6 @@ class RepositorySynchronizer * @param AuditLogger $logger Audit logger * @param MetricsCollector $metrics Metrics collector * @param CheckpointManager|null $checkpoints Checkpoint manager - * @param DefinitionParser|null $definitionParser Definition parser * @param GitPlatformAdapter|null $adapter Platform adapter (auto-created from ApiClient if null) */ public function __construct( @@ -63,14 +62,12 @@ class RepositorySynchronizer AuditLogger $logger, MetricsCollector $metrics, ?CheckpointManager $checkpoints = null, - ?DefinitionParser $definitionParser = null, ?GitPlatformAdapter $adapter = null ) { $this->adapter = $adapter ?? new MokoGiteaAdapter($apiClient); $this->logger = $logger; $this->metrics = $metrics; $this->checkpoints = $checkpoints ?? new CheckpointManager('.checkpoints'); - $this->definitionParser = $definitionParser ?? new DefinitionParser(); $this->manifestParser = new MokoStandardsParser(); } diff --git a/templates/governance.yml b/templates/governance.yml new file mode 100644 index 0000000..5a9925e --- /dev/null +++ b/templates/governance.yml @@ -0,0 +1,86 @@ +# governance.yml — Repository governance configuration +# Place this file in each Template-* repo to define branch protections, +# labels, secrets, variables, and repository settings for governed repos. +# +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# Schema Version: 1.0 + +schema_version: "1.0" + +branch_protections: + - pattern: main + require_pull_request: true + required_approvals: 0 + dismiss_stale_reviews: true + block_on_rejected_reviews: true + restrict_pushes: true + push_whitelist: [jmiller] + enable_force_push: true + force_push_whitelist: [jmiller] + enforce_admins: false + - pattern: dev + require_pull_request: false + restrict_pushes: false + enable_force_push: true + force_push_whitelist: [jmiller] + - pattern: "rc/*" + require_pull_request: false + restrict_pushes: false + enable_force_push: true + force_push_whitelist: [jmiller] + - pattern: "beta/*" + require_pull_request: false + restrict_pushes: false + enable_force_push: true + force_push_whitelist: [jmiller] + - pattern: "alpha/*" + require_pull_request: false + restrict_pushes: false + enable_force_push: true + force_push_whitelist: [jmiller] + +labels: + - name: bug + color: d73a4a + description: "Something isn't working" + - name: enhancement + color: a2eeef + description: "New feature or request" + - name: documentation + color: "0075ca" + description: "Improvements or additions to documentation" + - name: security + color: ee0701 + description: "Security vulnerability or concern" + +secrets: + - name: GA_TOKEN + description: "Gitea API token for automation" + required: true + scope: org + - name: GH_TOKEN + description: "GitHub PAT for mirror operations" + required: false + scope: org + +variables: + - name: GITEA_URL + description: "Gitea instance URL" + default: "https://git.mokoconsulting.tech" + scope: org + - name: GITEA_ORG + description: "Gitea organization name" + default: "MokoConsulting" + scope: org + +repo_settings: + has_issues: true + has_projects: true + has_wiki: false + has_discussions: false + allow_merge_commit: true + allow_squash_merge: true + allow_rebase_merge: false + delete_branch_on_merge: true + allow_auto_merge: false diff --git a/definitions/manifest-schema.xsd b/templates/schemas/manifest-schema.xsd similarity index 100% rename from definitions/manifest-schema.xsd rename to templates/schemas/manifest-schema.xsd diff --git a/validate/auto_detect_platform.php b/validate/auto_detect_platform.php index 853fba1..c752343 100755 --- a/validate/auto_detect_platform.php +++ b/validate/auto_detect_platform.php @@ -87,8 +87,8 @@ class AutoDetectPlatform extends CliFramework } if (!is_dir($schemaDir)) { - $this->log("Schema directory not found: {$schemaDir}", 'ERROR'); - return 3; + $this->log("Schema directory not found: {$schemaDir} (schema validation skipped)", 'WARN'); + $schemaDir = ''; } $this->log("Analyzing repository: {$repoPath}", 'INFO');