| @@ -0,0 +1,291 @@ | |||||
| # SKILLS.md | |||||
| ## Purpose | |||||
| This is the main skill index for AI coding agents working on **MindVisionCode PHP**. | |||||
| Read this file after `AGENTS.md`, then load only the focused skill files needed for the current task. | |||||
| --- | |||||
| ## Project Overview | |||||
| MindVisionCode PHP is a small PHP MVC framework inspired by a Classic ASP MVC framework style. | |||||
| The project favors: | |||||
| - Central dispatcher | |||||
| - Controllers and actions | |||||
| - ViewModels | |||||
| - Repository classes | |||||
| - Simple validation | |||||
| - Database migrations | |||||
| - Small, readable files | |||||
| - Minimal dependencies | |||||
| Do not turn this into Laravel, Symfony, Slim, CakePHP, or another large framework. | |||||
| --- | |||||
| ## Tech Stack | |||||
| - PHP 8.2+ | |||||
| - Composer | |||||
| - PSR-4 autoloading | |||||
| - PDO | |||||
| - PHP views | |||||
| - Optional SQLite/MySQL/SQL Server through PDO | |||||
| - Minimal dependencies | |||||
| --- | |||||
| ## Preferred Project Structure | |||||
| ```text | |||||
| project-root/ | |||||
| AGENTS.md | |||||
| .ai/ | |||||
| SKILLS.md | |||||
| skills/ | |||||
| php/ | |||||
| SKILL.md | |||||
| mvc/ | |||||
| SKILL.md | |||||
| database/ | |||||
| SKILL.md | |||||
| security/ | |||||
| SKILL.md | |||||
| testing/ | |||||
| SKILL.md | |||||
| workflow/ | |||||
| SKILL.md | |||||
| public/ | |||||
| index.php | |||||
| src/ | |||||
| Controller/ | |||||
| Service/ | |||||
| Repository/ | |||||
| Entity/ | |||||
| ValueObject/ | |||||
| ViewModel/ | |||||
| Http/ | |||||
| Routing/ | |||||
| Validation/ | |||||
| Database/ | |||||
| Migration/ | |||||
| templates/ | |||||
| config/ | |||||
| tests/ | |||||
| var/ | |||||
| cache/ | |||||
| logs/ | |||||
| vendor/ | |||||
| composer.json | |||||
| ``` | |||||
| Rules: | |||||
| - `public/` is the web root. | |||||
| - Do not expose `src/`, `config/`, `tests/`, `vendor/`, `.ai/`, or `.env` files through the web server. | |||||
| - Put application code under `src/`. | |||||
| - Put generated cache/log files under `var/` or another ignored runtime directory. | |||||
| - Keep secrets outside the web root. | |||||
| --- | |||||
| ## Setup Commands | |||||
| Install dependencies: | |||||
| ```bash | |||||
| composer install | |||||
| ``` | |||||
| Regenerate autoload files: | |||||
| ```bash | |||||
| composer dump-autoload | |||||
| ``` | |||||
| Run local server: | |||||
| ```bash | |||||
| php -S localhost:8000 -t public | |||||
| ``` | |||||
| Run basic tests: | |||||
| ```bash | |||||
| php tests/run.php | |||||
| ``` | |||||
| --- | |||||
| ## Request Flow | |||||
| ```text | |||||
| Browser | |||||
| → public/index.php | |||||
| → Request | |||||
| → Dispatcher | |||||
| → Router | |||||
| → Route | |||||
| → Controller | |||||
| → ViewModel/Repository/Service | |||||
| → View | |||||
| → Response | |||||
| ``` | |||||
| --- | |||||
| ## Skill Routes | |||||
| ### PHP Language, Style, Composer, OOP | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/php/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - PHP version decisions | |||||
| - PSR standards | |||||
| - Composer dependencies | |||||
| - Namespaces and autoloading | |||||
| - OOP design | |||||
| - Dependency injection | |||||
| - Documentation and PHPDoc | |||||
| - Performance and caching | |||||
| --- | |||||
| ### MVC Framework Architecture | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/mvc/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - Dispatcher changes | |||||
| - Router changes | |||||
| - Controllers and actions | |||||
| - ViewModels | |||||
| - PHP templates/views | |||||
| - HTTP request/response flow | |||||
| - Framework structure | |||||
| --- | |||||
| ### Database and Persistence | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/database/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - PDO | |||||
| - SQL | |||||
| - Repositories | |||||
| - Migrations | |||||
| - Transactions | |||||
| - Database configuration | |||||
| - SQLite/MySQL/SQL Server support | |||||
| --- | |||||
| ### Security | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/security/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - Input validation | |||||
| - Output escaping | |||||
| - Passwords | |||||
| - Authentication | |||||
| - Authorization | |||||
| - Sessions | |||||
| - CSRF | |||||
| - Secrets | |||||
| - Error disclosure | |||||
| - Dangerous functions | |||||
| --- | |||||
| ### Testing and Quality | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/testing/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - Tests | |||||
| - Test runner changes | |||||
| - Static analysis | |||||
| - Composer quality scripts | |||||
| - Code style tools | |||||
| - Verification steps | |||||
| --- | |||||
| ### Agent Workflow | |||||
| Read: | |||||
| ```text | |||||
| ./.ai/skills/workflow/SKILL.md | |||||
| ``` | |||||
| Use for: | |||||
| - Multi-file changes | |||||
| - Pull-request style review | |||||
| - Legacy PHP changes | |||||
| - Non-negotiable rules | |||||
| - Response format | |||||
| - Skill feedback updates | |||||
| --- | |||||
| ## Default Coding Rules | |||||
| - Keep code simple and readable. | |||||
| - Prefer small classes. | |||||
| - Use typed properties and return types where practical. | |||||
| - Avoid hidden magic. | |||||
| - Do not add dependencies without a clear reason. | |||||
| - Preserve the framework style. | |||||
| - Explain any architectural changes. | |||||
| --- | |||||
| ## Default Security Rules | |||||
| - Validate input. | |||||
| - Escape output. | |||||
| - Use prepared statements for SQL. | |||||
| - Do not expose sensitive errors. | |||||
| - Check authorization separately from authentication. | |||||
| --- | |||||
| ## Default Testing Rules | |||||
| - Add or update tests for meaningful behavior changes. | |||||
| - Explain how to verify changes. | |||||
| - If tests are not added, explain why. | |||||
| @@ -0,0 +1,122 @@ | |||||
| # Database Skill | |||||
| ## Purpose | |||||
| Use this skill for PDO, repositories, SQL, migrations, transactions, database configuration, and persistence rules. | |||||
| --- | |||||
| ## Database Stack | |||||
| Preferred database access: | |||||
| - PDO | |||||
| - Repositories or data access classes | |||||
| - Optional SQLite, MySQL, or SQL Server through PDO | |||||
| - Prepared statements for all untrusted values | |||||
| --- | |||||
| ## Database Access Rules | |||||
| Use PDO or a well-maintained database abstraction layer/ORM. | |||||
| Never concatenate untrusted input into SQL. | |||||
| Bad: | |||||
| ```php | |||||
| $sql = "SELECT * FROM users WHERE id = " . $_GET['id']; | |||||
| ``` | |||||
| Good: | |||||
| ```php | |||||
| $stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id'); | |||||
| $stmt->bindValue(':id', $id, PDO::PARAM_INT); | |||||
| $stmt->execute(); | |||||
| $user = $stmt->fetch(PDO::FETCH_ASSOC); | |||||
| ``` | |||||
| Rules: | |||||
| - Use prepared statements and bound parameters. | |||||
| - Validate input before using it in writes. | |||||
| - Keep SQL out of templates. | |||||
| - Keep database access out of controllers where practical. | |||||
| - Use transactions when multiple writes must succeed or fail together. | |||||
| - Do not rely only on client-side validation. | |||||
| - Do not expose raw database errors to users. | |||||
| --- | |||||
| ## Transactions | |||||
| Use transactions when multiple writes must succeed or fail together. | |||||
| Example: | |||||
| ```php | |||||
| $pdo->beginTransaction(); | |||||
| try { | |||||
| $orders->create($order); | |||||
| $auditLog->record('order.created', $order->id()); | |||||
| $pdo->commit(); | |||||
| } catch (Throwable $e) { | |||||
| $pdo->rollBack(); | |||||
| throw $e; | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Repository Rules | |||||
| - Put persistence logic in repositories or data access classes. | |||||
| - Keep repositories focused around a table, aggregate, or use case. | |||||
| - Do not let repositories render HTML. | |||||
| - Do not let repositories read directly from `$_GET`, `$_POST`, or other superglobals. | |||||
| - Return domain objects, entities, DTOs, arrays, or ViewModels according to existing project convention. | |||||
| - Prefer explicit methods such as `findById`, `findAllActive`, and `save` over generic magic calls. | |||||
| --- | |||||
| ## Migration Rules | |||||
| - Keep migrations small and reversible when practical. | |||||
| - Document destructive migrations clearly. | |||||
| - Do not mix schema changes with unrelated feature logic. | |||||
| - Use project migration conventions before inventing new ones. | |||||
| - Support SQLite/MySQL/SQL Server differences explicitly when the project targets multiple engines. | |||||
| --- | |||||
| ## SQL Safety Checklist | |||||
| Before completing database work, verify: | |||||
| - [ ] SQL uses prepared statements or a safe query builder. | |||||
| - [ ] Untrusted values are never concatenated into SQL. | |||||
| - [ ] Writes validate input server-side. | |||||
| - [ ] Multi-step writes use transactions where needed. | |||||
| - [ ] Database errors are logged safely and not displayed raw to users. | |||||
| - [ ] Schema changes are documented. | |||||
| - [ ] Tests or verification steps cover the changed behavior. | |||||
| --- | |||||
| ## Database Configuration | |||||
| - Keep database credentials out of source control. | |||||
| - Prefer environment variables or ignored local config files for secrets. | |||||
| - Provide safe examples such as `.env.example`. | |||||
| - Do not commit production DSNs, passwords, tokens, or private keys. | |||||
| Example `.env.example`: | |||||
| ```text | |||||
| APP_ENV=local | |||||
| APP_DEBUG=true | |||||
| DATABASE_URL=mysql://user:password@localhost:3306/app | |||||
| ``` | |||||
| @@ -0,0 +1,201 @@ | |||||
| # MVC Framework Skill | |||||
| ## Purpose | |||||
| Use this skill for MindVisionCode PHP framework architecture, routing, dispatching, controllers, actions, ViewModels, templates, and HTTP request/response flow. | |||||
| --- | |||||
| ## Project Identity | |||||
| This project is a small PHP MVC framework called **MindVisionCode PHP**. | |||||
| It is intentionally inspired by a Classic ASP MVC framework style: | |||||
| - Central dispatcher | |||||
| - Controllers and actions | |||||
| - ViewModels | |||||
| - Repository classes | |||||
| - Simple validation | |||||
| - Database migrations | |||||
| - Small, readable files | |||||
| - Minimal dependencies | |||||
| Do not turn this into Laravel, Symfony, Slim, CakePHP, or another large framework. | |||||
| --- | |||||
| ## Request Flow | |||||
| ```text | |||||
| Browser | |||||
| → public/index.php | |||||
| → Request | |||||
| → Dispatcher | |||||
| → Router | |||||
| → Route | |||||
| → Controller | |||||
| → ViewModel/Repository/Service | |||||
| → View | |||||
| → Response | |||||
| ``` | |||||
| --- | |||||
| ## Project Structure | |||||
| Preferred structure: | |||||
| ```text | |||||
| project-root/ | |||||
| public/ | |||||
| index.php | |||||
| src/ | |||||
| Controller/ | |||||
| Service/ | |||||
| Repository/ | |||||
| Entity/ | |||||
| ValueObject/ | |||||
| ViewModel/ | |||||
| Http/ | |||||
| Routing/ | |||||
| Validation/ | |||||
| Database/ | |||||
| Migration/ | |||||
| templates/ | |||||
| config/ | |||||
| tests/ | |||||
| var/ | |||||
| cache/ | |||||
| logs/ | |||||
| vendor/ | |||||
| composer.json | |||||
| ``` | |||||
| Rules: | |||||
| - `public/` is the web root. | |||||
| - Do not expose `src/`, `config/`, `tests/`, `vendor/`, `.ai/`, or `.env` files through the web server. | |||||
| - Put application code under `src/`. | |||||
| - Put generated cache/log files under `var/` or another ignored runtime directory. | |||||
| - Keep secrets outside the web root. | |||||
| --- | |||||
| ## Development Commands | |||||
| Install dependencies: | |||||
| ```bash | |||||
| composer install | |||||
| ``` | |||||
| Regenerate autoload files: | |||||
| ```bash | |||||
| composer dump-autoload | |||||
| ``` | |||||
| Run local server: | |||||
| ```bash | |||||
| php -S localhost:8000 -t public | |||||
| ``` | |||||
| Run basic tests: | |||||
| ```bash | |||||
| php tests/run.php | |||||
| ``` | |||||
| --- | |||||
| ## Framework Coding Rules | |||||
| - Keep code simple and readable. | |||||
| - Prefer small classes. | |||||
| - Use typed properties and return types where practical. | |||||
| - Avoid hidden magic. | |||||
| - Do not add dependencies without a clear reason. | |||||
| - Preserve the framework style. | |||||
| - Explain any architectural changes. | |||||
| --- | |||||
| ## Controller Rules | |||||
| - Keep controllers thin. | |||||
| - Validate request method and request shape at the boundary. | |||||
| - Do not put database query details directly in controllers when a repository or service is more appropriate. | |||||
| - Do not put template rendering logic inside business services. | |||||
| - Return or produce a response through the framework’s response mechanism. | |||||
| --- | |||||
| ## ViewModel Rules | |||||
| - Use ViewModels to shape data for views. | |||||
| - Keep ViewModels simple and explicit. | |||||
| - Avoid passing raw database rows directly into complex templates when a ViewModel would make the template clearer. | |||||
| - Do not put database access inside ViewModels unless the existing project convention explicitly does that. | |||||
| --- | |||||
| ## Templates and Views | |||||
| Keep presentation separate from business logic. | |||||
| Rules: | |||||
| - Do not query the database from templates. | |||||
| - Do not place business rules in templates. | |||||
| - Escape output by default. | |||||
| - Prefer simple view models or arrays passed into templates. | |||||
| - Use a template engine with automatic escaping only if it fits the project and does not make the framework unnecessarily large. | |||||
| Plain PHP template example: | |||||
| ```php | |||||
| <h1><?= e($pageTitle) ?></h1> | |||||
| <ul> | |||||
| <?php foreach ($users as $user): ?> | |||||
| <li><?= e($user->name()) ?></li> | |||||
| <?php endforeach; ?> | |||||
| </ul> | |||||
| ``` | |||||
| --- | |||||
| ## HTTP and Web Application Rules | |||||
| Rules: | |||||
| - Use the front controller pattern where appropriate. | |||||
| - Keep routing separate from business logic. | |||||
| - Validate request methods. | |||||
| - Use CSRF protection for state-changing forms. | |||||
| - Use proper HTTP status codes. | |||||
| - Redirect after successful POST to avoid duplicate form submission. | |||||
| - Do not trust headers such as `X-Forwarded-For` unless configured behind a trusted proxy. | |||||
| Example POST guard: | |||||
| ```php | |||||
| if ($_SERVER['REQUEST_METHOD'] !== 'POST') { | |||||
| http_response_code(405); | |||||
| exit('Method Not Allowed'); | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Architecture Guardrail | |||||
| When adding features, preserve the small-framework character: | |||||
| - Prefer explicit code over hidden convention. | |||||
| - Prefer simple routing over complex annotation systems. | |||||
| - Prefer plain PHP views unless a project decision says otherwise. | |||||
| - Prefer focused services and repositories over large framework abstractions. | |||||
| - Do not introduce a large package just to solve a small problem. | |||||
| @@ -0,0 +1,331 @@ | |||||
| # PHP Skill | |||||
| ## Purpose | |||||
| Use this skill for PHP language rules, coding style, Composer, namespacing, autoloading, object-oriented design, dependency injection, documentation, and performance. | |||||
| Source reference: | |||||
| ```text | |||||
| https://phptherightway.com/ | |||||
| ``` | |||||
| --- | |||||
| ## Core Philosophy | |||||
| Write PHP that is: | |||||
| - Readable before clever. | |||||
| - Secure by default. | |||||
| - Consistent with community standards. | |||||
| - Easy to test, debug, and refactor. | |||||
| - Separated by responsibility. | |||||
| PHP does not have only one canonical “right way,” so prefer widely accepted standards, documented project conventions, and clear tradeoffs over personal style. | |||||
| --- | |||||
| ## PHP Version Standard | |||||
| Use the current stable PHP version supported by the project. | |||||
| Default expectation: | |||||
| ```text | |||||
| PHP 8.2+ | |||||
| ``` | |||||
| Do not introduce code that depends on unsupported PHP versions unless the project explicitly targets a legacy runtime. | |||||
| When adding a language feature, verify that it is supported by the project’s configured PHP version in `composer.json`. | |||||
| Example: | |||||
| ```json | |||||
| { | |||||
| "require": { | |||||
| "php": ">=8.2" | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Coding Style | |||||
| Follow recognized PHP standards unless the repository already defines stricter rules. | |||||
| Preferred standards: | |||||
| - PSR-1: Basic Coding Standard | |||||
| - PSR-12: Extended Coding Style | |||||
| - PSR-4: Autoloading | |||||
| Use automated tooling rather than manual formatting arguments. | |||||
| Recommended tools: | |||||
| ```bash | |||||
| composer require --dev squizlabs/php_codesniffer | |||||
| composer require --dev friendsofphp/php-cs-fixer | |||||
| ``` | |||||
| Example checks: | |||||
| ```bash | |||||
| vendor/bin/phpcs --standard=PSR12 src tests | |||||
| vendor/bin/php-cs-fixer fix --dry-run --diff | |||||
| ``` | |||||
| Example fix: | |||||
| ```bash | |||||
| vendor/bin/php-cs-fixer fix | |||||
| ``` | |||||
| --- | |||||
| ## Naming Rules | |||||
| Use English names for code symbols and infrastructure. | |||||
| Good: | |||||
| ```php | |||||
| class InvoiceRepository | |||||
| { | |||||
| public function findByCustomerId(int $customerId): array | |||||
| { | |||||
| // ... | |||||
| } | |||||
| } | |||||
| ``` | |||||
| Avoid unclear abbreviations: | |||||
| ```php | |||||
| class InvRepo | |||||
| { | |||||
| public function fbcid($cid) | |||||
| { | |||||
| // ... | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Formatting Rules | |||||
| - Use `<?php` tags. Do not use short open tags. | |||||
| - Use strict types at the top of new PHP files when practical: | |||||
| ```php | |||||
| declare(strict_types=1); | |||||
| ``` | |||||
| - One class per file. | |||||
| - Match namespaces to directory structure. | |||||
| - Keep functions and methods small and focused. | |||||
| - Prefer explicit visibility: `public`, `protected`, or `private`. | |||||
| - Avoid global state unless required by the framework or legacy integration. | |||||
| --- | |||||
| ## Namespaces and Autoloading | |||||
| All new application classes must use namespaces. | |||||
| Use PSR-4 autoloading through Composer. | |||||
| Example `composer.json`: | |||||
| ```json | |||||
| { | |||||
| "autoload": { | |||||
| "psr-4": { | |||||
| "App\\": "src/" | |||||
| } | |||||
| }, | |||||
| "autoload-dev": { | |||||
| "psr-4": { | |||||
| "Tests\\": "tests/" | |||||
| } | |||||
| } | |||||
| } | |||||
| ``` | |||||
| After changing autoload rules, run: | |||||
| ```bash | |||||
| composer dump-autoload | |||||
| ``` | |||||
| Example class: | |||||
| ```php | |||||
| <?php | |||||
| declare(strict_types=1); | |||||
| namespace App\Service; | |||||
| final class InvoiceCalculator | |||||
| { | |||||
| public function calculateTotal(array $items): int | |||||
| { | |||||
| return array_sum(array_column($items, 'amountCents')); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Dependency Management | |||||
| Use Composer for PHP dependencies. | |||||
| Rules: | |||||
| - Add packages with `composer require` or `composer require --dev`. | |||||
| - Commit `composer.json` and `composer.lock` for applications. | |||||
| - Do not manually copy vendor libraries into the project. | |||||
| - Do not edit files under `vendor/`. | |||||
| - Prefer maintained packages with clear documentation, tests, and recent releases. | |||||
| - Remove unused packages. | |||||
| Commands: | |||||
| ```bash | |||||
| composer install | |||||
| composer update vendor/package | |||||
| composer audit | |||||
| composer validate | |||||
| ``` | |||||
| Use `composer update` intentionally. Do not casually update every dependency in unrelated work. | |||||
| --- | |||||
| ## Object-Oriented Design | |||||
| Prefer clear object-oriented code for domain and application logic. | |||||
| Example: | |||||
| ```php | |||||
| final class CustomerName | |||||
| { | |||||
| public function __construct(private string $value) | |||||
| { | |||||
| if (trim($value) === '') { | |||||
| throw new InvalidArgumentException('Customer name is required.'); | |||||
| } | |||||
| } | |||||
| public function value(): string | |||||
| { | |||||
| return $this->value; | |||||
| } | |||||
| } | |||||
| ``` | |||||
| Guidelines: | |||||
| - Keep controllers thin. | |||||
| - Put business rules in services or domain objects. | |||||
| - Put persistence logic in repositories or data access classes. | |||||
| - Use interfaces when multiple implementations are expected or when it improves testing. | |||||
| - Avoid huge “utility” classes. | |||||
| - Avoid magic methods unless they provide clear framework integration or a documented benefit. | |||||
| --- | |||||
| ## Dependency Injection | |||||
| Prefer dependency injection over creating dependencies inside classes. | |||||
| Good: | |||||
| ```php | |||||
| final class RegisterUser | |||||
| { | |||||
| public function __construct( | |||||
| private UserRepository $users, | |||||
| private PasswordHasher $passwords | |||||
| ) { | |||||
| } | |||||
| public function handle(string $email, string $plainPassword): void | |||||
| { | |||||
| $hash = $this->passwords->hash($plainPassword); | |||||
| $this->users->create($email, $hash); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| Avoid: | |||||
| ```php | |||||
| final class RegisterUser | |||||
| { | |||||
| public function handle(string $email, string $plainPassword): void | |||||
| { | |||||
| $users = new UserRepository(); | |||||
| $passwords = new PasswordHasher(); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| Rules: | |||||
| - Constructor injection is preferred for required dependencies. | |||||
| - Do not use service locators casually. | |||||
| - Do not hide dependencies in global variables. | |||||
| - Keep dependency containers at application boundaries, not inside domain logic. | |||||
| --- | |||||
| ## Documentation Rules | |||||
| Use PHPDoc where it adds clarity, especially for arrays, complex return values, and public APIs. | |||||
| Good: | |||||
| ```php | |||||
| /** | |||||
| * @return list<Customer> | |||||
| */ | |||||
| public function findActiveCustomers(): array | |||||
| { | |||||
| // ... | |||||
| } | |||||
| ``` | |||||
| Avoid noisy comments that repeat the code: | |||||
| ```php | |||||
| // Increment i by one. | |||||
| $i++; | |||||
| ``` | |||||
| Rules: | |||||
| - Explain why, not just what. | |||||
| - Document non-obvious tradeoffs. | |||||
| - Keep README setup instructions current. | |||||
| - Update examples when behavior changes. | |||||
| --- | |||||
| ## Performance and Caching | |||||
| Rules: | |||||
| - Measure before optimizing. | |||||
| - Avoid unnecessary database queries in loops. | |||||
| - Use pagination for large result sets. | |||||
| - Cache expensive reads where appropriate. | |||||
| - Use OPcache in production. | |||||
| - Do not cache user-specific sensitive data in shared caches without a clear key strategy. | |||||
| @@ -0,0 +1,232 @@ | |||||
| # Security Skill | |||||
| ## Purpose | |||||
| Use this skill for input validation, output escaping, passwords, authentication, authorization, sessions, CSRF, secrets, error disclosure, dangerous functions, serialization, and file/path safety. | |||||
| --- | |||||
| ## Security Baseline | |||||
| Treat all external data as untrusted. | |||||
| Untrusted data includes: | |||||
| - `$_GET` | |||||
| - `$_POST` | |||||
| - `$_REQUEST` | |||||
| - `$_COOKIE` | |||||
| - `$_SERVER` | |||||
| - uploaded files | |||||
| - request bodies | |||||
| - session values | |||||
| - database values originally supplied by users | |||||
| - third-party API responses | |||||
| --- | |||||
| ## Input Validation | |||||
| Validate on input. | |||||
| Example: | |||||
| ```php | |||||
| $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); | |||||
| if ($email === false || $email === null) { | |||||
| throw new InvalidArgumentException('A valid email address is required.'); | |||||
| } | |||||
| ``` | |||||
| Rules: | |||||
| - Validate type, range, length, format, and allowed values. | |||||
| - Validate server-side even when client-side validation exists. | |||||
| - Reject unexpected fields when appropriate. | |||||
| - Normalize data intentionally, not accidentally. | |||||
| --- | |||||
| ## Output Escaping | |||||
| Escape on output based on context. | |||||
| For HTML output: | |||||
| ```php | |||||
| function e(string $value): string | |||||
| { | |||||
| return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); | |||||
| } | |||||
| ``` | |||||
| Usage: | |||||
| ```php | |||||
| <p><?= e($user->name()) ?></p> | |||||
| ``` | |||||
| Rules: | |||||
| - Escape based on context: HTML, attribute, JavaScript, CSS, URL, SQL, shell. | |||||
| - Do not use the same escaping function for every context. | |||||
| - Prefer template engines with automatic escaping only when appropriate for the project. | |||||
| - Avoid allowing raw HTML from users. If required, sanitize with a proven whitelist sanitizer. | |||||
| - Use `escapeshellarg()` when passing controlled values to shell commands, and avoid shell execution when possible. | |||||
| - Never trust file paths supplied by users. | |||||
| - Reject path traversal values such as `../`, `/`, `\`, and null bytes when user-provided paths are not allowed. | |||||
| --- | |||||
| ## Passwords and Authentication | |||||
| Never store plain-text passwords. | |||||
| Use PHP’s password API: | |||||
| ```php | |||||
| $hash = password_hash($plainPassword, PASSWORD_DEFAULT); | |||||
| if (! password_verify($plainPassword, $hash)) { | |||||
| throw new RuntimeException('Invalid credentials.'); | |||||
| } | |||||
| ``` | |||||
| Rules: | |||||
| - Use `password_hash()` for new password hashes. | |||||
| - Use `password_verify()` for login checks. | |||||
| - Use `password_needs_rehash()` when algorithm/cost settings change. | |||||
| - Do not create your own password hashing algorithm. | |||||
| - Do not use general-purpose hashes like `md5`, `sha1`, or raw `sha256` for passwords. | |||||
| - Rate-limit login attempts. | |||||
| - Regenerate session IDs after login. | |||||
| - Use secure, HTTP-only, SameSite cookies for sessions. | |||||
| --- | |||||
| ## Authorization | |||||
| - Check authorization separately from authentication. | |||||
| - Do not assume logged-in means allowed. | |||||
| - Enforce permissions server-side. | |||||
| - Avoid hiding buttons as the only authorization control. | |||||
| - Prefer explicit permission checks near protected actions or service boundaries. | |||||
| --- | |||||
| ## CSRF | |||||
| Use CSRF protection for state-changing forms and unsafe HTTP methods. | |||||
| State-changing actions include: | |||||
| - Create | |||||
| - Update | |||||
| - Delete | |||||
| - Login/logout state changes | |||||
| - Password changes | |||||
| - Email changes | |||||
| - Permission changes | |||||
| --- | |||||
| ## Serialization and Data Exchange | |||||
| Do not call `unserialize()` on untrusted data. | |||||
| Prefer JSON for data exchange: | |||||
| ```php | |||||
| $data = json_decode($json, true, flags: JSON_THROW_ON_ERROR); | |||||
| $json = json_encode($data, JSON_THROW_ON_ERROR); | |||||
| ``` | |||||
| Rules: | |||||
| - Use `JSON_THROW_ON_ERROR` for new code. | |||||
| - Validate decoded data before using it. | |||||
| - Avoid PHP serialization for data that crosses trust boundaries. | |||||
| --- | |||||
| ## Configuration and Secrets | |||||
| Rules: | |||||
| - Keep secrets out of source control. | |||||
| - Do not commit passwords, API keys, private keys, tokens, or production DSNs. | |||||
| - Store configuration outside the public web root. | |||||
| - Use environment variables or ignored local config files for secrets. | |||||
| - Provide a safe example file such as `.env.example`. | |||||
| Example `.gitignore` entries: | |||||
| ```text | |||||
| .env | |||||
| .env.local | |||||
| /config/local.php | |||||
| /var/cache/ | |||||
| /var/log/ | |||||
| /vendor/ | |||||
| ``` | |||||
| --- | |||||
| ## Error Handling and Logging | |||||
| Development: | |||||
| - Show errors locally. | |||||
| - Log errors. | |||||
| - Use Xdebug when debugging complex issues. | |||||
| Production: | |||||
| - Do not display errors to users. | |||||
| - Log errors to a secure log destination. | |||||
| - Return safe, generic error messages. | |||||
| - Preserve enough context in logs for troubleshooting. | |||||
| Do not leak: | |||||
| - stack traces to users | |||||
| - SQL statements with secrets | |||||
| - environment variables | |||||
| - full filesystem paths | |||||
| - tokens or passwords | |||||
| Example: | |||||
| ```php | |||||
| try { | |||||
| $service->handle($request); | |||||
| } catch (Throwable $e) { | |||||
| $logger->error('Order processing failed.', [ | |||||
| 'exception' => $e, | |||||
| 'requestId' => $requestId, | |||||
| ]); | |||||
| http_response_code(500); | |||||
| echo 'An unexpected error occurred.'; | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Security Checklist | |||||
| Before completing any feature, verify: | |||||
| - [ ] All external input is validated. | |||||
| - [ ] All output is escaped for the correct context. | |||||
| - [ ] SQL uses prepared statements or safe query builders. | |||||
| - [ ] Authentication and authorization are checked server-side. | |||||
| - [ ] Secrets are not committed. | |||||
| - [ ] Errors are not exposed in production responses. | |||||
| - [ ] File uploads validate size, extension, MIME type, and storage path. | |||||
| - [ ] Passwords use `password_hash()` and `password_verify()`. | |||||
| - [ ] CSRF protection exists for state-changing requests. | |||||
| - [ ] Dangerous functions are avoided or justified: `eval`, `exec`, `shell_exec`, `system`, `passthru`, `unserialize`. | |||||
| - [ ] Dependencies have no known vulnerabilities according to `composer audit`. | |||||
| @@ -0,0 +1,162 @@ | |||||
| # Testing and Quality Skill | |||||
| ## Purpose | |||||
| Use this skill for tests, static analysis, quality gates, Composer scripts, verification steps, and code style checks. | |||||
| --- | |||||
| ## Testing Standard | |||||
| Automated tests are expected for new behavior. | |||||
| Preferred tools: | |||||
| - The project’s existing `tests/run.php` runner | |||||
| - PHPUnit, if the project adds or already uses it | |||||
| - Pest, if the project already uses it | |||||
| Rules: | |||||
| - Add or update tests with every meaningful behavior change. | |||||
| - Cover success paths and failure paths. | |||||
| - Unit-test business logic. | |||||
| - Integration-test database and framework wiring where useful. | |||||
| - Functional-test important user flows. | |||||
| - Avoid relying on `var_dump()` or manual browser testing as the only verification. | |||||
| --- | |||||
| ## Basic Test Command | |||||
| Run basic tests: | |||||
| ```bash | |||||
| php tests/run.php | |||||
| ``` | |||||
| If PHPUnit is installed: | |||||
| ```bash | |||||
| vendor/bin/phpunit | |||||
| ``` | |||||
| Example PHPUnit test: | |||||
| ```php | |||||
| final class InvoiceCalculatorTest extends TestCase | |||||
| { | |||||
| public function testItCalculatesTotalInCents(): void | |||||
| { | |||||
| $calculator = new InvoiceCalculator(); | |||||
| $total = $calculator->calculateTotal([ | |||||
| ['amountCents' => 1000], | |||||
| ['amountCents' => 2500], | |||||
| ]); | |||||
| self::assertSame(3500, $total); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| --- | |||||
| ## Static Analysis and Quality Gates | |||||
| Use static analysis when available. | |||||
| Recommended tools: | |||||
| ```bash | |||||
| composer require --dev phpstan/phpstan | |||||
| composer require --dev vimeo/psalm | |||||
| ``` | |||||
| Common quality commands: | |||||
| ```bash | |||||
| composer validate | |||||
| composer audit | |||||
| vendor/bin/phpcs --standard=PSR12 src tests | |||||
| vendor/bin/phpunit | |||||
| vendor/bin/phpstan analyse src tests | |||||
| ``` | |||||
| Do not ignore tool failures without documenting why. | |||||
| --- | |||||
| ## Recommended Style Tools | |||||
| ```bash | |||||
| composer require --dev squizlabs/php_codesniffer | |||||
| composer require --dev friendsofphp/php-cs-fixer | |||||
| ``` | |||||
| Example checks: | |||||
| ```bash | |||||
| vendor/bin/phpcs --standard=PSR12 src tests | |||||
| vendor/bin/php-cs-fixer fix --dry-run --diff | |||||
| ``` | |||||
| Example fix: | |||||
| ```bash | |||||
| vendor/bin/php-cs-fixer fix | |||||
| ``` | |||||
| --- | |||||
| ## Recommended Composer Scripts | |||||
| A project may include scripts like this: | |||||
| ```json | |||||
| { | |||||
| "scripts": { | |||||
| "test": "phpunit", | |||||
| "style": "phpcs --standard=PSR12 src tests", | |||||
| "style:fix": "php-cs-fixer fix", | |||||
| "analyse": "phpstan analyse src tests", | |||||
| "quality": [ | |||||
| "@style", | |||||
| "@test", | |||||
| "@analyse" | |||||
| ] | |||||
| } | |||||
| } | |||||
| ``` | |||||
| Then run: | |||||
| ```bash | |||||
| composer quality | |||||
| ``` | |||||
| --- | |||||
| ## Verification Rules | |||||
| When completing work: | |||||
| - Run relevant checks when possible. | |||||
| - Explain any checks that could not be run. | |||||
| - If tests are not added, explain why. | |||||
| - If a test fails, do not hide the failure. | |||||
| - Do not change unrelated tests just to make failures disappear. | |||||
| --- | |||||
| ## Quality Checklist | |||||
| Before considering work complete: | |||||
| - [ ] New behavior is tested. | |||||
| - [ ] Existing tests pass, or failures are explained. | |||||
| - [ ] Code follows PSR-12 or project-specific style. | |||||
| - [ ] Composer files are valid. | |||||
| - [ ] No unrelated dependency updates were introduced. | |||||
| - [ ] Static analysis passes if configured. | |||||
| - [ ] Manual verification steps are documented when automated testing is not practical. | |||||
| @@ -0,0 +1,126 @@ | |||||
| # Agent Workflow Skill | |||||
| ## Purpose | |||||
| Use this skill for AI agent behavior, multi-file work, pull-request checks, legacy PHP changes, non-negotiable rules, response format, and skill feedback. | |||||
| --- | |||||
| ## Agent Workflow | |||||
| When modifying this codebase, the AI agent must: | |||||
| 1. Inspect existing project conventions before adding new patterns. | |||||
| 2. Prefer small, focused changes. | |||||
| 3. Preserve public behavior unless explicitly asked to change it. | |||||
| 4. Add or update tests when behavior changes. | |||||
| 5. Run relevant checks when possible. | |||||
| 6. Explain any checks that could not be run. | |||||
| 7. Avoid introducing new dependencies unless they solve a clear problem. | |||||
| 8. Never place secrets in code, tests, fixtures, logs, or documentation. | |||||
| 9. Keep generated code consistent with this file and the loaded skill files. | |||||
| 10. Leave the repository better organized than it was found. | |||||
| --- | |||||
| ## Pull Request / Review Checklist | |||||
| Before considering work complete: | |||||
| - [ ] Code follows PSR-12 or project-specific style. | |||||
| - [ ] Namespaces and autoloading are correct. | |||||
| - [ ] Composer files are valid. | |||||
| - [ ] No unrelated dependency updates were introduced. | |||||
| - [ ] New behavior is tested. | |||||
| - [ ] Existing tests pass. | |||||
| - [ ] SQL is parameterized. | |||||
| - [ ] User input is validated. | |||||
| - [ ] Output is escaped. | |||||
| - [ ] No secrets are committed. | |||||
| - [ ] Errors are handled safely. | |||||
| - [ ] Documentation was updated where needed. | |||||
| --- | |||||
| ## Legacy PHP Exception Policy | |||||
| If this project contains legacy PHP: | |||||
| - Do not rewrite large areas without approval. | |||||
| - Add tests around legacy behavior before refactoring. | |||||
| - Improve safety incrementally. | |||||
| - Replace deprecated patterns as touched. | |||||
| - Avoid mixing modernization with unrelated feature work. | |||||
| - Document any compatibility constraints. | |||||
| Legacy code should still move toward: | |||||
| - Composer autoloading | |||||
| - Namespaces | |||||
| - PDO/prepared statements | |||||
| - Centralized configuration | |||||
| - Automated tests | |||||
| - Safer error handling | |||||
| --- | |||||
| ## Non-Negotiable Rules | |||||
| The agent must not: | |||||
| - Commit secrets. | |||||
| - Build SQL using untrusted string concatenation. | |||||
| - Store plain-text passwords. | |||||
| - Use `md5`, `sha1`, or raw fast hashes for passwords. | |||||
| - Display production errors to users. | |||||
| - `unserialize()` untrusted data. | |||||
| - Put database queries in templates. | |||||
| - Edit files under `vendor/`. | |||||
| - Add dependencies without a clear reason. | |||||
| - Ignore failing tests or quality checks without explanation. | |||||
| --- | |||||
| ## Response Format | |||||
| For non-trivial tasks, respond using this structure: | |||||
| ```text | |||||
| Goal: | |||||
| Route: | |||||
| Assumptions: | |||||
| Plan: | |||||
| Implementation: | |||||
| Tests: | |||||
| Risks: | |||||
| ``` | |||||
| For simple questions, answer directly. | |||||
| --- | |||||
| ## Skill Feedback Rule | |||||
| If project guidance is missing or unclear, suggest an update. | |||||
| ```text | |||||
| Suggested SKILLS.md update: | |||||
| - Add/update: ... | |||||
| - Reason: ... | |||||
| ``` | |||||
| --- | |||||
| ## Final Instruction to Coding Agents | |||||
| When in doubt, choose the boring, obvious, secure PHP solution: | |||||
| - Composer-managed dependencies | |||||
| - PSR-style code | |||||
| - Namespaced classes | |||||
| - Dependency injection | |||||
| - PDO prepared statements | |||||
| - Escaped output | |||||
| - Tested behavior | |||||
| - Clear errors and logs | |||||
| - No secrets in source control | |||||
| @@ -0,0 +1,7 @@ | |||||
| { | |||||
| "permissions": { | |||||
| "allow": [ | |||||
| "PowerShell(\\(Get-Item \"d:\\\\Development\\\\PHP\\\\Mind-Vision-Code\\\\CLAUDE.md\"\\).Target)" | |||||
| ] | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1 @@ | |||||
| AGENTS.md | |||||
Powered by TurnKey Linux.