Checks#
This page lists every check PROCTOR runs in a single vendor/bin/proctor check run, and how each one reports. The proctor asks the same questions in the same order on every run; only the hall changes.
Nine of the seventeen checks shown, asked in this order on every run; policy-age stays silent while the policy is fresh. The lines are real output from the test fixtures.
How a check reports#
Every finding carries one of four statuses: pass, warning, info or fail. A fail is a resit; a warning is a note in the margin that never changes the exit code; an info is the proctor thinking out loud, such as a missing composer or a lookup that could not run.
Every finding also carries a stable, namespaced rule id: proctor/<check-id> for a check's default finding, proctor/<check-id>/<rule> for a named rule. The id is the finding's identity in the machine formats: rule_id in json, ruleId in sarif, and check_name in codequality. A rule keeps the same id across runs and across formats even when its message changes. The full table lives on the Rule ids page.
Composer#
The six checks that read composer.json and composer.lock. Details and fixes: Composer checks.
unbounded-constraints: fails for every runtime constraint that is*, names adev-branch, carries@dev, has a lower bound with no upper bound, or matches the policy'sbanned_constraints; warns onpathandvcsrepositories, on aminimum-stabilitybelow stable, and on a repository URL that is plain http.require-dev,php,ext-*andlib-*are not checked.composer-config: warns when composer.json opens a door Composer closes by default:allow-pluginsset totrue,secure-httpset tofalse,lockset tofalse,audit.block-insecureset tofalse,config.policyset tofalse,policy.malwareset tofalseorpolicy.advisoriesset tofalse; notes whenrequire.phpis set withoutconfig.platform.php. Warning and info only, never a fail.lock-committed: fails when composer.lock is missing from the app path. When the lock is present and itscontent-hashis a real 32-hex hash, it warns (proctor/lock-committed/out-of-sync) when the hash no longer matches composer.json, so a stale lock that still installs is visible instead of silent; the warning never changes the exit code.composer-audit: fails for advisories at or above the policy'saudit_severity_threshold, warns for lower ones, and reports info when composer or the lock file is absent. Fails (proctor/composer-audit/could-not-run) when the audit runs but its stdout is not parseable JSON, because a green run that audited nothing is worse than a red one.composer-version: fails when the Composer on PATH is Composer 1 (end of life) or carries the command-injection holes CVE-2024-35241 and CVE-2024-35242 (2.2.x below 2.2.24, or any other 2.x below 2.7.7); warns when composer cannot be run.repo-url-credentials: warns when a credential is written into a package source URL: a deploy token in the userinfo of a composer.json repository URL or a composer.lock source/dist URL, a bare token user of 20+ characters, aprivate_token,access_token,tokenorpasswordquery parameter, or a.npmrcline that sets_authToken,_author_passwordto a literal value. The secret is masked as***in the message, so the report itself is safe to hand back.
PHP and database#
The checks that grade the PHP floor, patch currency, MySQL 5.6 compatibility and the age of the policy in use. Details and fixes: PHP checks.
php-floor: fails when the lowest PHP version allowed byrequire.phpis past security support plus the grace window, when composer.json has no usable php constraint, or when there is no composer.json at all.unpatched: warns when a locked component is behind the policy'slatest_patchfor its version line, and passes when it is current. Reads laravel from composer.lock (laravel/framework), vue and inertia from package-lock.json (vue,@inertiajs/vue3), and the PHP runtime from--php-runtime. No finding when the component, its version line, orlatest_patchis absent from the policy.mysql56: warns when migrations or app code use MySQL features the shared 5.6 server rejects: JSON columns (indatabase/) and JSON queries, generated columns,renameColumn/renameIndex, vector, invisible and spatial columns,Schema::hasColumn-style introspection, raw SQL with 5.7+ syntax, the upsert row alias, indexed strings over 191 characters, date columns defaulting to the current time, and thedb:show/db:monitorcommands. Warnings, not failures: an app on its own newer database is not affected.policy-age: warns when the policy in use is more than 60 days old (itsrefreshed_ondate is more than 60 days before--today), or when a non-bundled policy has norefreshed_ondate. Warning only: an old policy never fails a run.
The portability and destructive-deploy checks also read PHP and deploy scripts; they are covered on the CI checks page.
CI and deploy#
Details and fixes: CI checks.
ci-pipelines: for stack packages (composer.jsonnamestarting withwaynestate/), fails when.gitlab-ci.ymlor.github/workflows/ci.ymlis missing or runs nocomposer ci; for any other project, a missing or incomplete.gitlab-ci.ymlis a warning and.github/workflows/ci.ymlis optional. Warns when a GitHubuses:ref is not a 40-hex commit SHA, and when the pipeline environment switches Composer's audit or blocking policy off.preflight-pinned: warns, never fails, when an app includes a Preflight component at a moving ref or re-declares what an included Preflight job runs.portability: warns when code hard-codes a platform fact: an absolute host path, a hard-coded proxy address, a local-disk session store, or a php_value/php_flag line in .htaccess.destructive-deploy: fails when a deploy script runs an artisan command that drops or rebuilds the database (migrate:fresh,migrate:refresh,migrate:reset,db:wipe), which erases production data on every deploy.instant-client-committed: warns when Oracle Instant Client is committed to the repo: an archive, an unzipped install under aninstantclientdirectory, or a loose client library.
WayneUI#
Details and fixes: WayneUI checks.
wayneui-forked-views: warns when forked copies of WayneUI are committed underresources/views/vendor/wayne-ui/orpublic/vendor/wayne-ui/; those copies silently override the package, so an app keeps old layouts after a WayneUI upgrade and nobody sees it.wayneui-outdated: warns when the WayneUI an app carries is behind the latest release of the same major; by default a warning, not a failure, and an offline run never breaks.
Overrides#
overrides: fails for every expired entry in policy-overrides.json; warns for an active entry that expires within 14 days of--todayand for an active entry that matches no failure. How the file works: Overrides.