Rename the top-level lib/ directory to core/ so the project root immediately communicates which code is core platform and which lives in modules/. PHP namespaces (MintyPHP\*) are unchanged — only the Composer PSR-4 path mapping moves from lib/ to core/. Module-internal lib/ directories (modules/*/lib/) are untouched. Updated across the full stack: - composer.json PSR-4 mapping - bootstrap entry points (web/index.php, bin/*, tests/bootstrap.php) - tooling configs (phpstan.neon, phpunit.xml, php-cs-fixer) - 26 architecture contract tests - enforcement-policy, guard-catalog, quality-gates - all documentation (CLAUDE.md, README, 25 docs/, .agents/skills/) - bin/qa-extended.sh search paths - .claude/settings.local.json permission paths Workflow: .agents/runs/CORE-LIB-RENAME-001/ (Analyst → Planner → Executor → Code Review (4 findings fixed) → Security Review → Acceptance Test → Finalizer) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
195 lines
8.6 KiB
JSON
195 lines
8.6 KiB
JSON
{
|
|
"version": "2.0.0",
|
|
"guards": [
|
|
{
|
|
"id": "GR-CORE-003",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Request input contract",
|
|
"requirement": "MUST read input via requestInput() in pages and avoid superglobals for request data."
|
|
},
|
|
{
|
|
"id": "GR-CORE-007",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "OpenAPI sync",
|
|
"requirement": "MUST update docs/openapi.yaml in the same merge when API endpoints change."
|
|
},
|
|
{
|
|
"id": "GR-CORE-010",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Idempotent DB update scripts",
|
|
"requirement": "Schema or data changes for existing installs MUST be shipped as idempotent SQL scripts in db/updates/ (IF NOT EXISTS, ON DUPLICATE KEY, guarded ALTER TABLE). db/init/init.sql alone is not sufficient."
|
|
},
|
|
{
|
|
"id": "GR-CORE-011",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Settings in DB, not config files",
|
|
"requirement": "New application settings MUST be stored in the settings DB table. storage/runtime/settings.php is a partial hot-path cache only."
|
|
},
|
|
{
|
|
"id": "GR-CORE-012",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "POST-Redirect-GET",
|
|
"requirement": "Actions that successfully mutate state MUST respond with a redirect (PRG pattern). Flash messages set before redirect via Flash::set()."
|
|
},
|
|
{
|
|
"id": "GR-TEST-001",
|
|
"area": "test",
|
|
"reviewer": "code",
|
|
"title": "Tests ship with new logic",
|
|
"requirement": "New or changed business logic in core/Service/ MUST be accompanied by PHPUnit tests covering the happy path and at least one failure or edge case. No new public method in a Service or Gateway without a test."
|
|
},
|
|
{
|
|
"id": "GR-TEST-002",
|
|
"area": "test",
|
|
"reviewer": "code",
|
|
"title": "Code must be testable",
|
|
"requirement": "New code MUST use constructor injection. MUST NOT introduce static side-effects in constructors, hidden global state, or direct DB/HTTP calls outside Repository/Gateway abstractions."
|
|
},
|
|
{
|
|
"id": "GR-UI-014",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "UI state completeness",
|
|
"requirement": "New user-facing views or components MUST handle four states: loading, empty, error, success. All four defined in plan before implementation. Not required for small fixes to existing UI."
|
|
},
|
|
{
|
|
"id": "GR-UI-LIST",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "List and grid standards",
|
|
"requirement": "Lists MUST preserve row action column plus enter/dblclick fallback behavior. Page size options and URL/localStorage/default precedence MUST be maintained. New lists MUST use initStandardListPage()."
|
|
},
|
|
{
|
|
"id": "GR-UI-DETAIL",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "Detail page standards",
|
|
"requirement": "MUST use standard detail page contracts for dirty-state and actions. MUST NOT use inline confirm handlers on standardized flows. MUST use shared list/detail partials for standardized UI blocks. New pages MUST use the established layout system. Blocks reused in 2+ pages MUST be extracted as partials (app-{context}-{purpose}.phtml)."
|
|
},
|
|
{
|
|
"id": "GR-UI-A11Y",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "Accessibility",
|
|
"requirement": "MUST NOT regress a11y basics (labels, roles, keyboard focus) on touched flows. New interactive components MUST use semantic HTML, be keyboard-operable (Tab/Enter/Escape), use ARIA only where necessary, and meet WCAG 2.1 AA contrast."
|
|
},
|
|
{
|
|
"id": "GR-UI-I18N",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "Internationalization completeness",
|
|
"requirement": "All user-visible strings in phtml views MUST use t('key'). Every new t() key MUST be present in ALL language files (i18n/default_de.json and i18n/default_en.json) in the same merge."
|
|
},
|
|
{
|
|
"id": "GR-UI-REUSE",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "Reuse-first (JS + CSS)",
|
|
"requirement": "MUST check web/js/core/ and web/js/components/ for existing exports before adding new functions. MUST check existing CSS layers and app-* classes before writing new rules. No duplication of logic from core modules."
|
|
},
|
|
{
|
|
"id": "GR-SEC-001",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "CSRF on POST",
|
|
"requirement": "MUST verify CSRF token on every POST endpoint in pages before processing the request body."
|
|
},
|
|
{
|
|
"id": "GR-SEC-002",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "No PII/secrets in logs",
|
|
"requirement": "MUST NOT write PII (email, names, UUIDs) or secrets (tokens, passwords) to logs or audit metadata without prior redaction."
|
|
},
|
|
{
|
|
"id": "GR-SEC-003",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "SQL via prepared statements only",
|
|
"requirement": "MUST NOT build SQL strings with user-controlled input. All queries MUST go through Repository classes using prepared statements."
|
|
},
|
|
{
|
|
"id": "GR-SEC-004",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "No external CDN/remote assets",
|
|
"requirement": "MUST NOT load JS, CSS, fonts from external CDNs or remote URLs. Third-party libraries MUST be vendored locally and served via assetVersion()."
|
|
},
|
|
{
|
|
"id": "GR-SEC-005",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "Encryption via Crypto only",
|
|
"requirement": "Encryption/decryption MUST use core/Support/Crypto.php (AES-256-GCM). No raw openssl_encrypt, no base64 as encryption, no hand-rolled crypto."
|
|
},
|
|
{
|
|
"id": "GR-SEC-006",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "File uploads in storage/ only",
|
|
"requirement": "User-uploaded files MUST be stored under storage/ with non-guessable identifiers. MUST NOT be written to web/. MUST be served via PHP controller with authz. MUST validate MIME + extension before storing."
|
|
},
|
|
{
|
|
"id": "GR-SEC-007",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "API must not start sessions",
|
|
"requirement": "API requests (api/ prefix) MUST NOT trigger Session::start(), remember-me cookie handling, or session timeout redirects."
|
|
},
|
|
{
|
|
"id": "GR-SEC-008",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "Server-side authorization",
|
|
"requirement": "MUST enforce authorization server-side in actions and services. UI-only permission checks are insufficient."
|
|
},
|
|
{
|
|
"id": "GR-SEC-009",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "Server-side tenant scope",
|
|
"requirement": "MUST enforce tenant scope server-side. Every query touching tenant-scoped data MUST filter by tenant_id. No cross-tenant data leakage."
|
|
},
|
|
{
|
|
"id": "GR-SEC-010",
|
|
"area": "security",
|
|
"reviewer": "security",
|
|
"title": "Output escaping in views",
|
|
"requirement": "Views (.phtml) MUST use e() for all HTML output. Raw echo is only permitted for pre-built HTML fragments from framework helpers (e.g. ARIA attributes from navActive()). Each raw echo MUST carry an inline '// raw-html-ok: reason' comment."
|
|
},
|
|
{
|
|
"id": "GR-CORE-LAYERS",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Architecture layer isolation",
|
|
"requirement": "MUST enforce strict layer separation: Views render only (no DB calls), Services contain no HTML, Repositories are isolated from HTTP/session. No cross-layer violations."
|
|
},
|
|
{
|
|
"id": "GR-CORE-MODULE",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Module boundary isolation",
|
|
"requirement": "Modules MUST use MintyPHP\\Module\\* namespaces, declare valid manifests conforming to the schema, register providers correctly, prefix session keys with module.<id>.*, and pass per-module isolation tests."
|
|
},
|
|
{
|
|
"id": "GR-CORE-META",
|
|
"area": "core",
|
|
"reviewer": "code",
|
|
"title": "Agent and codex system integrity",
|
|
"requirement": "Guard catalog, enforcement map, quality gates, agent references, and codex skill/docs links MUST be internally consistent. All guard/gate IDs MUST resolve. No orphaned or broken references."
|
|
},
|
|
{
|
|
"id": "GR-UI-TAXONOMY",
|
|
"area": "ui",
|
|
"reviewer": "code",
|
|
"title": "Status taxonomy consistency",
|
|
"requirement": "Status enums, filter schemas, data-layer constants, and UI labels MUST stay in sync across all layers. No literal status strings outside taxonomy enums."
|
|
}
|
|
]
|
|
}
|