Files
moko-platform/validate/check_enterprise_readiness.php
Jonathan Miller cbfa23c4c4
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Scripts governance (push) Successful in 5s
Generic: Repo Health / Release configuration (push) Successful in 5s
Generic: Repo Health / Repository health (push) Successful in 12s
Platform: moko-platform CI / Gate 1: Code Quality (push) Successful in 45s
Platform: moko-platform CI / CI Summary (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Successful in 5s
Universal: PR Check / Build RC Package (pull_request) Successful in 2s
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Failing after 44s
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Failing after 48s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Failing after 48s
Platform: moko-platform CI / Gate 4: Governance (push) Successful in 48s
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Failing after 50s
Platform: moko-platform CI / Gate 5: Template Integrity (push) Failing after 12s
Platform: moko-platform CI / Gate 1: Code Quality (pull_request) Successful in 1m13s
Platform: moko-platform CI / Gate 5: Template Integrity (pull_request) Failing after 5s
Platform: moko-platform CI / Gate 3: Self-Health Check (pull_request) Failing after 42s
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (pull_request) Failing after 45s
Platform: moko-platform CI / Gate 4: Governance (pull_request) Successful in 44s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (pull_request) Failing after 47s
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (pull_request) Failing after 49s
fix: PHPStan level 0 → 2 — fix 67 type errors across 18 files
Real bugs found and fixed:
- bulk_joomla_template: $org undefined in heredoc (missing parameter)
- RepositorySynchronizer: $root undefined (should be $repoRoot), duplicate array key
- RepositoryHealthChecker: wrong class name (UnifiedValidation → UnifiedValidator)
- scan_drift: missing $adapter property declaration
- auto_detect_platform: wrong method name (detectProjectType → detect)
- EnterpriseReadinessValidator: void return used as value
- check_client_theme: extra parameter to printSummary()
- ApiClient: unused constructor parameter now stored
- GitPlatformAdapter: added listBranches/getCloneUrl/cloneRepo to interface
- MokoGiteaAdapter/GitHubAdapter: implemented new interface methods

3 legacy CLIApp scripts excluded (need migration to CliFramework):
  repo_cleanup.php, push_files.php, joomla_release.php

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-25 19:29:52 -05:00

252 lines
8.3 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* FILE INFORMATION
* DEFGROUP: MokoStandards.Scripts.Validate
* INGROUP: MokoStandards
* REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
* PATH: /validate/check_enterprise_readiness.php
* BRIEF: Enterprise readiness checker - PHP implementation
*/
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use MokoEnterprise\{
AuditLogger,
CliFramework,
SecurityValidator,
PluginFactory,
ProjectTypeDetector
};
/**
* Enterprise Readiness Checker
*
* Validates repository against enterprise standards
*/
class EnterpriseReadinessChecker extends CliFramework
{
private AuditLogger $logger;
private SecurityValidator $securityValidator;
private PluginFactory $pluginFactory;
private ?object $projectPlugin = null;
private array $results = [];
protected function configure(): void
{
$this->setDescription('Check enterprise readiness compliance');
$this->addArgument('--path', 'Repository path to check', '.');
$this->addArgument('--strict', 'Fail on any non-compliance', false);
}
protected function initialize(): void
{
parent::initialize();
$this->logger = new AuditLogger('enterprise_readiness');
$this->securityValidator = new SecurityValidator();
$metrics = new \MokoEnterprise\MetricsCollector();
$this->pluginFactory = new PluginFactory($this->logger, $metrics);
$this->log('Enterprise readiness checker initialized with plugin system');
}
protected function run(): int
{
$path = $this->getArgument('--path');
$strict = $this->getArgument('--strict');
$this->section('Initialising');
$this->log("Checking enterprise readiness: {$path}");
// Try to load the project plugin
$this->projectPlugin = $this->pluginFactory->createForProject($path);
if ($this->projectPlugin) {
$pluginName = $this->projectPlugin->getPluginName();
$projectType = $this->projectPlugin->getProjectType();
$this->log("Using plugin: {$pluginName} for type: {$projectType}");
// Use plugin's readiness check if available
$pluginReadiness = $this->projectPlugin->checkReadiness($path, []);
if (!empty($pluginReadiness)) {
$this->log("Plugin readiness check: " . ($pluginReadiness['ready'] ? 'READY' : 'NOT READY'));
$this->results['plugin_readiness'] = [
'passed' => $pluginReadiness['ready'],
'score' => $pluginReadiness['score'] ?? 0,
'blockers' => $pluginReadiness['blockers'] ?? [],
'warnings' => $pluginReadiness['warnings'] ?? [],
];
}
} else {
$this->log("No plugin found, using generic readiness checks");
}
// Run standard enterprise checks (backwards compatible)
$this->section('Enterprise libraries');
$this->checkEnterpriseLibraries($path);
$this->section('Monitoring & audit');
$this->checkMonitoring($path);
$this->checkAuditLogging($path);
$this->section('Security compliance');
$this->checkSecurityCompliance($path);
$this->section('Documentation');
$this->checkDocumentation($path);
// Display results using visual API
$this->section('Results');
$passed = 0;
$failed = 0;
foreach ($this->results as $result) {
$this->status($result['passed'], $result['check'], $result['passed'] ? '' : $result['message']);
if ($result['passed']) {
$passed++;
} else {
$failed++;
}
}
$this->printSummary($passed, $failed, $this->elapsed());
$failures = $failed;
if ($strict && $failures > 0) {
$this->error("Enterprise readiness check failed (strict mode): {$failures} issues found");
return 1;
}
if ($failures > 0) {
$this->warning("{$failures} enterprise readiness issues found");
} else {
$this->success('All enterprise readiness checks passed');
}
return 0;
}
private function checkEnterpriseLibraries(string $path): void
{
$required = ['ApiClient', 'AuditLogger', 'Config', 'ErrorRecovery', 'MetricsCollector'];
// Enterprise libs may live in vendor/ (Composer install) or lib/Enterprise/ (MokoStandards itself).
// A single vendor/ directory confirms the whole package is present — no need to check per-file.
$vendorPkg = "{$path}/vendor/mokoconsulting-tech/enterprise";
$inVendor = is_dir($vendorPkg);
foreach ($required as $library) {
$localFile = "{$path}/lib/Enterprise/{$library}.php";
$found = $inVendor || file_exists($localFile);
$this->addResult(
"Enterprise library: {$library}",
$found,
"Missing enterprise library (not in vendor/mokoconsulting-tech/enterprise or lib/Enterprise/)"
);
}
}
private function checkMonitoring(string $path): void
{
// Check for metrics collection
$metricsDir = "{$path}/var/logs/metrics";
$this->addResult(
'Metrics directory configured',
is_dir($metricsDir) || !file_exists($path . '/composer.json'),
'Metrics logging not configured'
);
// Check for monitoring documentation
$monitoringDocs = "{$path}/docs/monitoring";
$this->addResult(
'Monitoring documentation exists',
is_dir($monitoringDocs) || file_exists("{$path}/docs/monitoring.md"),
'Monitoring documentation not found'
);
}
private function checkAuditLogging(string $path): void
{
$auditDir = "{$path}/var/logs/audit";
$this->addResult(
'Audit logging directory configured',
is_dir($auditDir) || !file_exists($path . '/composer.json'),
'Audit logging not configured'
);
}
private function checkSecurityCompliance(string $path): void
{
// Check for security policy
$this->addResult(
'Security policy exists',
file_exists("{$path}/SECURITY.md") || file_exists("{$path}/.github/SECURITY.md"),
'SECURITY.md not found'
);
// Check for CodeQL configuration
$codeqlConfig = "{$path}/.github/codeql";
$this->addResult(
'CodeQL configured',
is_dir($codeqlConfig) || file_exists("{$path}/.github/codeql/codeql-config.yml"),
'CodeQL not configured'
);
// Run security scan on PHP files
if (is_dir("{$path}/src")) {
$this->securityValidator->scanDirectory("{$path}/src", ['.php']);
$findings = $this->securityValidator->getFindings();
$this->addResult(
'No security vulnerabilities in source code',
empty($findings),
count($findings) . ' security issues found'
);
}
}
private function checkDocumentation(string $path): void
{
// Check for architecture documentation
$this->addResult(
'Architecture documentation exists',
file_exists("{$path}/docs/architecture.md") ||
file_exists("{$path}/docs/guide/architecture.md"),
'Architecture documentation not found'
);
// Check for API documentation
$this->addResult(
'API documentation exists',
file_exists("{$path}/docs/api.md") || is_dir("{$path}/docs/api"),
'API documentation not found'
);
}
private function addResult(string $check, bool $passed, string $message): void
{
$this->results[] = [
'check' => $check,
'passed' => $passed,
'message' => $message,
];
}
private function displayResults(): void
{
// Results are now displayed directly in run() using visual API methods.
}
}
// Run the application
$app = new EnterpriseReadinessChecker();
exit($app->execute());