Skip to content

Commit 294ffa0

Browse files
committed
chore: centralize current metrics and harden local test bootstrap
1 parent b6cc2b8 commit 294ffa0

10 files changed

Lines changed: 310 additions & 257 deletions

File tree

.github/copilot-instructions.md

Lines changed: 57 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -1,261 +1,89 @@
11
# Copilot Instructions
22

3-
## Project Overview
3+
Use this file as a quick execution guide for this repository. If instructions conflict, follow this precedence:
44

5-
WP Sudo is a WordPress plugin that provides action-gated reauthentication. Dangerous operations (plugin activation, user deletion, critical settings changes, etc.) require password confirmation before they proceed — regardless of user role.
5+
1. `AGENTS.md`
6+
2. `CLAUDE.md`
7+
3. This file
68

7-
- **Requirements:** WordPress 6.2+, PHP 8.0+
8-
- **Repository Type:** WordPress Plugin
9-
- **Primary Language:** PHP, JavaScript
10-
- **Frameworks:** WordPress, WordPress Block Editor (Gutenberg), @wordpress/scripts
11-
- **Target Runtime:** WordPress 6.8+, PHP 8.1+
9+
## Repository Snapshot
1210

13-
## Critical Build Instructions
11+
- Project: WP Sudo (WordPress plugin)
12+
- Runtime requirements: WordPress 6.2+, PHP 8.0+
13+
- Plugin version source of truth: `wp-sudo.php` (`Version` header + `WP_SUDO_VERSION`)
14+
- Architecture center: `includes/class-gate.php`
15+
- Built-in gated actions: 32 rules (single-site + multisite)
1416

15-
### Environment Requirements
17+
## What This Plugin Does
1618

17-
- **PHP:** 8.1 or higher (plugin requires PHP 8.1+)
18-
- **Composer:** 2.8.12 or higher
19+
WP Sudo requires reauthentication before dangerous actions execute (plugin/theme changes, user/role operations, key settings changes, etc.). It enforces this across admin UI, AJAX, REST, WP-CLI, Cron, XML-RPC, and WPGraphQL policy surfaces.
1920

20-
### Dependency Versions
21+
## Ground Rules For Changes
2122

22-
#### npm Packages
23-
- **@wordpress/scripts:** 30.26.0 or higher
23+
- Follow TDD: write/adjust failing tests first, then production code.
24+
- Do not invent external plugin methods/classes/hooks/meta keys.
25+
- Verify external technical references against authoritative sources before writing docs or integration code.
26+
- Keep lifecycle behavior safe and idempotent (activation, deactivation, uninstall, upgrades).
27+
- Do not weaken capability checks, nonce checks, sanitization, or escaping.
2428

25-
#### Composer Packages
26-
- **wp-coding-standards/wpcs:** 3.0 or higher
29+
## Correct Commands
2730

28-
### Dependency Installation
31+
### Setup
2932

30-
**ALWAYS install dependencies in this exact order before any build operations:**
31-
32-
1. **npm dependencies (REQUIRED FIRST):**
33-
```bash
34-
npm install
35-
```
36-
- Takes approximately 60 seconds on first install
37-
- May show deprecation warnings (these are non-critical)
38-
- May show 2 moderate severity vulnerabilities (these are from dev dependencies and are non-critical)
39-
- Creates `node_modules/` directory (ignored by git)
40-
41-
2. **Composer dependencies (for PHP linting only):**
42-
```bash
43-
composer install —no-interaction
44-
```
45-
- Takes approximately 30-60 seconds
46-
- May prompt for GitHub OAuth token if run interactively; use `—no-interaction` flag to avoid this
47-
- Falls back to cloning from git cache if GitHub API rate limits are hit
48-
- Creates `vendor/` directory (ignored by git)
49-
- Installs WordPress Coding Standards (WPCS) for PHP linting
50-
51-
#### Composer Commands
52-
53-
```bash
54-
composer install # Install dev dependencies
55-
composer test # Run all unit tests (PHPUnit 9.6)
56-
composer lint # Run PHPCS (WordPress-Extra + WordPress-Docs + WordPressVIPMinimum)
57-
composer lint:fix # Auto-fix PHPCS violations
58-
composer analyse # Run PHPStan level 6 (use --memory-limit=1G if needed)
59-
composer sbom # Regenerate CycloneDX SBOM (bom.json)
60-
```
61-
62-
No build step. No npm. No production dependencies — only dev dependencies.
63-
64-
Always run `composer test` and `composer analyse` before committing.
65-
66-
### Build Process
67-
68-
**ALWAYS run build after making JavaScript/CSS changes:**
69-
70-
```bash
71-
npm run build
72-
```
73-
- Takes approximately 1-2 seconds
74-
- Uses webpack via @wordpress/scripts
75-
- Generates files in `build/` directory (ignored by git, but required for plugin to function)
76-
- Creates `build/blocks-manifest.php` (automatically generated, do NOT edit manually)
77-
- Creates minified JavaScript, CSS, and asset dependency files in `build/wp-sudo/`
78-
- Build output includes RTL CSS variants automatically
79-
80-
**For development with hot reload:**
8133
```bash
82-
npm run start
34+
composer install
8335
```
84-
- Watches for file changes and rebuilds automatically
85-
- Generates unminified source maps for debugging
86-
- Use Ctrl+C to stop the watch process
8736

88-
**To clean and rebuild:**
89-
```bash
90-
rm -rf build/
91-
npm run build
92-
```
37+
### Test and Quality Gates
9338

94-
### Linting and Code Quality
95-
96-
**JavaScript/JSX Linting:**
9739
```bash
98-
npm run lint:js
40+
composer test:unit
41+
composer test:integration
42+
composer analyse:phpstan
43+
composer analyse:psalm
44+
composer lint
9945
```
100-
- Uses ESLint with WordPress coding standards
101-
- Checks all `.js` files in `src/`
102-
- Must pass with no errors before committing
103-
- Some warnings are acceptable
10446

105-
**CSS/SCSS Linting:**
106-
```bash
107-
npm run lint:css
108-
```
109-
- Uses stylelint with WordPress standards
110-
- Checks all `.scss` files in `src/`
111-
- Must pass with no errors before committing
112-
113-
**Auto-formatting:**
114-
```bash
115-
npm run format
116-
```
117-
- Uses Prettier to auto-format JavaScript, JSON, CSS/SCSS
118-
- **ALWAYS run this before linting if you get Prettier errors**
119-
- Automatically fixes most lint issues related to formatting
120-
- Safe to run on all files
47+
### Optional Utilities
12148

122-
**PHP Linting:**
12349
```bash
124-
./vendor/bin/phpcs wp-sudo.php
50+
composer test:coverage
51+
composer sbom
12552
```
126-
- Uses PHP_CodeSniffer with WordPress Coding Standards
127-
- Available coding standards: WordPress, WordPress-Core, WordPress-Docs, WordPress-Extra
128-
- The main plugin file may have known PHPCS warnings (tabs vs spaces, line length) - these may be acceptable per project style
129-
- Auto-fix many PHP issues with: `./vendor/bin/phpcbf wp-sudo.php`
130-
131-
**NOTE:** This project uses **tabs for indentation** (not spaces) per WordPress coding standards, as specified in `.editorconfig`. The PHPCS errors about “spaces must be used” are using the wrong standard and can be ignored.
132-
133-
## Repository Structure
134-
135-
- `wp-sudo.php` — Plugin entry point, autoloader, lifecycle hooks.
136-
- `includes/` — Core PHP classes (namespace `WP_Sudo`). Key classes: Plugin, Gate, Action_Registry, Challenge, Sudo_Session, Request_Stash, Admin, Admin_Bar, Site_Health, Upgrader.
137-
- `admin/js/` — Vanilla JS for challenge page and admin bar timer. No build step.
138-
- `admin/css/` — Stylesheets for challenge page and admin bar.
139-
- `tests/Unit/` — PHPUnit tests using Brain\Monkey (no WordPress loaded).
140-
- `bridges/` — Drop-in 2FA bridge files for third-party plugins.
141-
- `ROADMAP.md` — Unified roadmap: integration tests, WP 7.0 prep, TDD strategy, core design features, feature backlog, accessibility appendix.
142-
- `CHANGELOG.md` — Full version history.
143-
- `FAQ.md` — All frequently asked questions.
144-
- `docs/` — Documentation suite:
145-
- `security-model.md` — Threat model, boundaries, environmental considerations.
146-
- `developer-reference.md` — Hook signatures, filters, custom rule structure.
147-
- `ai-agentic-guidance.md` — AI and agentic tool integration guidance.
148-
- `two-factor-integration.md` — 2FA plugin integration guide.
149-
- `two-factor-ecosystem.md` — 2FA plugin ecosystem survey.
150-
- `ui-ux-testing-prompts.md` — Structured UI/UX testing prompts.
151-
- `bom.json` — CycloneDX SBOM (regenerate with `composer sbom`).
15253

153-
## Architecture
54+
## Important Reality Checks
15455

155-
**Bootstrap:** `plugins_loaded``Plugin::init()` → loads translations, runs upgrader, registers gate, sets up challenge page, initializes admin UI.
56+
- There is no production JS build pipeline for current plugin runtime assets.
57+
- Do not introduce or depend on `build/` artifacts unless explicitly requested.
58+
- Do not assume npm is required for normal PHP/plugin development in this repo.
59+
- Frontend assets used by the plugin live in `admin/js/` and `admin/css/`.
15660

157-
**Gate pattern:** Multi-surface interceptor matches incoming requests against the Action Registry (29 rules across 7 categories + 8 multisite rules). Admin requests get the stash-challenge-replay flow. AJAX/REST get error responses. CLI/Cron/XML-RPC follow per-surface policies (Disabled, Limited, Unrestricted).
61+
## File Map
15862

159-
**Sessions:** Cryptographic token stored in user meta + httponly cookie. Progressive rate limiting (5 attempts → 5-min lockout).
63+
- Entry point: `wp-sudo.php`
64+
- Core classes: `includes/`
65+
- Optional bridges: `bridges/`
66+
- MU support: `mu-plugin/`
67+
- Unit tests: `tests/Unit/`
68+
- Integration tests: `tests/Integration/`
69+
- Security + developer docs: `docs/`
70+
- Roadmap and planning: `.planning/`
16071

161-
## Coding Standards
72+
## Before Commit
16273

163-
- WordPress Coding Standards (WPCS) enforced via PHPCS.
164-
- PHPStan level 6 with `szepeviktor/phpstan-wordpress`.
165-
- Conventional commit messages.
166-
- WCAG 2.1 AA accessibility throughout (ARIA labels, focus management, screen reader announcements).
167-
- No inline `<script>` blocks — all JS is enqueued as external files (CSP-compatible).
74+
Run and record outcomes:
16875

169-
## Testing
76+
1. `composer test:unit`
77+
2. `composer test:integration` (or document blocker)
78+
3. `composer analyse:phpstan`
79+
4. `composer analyse:psalm`
80+
5. `composer lint`
17081

171-
Tests use Brain\Monkey to mock WordPress functions/hooks without loading WordPress, plus Mockery for object mocking and Patchwork for redefining `setcookie` and `header`.
82+
If any command cannot run, report the exact command and blocker.
17283

173-
PHPUnit strict mode: tests must assert something, produce no output, and not trigger warnings.
84+
## Documentation Hygiene
17485

175-
### Plugin Distribution
176-
177-
**To create a distributable ZIP file:**
178-
```bash
179-
npm run plugin-zip
180-
```
181-
- Creates `wp-sudo.zip` in the repository root (ignored by git)
182-
- Includes only necessary files: `wp-sudo.php`, `build/` directory contents
183-
- Excludes: `src/`, `node_modules/`, `vendor/`, development files
184-
- Takes approximately 1-2 seconds
185-
186-
## Project Architecture
187-
188-
### Directory Structure
189-
190-
### Build Output Structure
191-
192-
### Key Files
193-
194-
## WordPress Coding Guidelines
195-
196-
### Hook Registration
197-
198-
**CRITICAL:** Hook registration must ALWAYS come before the callback function definition.
199-
200-
This ensures that the code is clear and follows WordPress best practices. The hook registration tells WordPress what function to call, so it makes logical sense to define the hook first, then define the function it will call.
201-
202-
**Correct pattern:**
203-
```php
204-
add_action( ‘init’, ‘my_function’ );
205-
function my_function() {
206-
// function content here
207-
}
208-
```
209-
210-
## Validation Workflow
211-
212-
**Before committing any code changes, ALWAYS run in this order:**
213-
214-
1. Format code: `npm run format`
215-
2. Lint JavaScript: `npm run lint:js`
216-
3. Lint CSS: `npm run lint:css`
217-
4. Build: `npm run build`
218-
5. Verify build output exists in `build/wp-sudo/`
219-
220-
**For PHP changes only:**
221-
1. Format and lint as above (if any JS/CSS was touched)
222-
2. Check PHP: `./vendor/bin/phpcs wp-sudo.php` (warnings acceptable)
223-
3. Build: `npm run build`
224-
225-
## Common Issues and Solutions
226-
227-
**Issue:** `npm run build` fails with “Cannot find module”
228-
- **Solution:** Run `npm install` first - dependencies not installed
229-
230-
**Issue:** Lint errors about Prettier formatting
231-
- **Solution:** Run `npm run format` first, then lint again
232-
233-
**Issue:** `./vendor/bin/phpcs: No such file or directory`
234-
- **Solution:** Run `composer install —no-interaction`
235-
236-
**Issue:** Composer hangs asking for GitHub token
237-
- **Solution:** Use `composer install —no-interaction` or let it clone from cache (slower but works)
238-
239-
**Issue:** Build directory is empty after `npm run build`
240-
- **Solution:** Check for errors in console; ensure `src/wp-sudo/` files exist
241-
242-
**Issue:** Plugin not working in WordPress after changes
243-
- **Solution:** ALWAYS run `npm run build` after changing any file in `src/`
244-
245-
## Important Notes
246-
247-
- Never edit files in `build/` directly - they are auto-generated
248-
- The plugin uses WordPress 6.8+ block registration API with blocks-manifest.php for improved performance
249-
- All source files are in `src/wp-sudo/`, all build outputs go to `build/wp-sudo/`
250-
- This project follows WordPress coding standards, which use TABS for indentation
251-
- Do not generate additional files beyond what is required for the assigned task (e.g., summary or documentation files) unless explicitly requested
252-
253-
## Trust These Instructions
254-
255-
These instructions have been thoroughly tested and validated. Only perform additional searches or exploration if:
256-
- The information here is incomplete for your specific task
257-
- You encounter an error not documented in “Common Issues”
258-
- You are adding new functionality not covered by existing patterns
259-
260-
For routine code changes, trust this documentation and avoid unnecessary exploration.
261-
```
86+
- Treat hardcoded counts as perishable.
87+
- When updating test counts, verify from test output first.
88+
- When updating project size metrics, use the commands in `AGENTS.md`.
89+
- Keep release-history entries historical; do not rewrite prior release facts.

.planning/PROJECT.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Every destructive WordPress admin action requires proof that the person at the k
3333
- Public API (wp_sudo_check/wp_sudo_require) — v2.12.0
3434
- 9 audit hooks for external logging — v2.0+
3535
- Editor unfiltered_html restriction + tamper detection — v2.0+
36-
- 496 unit tests, 132 integration tests — v2.13.0
36+
- Comprehensive automated test coverage (current counts in `../docs/current-metrics.md`) — v2.13.0+
3737

3838
### Active
3939

@@ -57,7 +57,7 @@ Every destructive WordPress admin action requires proof that the person at the k
5757

5858
## Context
5959

60-
WP Sudo has comprehensive PHPUnit coverage (496 unit + 132 integration tests) but zero browser-level testing. Five specific scenarios cannot be tested with PHPUnit:
60+
WP Sudo has comprehensive PHPUnit coverage (see `../docs/current-metrics.md` for current counts) but zero browser-level testing. Five specific scenarios cannot be tested with PHPUnit:
6161

6262
1. **Cookie attributes**`setcookie()` output (httponly, SameSite, Secure) not capturable
6363
2. **Admin bar countdown JS** — requires real DOM + `setInterval`
@@ -67,7 +67,7 @@ WP Sudo has comprehensive PHPUnit coverage (496 unit + 132 integration tests) bu
6767

6868
Beyond these 5, the settings page, challenge flow, and admin bar have never been tested end-to-end in a real browser. WP 7.0 GA ships April 9, 2026 with an admin visual refresh — visual regression baselines established now will catch any breakage.
6969

70-
WordPress dev environment: PHP 8.1+, WP 6.7+. CI matrix: PHP 8.0-8.4, WP 6.7/latest/trunk, single-site + multisite.
70+
WordPress dev environment: PHP 8.1+, WP 6.7+. CI matrix: unit tests on PHP 8.1-8.4, integration tests on PHP 8.1/8.3, WP 6.7/latest/trunk, single-site + multisite.
7171

7272
## Constraints
7373

.planning/STATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ See: .planning/PROJECT.md (updated 2026-03-08)
1515
## Accumulated Context
1616

1717
- Security Hardening Sprint (5 phases, v2.10.2-v2.13.0) complete and archived
18-
- 496 unit tests, 1293 assertions; 132 integration tests in CI
18+
- Current test and size counts are centralized in `../docs/current-metrics.md`
1919
- PHPStan level 6 + Psalm clean
2020
- WP 7.0 GA ships April 9, 2026 -- visual regression baselines needed before then
2121
- 5 PHPUnit-uncoverable scenarios identified and scoped into 32 requirements

.planning/codebase/TESTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Testing Patterns
22

3-
**Analysis Date:** 2026-03-04 (revised; original 2026-02-19)
3+
**Analysis Date:** 2026-03-08 (revised; original 2026-02-19)
44

55
## Test Framework
66

@@ -82,7 +82,7 @@ tests/
8282
└── WpGraphQLGatingTest.php
8383
```
8484

85-
**Current counts (2026-03-04):** 460 unit tests, 1182 assertions, and 130 integration tests.
85+
**Current counts:** centralized in `../../docs/current-metrics.md` (single source of truth).
8686

8787
## Test Types
8888

@@ -106,9 +106,9 @@ tests/
106106

107107
### E2E Tests
108108

109-
- Not automated
109+
- Not committed yet
110110
- Manual testing checklist: `tests/MANUAL-TESTING.md` (UI/UX prompts, 19 sections)
111-
- No Playwright/Cypress/WebDriver tests planned
111+
- Playwright E2E is active roadmap work (`.planning/ROADMAP.md`, Phase 6-8)
112112

113113
## Test Structure
114114

.planning/research/FEATURES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ milestone.
5757
| Feature | Why Requested | Why Problematic | Alternative |
5858
|---------|---------------|-----------------|-------------|
5959
| **Full visual regression across all WP versions** | "Catch CSS regressions on WP 6.9 and 7.0 simultaneously" seems thorough. | Snapshot baselines are tied to a specific WP admin theme. A snapshot taken on WP 6.9 will pixel-diff fail against WP 7.0 by design. Maintaining two baseline sets doubles the snapshot count and the CI time, for a scenario already covered by the integration test matrix (PHP × WP version). | Take baselines against WP 7.0 only (the target). The WP 6.x visual appearance is already known from manual testing history. Snapshot regressions catch changes _within_ a WP version, not _between_ versions. |
60-
| **Testing REST API endpoints via Playwright** | "Let's verify the REST API returns `sudo_required` in the browser" sounds comprehensive. | REST API behavior is PHP-layer logic already covered by PHPUnit integration tests. Playwright tests it through the browser fetch layer with no additional insight over `curl` tests in the manual guide. Adds authentication setup complexity (nonce extraction from DOM) for zero new coverage signal. | Keep REST API behavioral tests in PHPUnit integration tests (`RestGatingTest.php` already exists with 132 integration tests). Use `curl` tests in `MANUAL-TESTING.md` for REST verification. |
60+
| **Testing REST API endpoints via Playwright** | "Let's verify the REST API returns `sudo_required` in the browser" sounds comprehensive. | REST API behavior is PHP-layer logic already covered by PHPUnit integration tests. Playwright tests it through the browser fetch layer with no additional insight over `curl` tests in the manual guide. Adds authentication setup complexity (nonce extraction from DOM) for zero new coverage signal. | Keep REST API behavioral tests in PHPUnit integration tests (`RestGatingTest.php` already exists; see `../../docs/current-metrics.md` for current suite counts). Use `curl` tests in `MANUAL-TESTING.md` for REST verification. |
6161
| **WP-CLI behavior via Playwright** | CLI policy behavior visible from a browser is appealing. | WP-CLI does not run in a browser. Playwright cannot exec shell commands without Playwright's `spawn` workaround that is fragile and platform-specific. CLI behavior is already covered by manual testing section 7 and the policy architecture is integration-tested. | Leave WP-CLI tests in `MANUAL-TESTING.md` sections 7–8. CLI testing is a better fit for a shell-based CI step (phpunit integration tests simulate CLI context via `defined('WP_CLI')` mocking). |
6262
| **Screenshot comparison for every admin page** | "Let's capture the full WordPress admin at 10 viewports × 5 pages × 2 WP versions = 100 snapshots" sounds complete. | Visual snapshot suites that grow beyond ~20 baselines become a maintenance burden. False positive diffs from WordPress's dynamic content (menu highlight, time-sensitive notifications, user avatar rendering) require constant baseline updates that erode developer trust in the suite. | Limit snapshots to the 3 WP Sudo surfaces (challenge page, settings page, admin bar) at 2–3 viewports. Keep snapshot count under 15. Never snapshot dynamic page content (plugin list, user list). |
6363
| **Two-Factor Authentication full flow E2E** | "Test the TOTP entry step in a real browser" is appealing. | TOTP codes are time-based and require either a real 2FA-configured account or TOTP seed manipulation in the test environment. Setting up a real TOTP seed in a local WordPress + Playwright test is high complexity with fragile time synchronization. The PHP-level 2FA pending state machine is already covered by `TwoFactorTest.php` integration tests (132 total). | Test the 2FA UI elements (2FA step visibility, timer display, focus management) by mocking the AJAX response to return `requires_two_factor: true` via Playwright's `page.route()` interception, without requiring a real TOTP calculation. |

0 commit comments

Comments
 (0)