From 5222d7efc4fda88d9f4247d805ce0dcd4bc1a5a7 Mon Sep 17 00:00:00 2001 From: Daniel Covington Date: Thu, 21 May 2026 10:07:31 -0400 Subject: [PATCH] ai updates --- .ai/SKILLS.md | 291 +++++++++++ .ai/skills/database/SKILL.md | 122 +++++ .ai/skills/mvc/SKILL.md | 201 ++++++++ .ai/skills/php/SKILL.md | 331 ++++++++++++ .ai/skills/security/SKILL.md | 232 +++++++++ .ai/skills/testing/SKILL.md | 162 ++++++ .ai/skills/workflow/SKILL.md | 126 +++++ .claude/settings.local.json | 7 + AGENTS.md | 940 ++++------------------------------- CLAUDE.md | 1 + 10 files changed, 1573 insertions(+), 840 deletions(-) create mode 100644 .ai/SKILLS.md create mode 100644 .ai/skills/database/SKILL.md create mode 100644 .ai/skills/mvc/SKILL.md create mode 100644 .ai/skills/php/SKILL.md create mode 100644 .ai/skills/security/SKILL.md create mode 100644 .ai/skills/testing/SKILL.md create mode 100644 .ai/skills/workflow/SKILL.md create mode 100644 .claude/settings.local.json create mode 120000 CLAUDE.md diff --git a/.ai/SKILLS.md b/.ai/SKILLS.md new file mode 100644 index 0000000..acef0c5 --- /dev/null +++ b/.ai/SKILLS.md @@ -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. diff --git a/.ai/skills/database/SKILL.md b/.ai/skills/database/SKILL.md new file mode 100644 index 0000000..2e79687 --- /dev/null +++ b/.ai/skills/database/SKILL.md @@ -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 +``` diff --git a/.ai/skills/mvc/SKILL.md b/.ai/skills/mvc/SKILL.md new file mode 100644 index 0000000..91f9aaf --- /dev/null +++ b/.ai/skills/mvc/SKILL.md @@ -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 +

+ + +``` + +--- + +## 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. diff --git a/.ai/skills/php/SKILL.md b/.ai/skills/php/SKILL.md new file mode 100644 index 0000000..98c73b8 --- /dev/null +++ b/.ai/skills/php/SKILL.md @@ -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 `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 + */ +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. diff --git a/.ai/skills/security/SKILL.md b/.ai/skills/security/SKILL.md new file mode 100644 index 0000000..377bdfe --- /dev/null +++ b/.ai/skills/security/SKILL.md @@ -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 +

name()) ?>

+``` + +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`. diff --git a/.ai/skills/testing/SKILL.md b/.ai/skills/testing/SKILL.md new file mode 100644 index 0000000..707070d --- /dev/null +++ b/.ai/skills/testing/SKILL.md @@ -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. diff --git a/.ai/skills/workflow/SKILL.md b/.ai/skills/workflow/SKILL.md new file mode 100644 index 0000000..9d40542 --- /dev/null +++ b/.ai/skills/workflow/SKILL.md @@ -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 diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..be375f7 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "PowerShell(\\(Get-Item \"d:\\\\Development\\\\PHP\\\\Mind-Vision-Code\\\\CLAUDE.md\"\\).Target)" + ] + } +} diff --git a/AGENTS.md b/AGENTS.md index 8aa6a62..12e305c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,907 +1,167 @@ -# AGENT.md — PHP Coding Standard +# AGENTS.md -This file defines the coding standards and working rules for AI agents and developers contributing to this PHP codebase. It is based on the principles from **PHP: The Right Way** and adapted into practical project instructions. +## Purpose -Source reference: https://phptherightway.com/ +Describe how AI coding agents should work in this repository. ---- - -## 1. 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**: routing, controllers, services, models, persistence, templates, and configuration should not be mixed together. - -PHP does not have only one canonical “right way,” so prefer widely accepted standards, documented project conventions, and clear tradeoffs over personal style. - ---- - -## 2. PHP Version Standard - -Use the current stable PHP version supported by the project. - -Default expectation: - -```text -PHP 8.x+ -``` - -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" - } -} -``` - ---- - -## 3. 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. - -Use: - -```php -class InvoiceRepository -{ - public function findByCustomerId(int $customerId): array - { - // ... - } -} -``` - -Avoid unclear abbreviations: - -```php -class InvRepo -{ - public function fbcid($cid) - { - // ... - } -} -``` - -### Formatting Rules - -- Use `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. - ---- - -## 8. 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. - ---- - -## 9. Database Access - -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. - -Transaction example: - -```php -$pdo->beginTransaction(); - -try { - $orders->create($order); - $auditLog->record('order.created', $order->id()); - $pdo->commit(); -} catch (Throwable $e) { - $pdo->rollBack(); - throw $e; -} -``` - ---- - -## 10. Input Validation and Output Escaping - -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 - -### 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.'); -} -``` - -### Escape on Output - -For HTML output: - -```php -function e(string $value): string -{ - return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); -} -``` - -Usage: - -```php -

name()) ?>

-``` - -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 when appropriate. -- 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. - ---- - -## 11. 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. - ---- +This project is a small PHP MVC framework called **MindVisionCode PHP**. -## 12. Serialization and Data Exchange - -Do not call `unserialize()` on untrusted data. - -Prefer JSON for data exchange: +It is intentionally inspired by a Classic ASP MVC framework style: -```php -$data = json_decode($json, true, flags: JSON_THROW_ON_ERROR); -$json = json_encode($data, JSON_THROW_ON_ERROR); -``` +- Central dispatcher +- Controllers and actions +- ViewModels +- Repository classes +- Simple validation +- Database migrations +- Small, readable files +- Minimal dependencies -Rules: +Do **not** turn this project into Laravel, Symfony, Slim, CakePHP, or another large framework. -- Use `JSON_THROW_ON_ERROR` for new code. -- Validate decoded data before using it. -- Avoid PHP serialization for data that crosses trust boundaries. +The goal is to keep the framework understandable, practical, and easy to extend. --- -## 13. 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/ -``` +## Main Route -Example `.env.example`: +Always start here: ```text -APP_ENV=local -APP_DEBUG=true -DATABASE_URL=mysql://user:password@localhost:3306/app +./.ai/SKILLS.md ``` ---- - -## 14. Error Handling and Logging - -Use exceptions for exceptional failure paths. - -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.'; -} -``` +Then load only the skill files needed for the task. --- -## 15. 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 when it fits the project. - -Plain PHP template example: - -```php -

- - -``` - ---- - -## 16. 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'); -} -``` - ---- - -## 17. 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`. - ---- - -## 18. Testing Standard - -Automated tests are expected for new behavior. - -Preferred tools: - -- PHPUnit -- Pest, if the project already uses it - -Rules: - -- Add or update tests with every 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. - -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); - } -} -``` - -Run tests: - -```bash -vendor/bin/phpunit -``` - ---- +## Common Skill Routes -## 19. Static Analysis and Quality Gates +```text +PHP language, style, Composer, OOP: +./.ai/skills/php/SKILL.md -Use static analysis when available. +MVC framework architecture, routing, controllers, views, ViewModels: +./.ai/skills/mvc/SKILL.md -Recommended tools: +PDO, repositories, migrations, SQL, database safety: +./.ai/skills/database/SKILL.md -```bash -composer require --dev phpstan/phpstan -composer require --dev vimeo/psalm -``` +Input validation, escaping, passwords, sessions, secrets, web security: +./.ai/skills/security/SKILL.md -Common quality commands: +Tests, static analysis, quality gates, composer scripts: +./.ai/skills/testing/SKILL.md -```bash -composer validate -composer audit -vendor/bin/phpcs --standard=PSR12 src tests -vendor/bin/phpunit -vendor/bin/phpstan analyse src tests +Agent behavior, PR checklist, legacy policy, response format: +./.ai/skills/workflow/SKILL.md ``` -Do not ignore tool failures without documenting why. - --- -## 20. Documentation - -Use PHPDoc where it adds clarity, especially for arrays, generics-like structures, complex return values, and public APIs. - -Good: - -```php -/** - * @return list - */ -public function findActiveCustomers(): array -{ - // ... -} -``` +## Response Format -Avoid noisy comments that repeat the code: +For non-trivial tasks, respond using this structure: -```php -// Increment i by one. -$i++; +```text +Goal: +Route: +Assumptions: +Plan: +Implementation: +Tests: +Risks: ``` -Rules: - -- Explain why, not just what. -- Document non-obvious tradeoffs. -- Keep README setup instructions current. -- Update examples when behavior changes. - ---- - -## 21. 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. - ---- - -## 22. 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. -10. Leave the repository better organized than it was found. - ---- - -## 23. 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. +For simple questions, answer directly. --- -## 24. Legacy PHP Exception Policy +## Framework Change Policy -If this project contains legacy PHP: +The framework core may be modified to add functionality or optimize existing code, but **never silently**. Any time an agent identifies a change to framework-level code (dispatcher, routing, base controller, base repository, migration runner, validation engine, autoloader, or any file under `framework/`), it must stop and present the following proposal to the user before writing a single line: -- 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 +```text +FRAMEWORK CHANGE PROPOSAL +========================== +Issue: + What problem or limitation was found, and where in the framework it lives. ---- +Proposed Change: + What would be added, modified, or removed. -## 25. Non-Negotiable Rules +Why It Is Needed: + The specific reason application code cannot solve this without a framework change. -The agent must not: +Risks / Dangers: + - Breaking changes to existing controllers, repositories, or views + - Behavioral differences across PHP versions + - Security surface changes + - Performance regressions + - Any other relevant concerns -- 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. +Benefits: + - What improves or is unlocked by the change ---- +Alternatives Considered: + Any application-level workarounds that were ruled out and why. -## 26. 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" - ] - } -} +Awaiting your approval before proceeding. Reply YES to apply, NO to skip, or ask questions. ``` -Then run: - -```bash -composer quality -``` +**Rules:** +- Do not apply the change until the user explicitly approves. +- If the user says NO, document the limitation as a comment or note and continue with the best available application-level workaround. +- Keep framework changes small and focused — one concern per change. +- After approval, note the change in the commit message so the history is clear. --- -## 27. Final Instruction to Coding Agents - -When in doubt, choose the boring, obvious, secure PHP solution: +## Skill Feedback Rule -- 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 +If project guidance is missing or unclear, suggest an update. - -## Project Overview - -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, or another large framework. - -## Tech Stack - -- PHP 8.2+ -- Composer -- PSR-4 autoloading -- PDO -- PHP views -- Optional SQLite/MySQL/SQL Server through PDO - -## 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 +```text +Suggested SKILLS.md update: +- Add/update: ... +- Reason: ... ``` - -## 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. - -## Request Flow - -Browser → public/index.php → Request → Dispatcher → Router → Route → Controller → ViewModel/Repository → View → Response \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file