Skip to content

Commit bebb91e

Browse files
committed
Compliance for Wordpress.org plugin submission review
1 parent ba44df0 commit bebb91e

5 files changed

Lines changed: 244 additions & 38 deletions

File tree

README.md

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,75 @@ For manual source installation:
6060

6161
### Install the Perfbase extension
6262

63-
The plugin depends on the native Perfbase PHP extension. Install it with:
63+
The plugin depends on the native Perfbase PHP extension. Installing that extension requires shell/server access and permission to copy a native extension into PHP's extension directory and add an ini file. Perfbase for WordPress is intended for advanced or server-managed WordPress environments. Many shared hosting and restricted managed WordPress environments do not support custom PHP extensions; in those environments the plugin can be installed, but profiling will not run until the extension is available.
64+
65+
Automated installer for supported server environments:
6466

6567
```bash
6668
bash -c "$(curl -fsSL https://cdn.perfbase.com/install.sh)"
6769
```
6870

69-
Restart PHP-FPM, Apache, Nginx Unit, or any long-lived PHP worker after installing the extension.
71+
The installer performs the same download, checksum, copy, ini-file, and verification steps automatically.
72+
73+
Manual extension installation with `wget`:
74+
75+
Find the PHP major/minor version and CPU architecture:
76+
77+
```bash
78+
php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION.PHP_EOL;'
79+
uname -m
80+
```
81+
82+
Use `amd64` for `x86_64`, and `arm64` for `aarch64` or Apple Silicon. Choose the URL pattern for your server:
83+
84+
Debian/Ubuntu and most glibc Linux distributions:
85+
86+
```bash
87+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-linux-amd64-gnu-release.so
88+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-linux-amd64-gnu-release.so.sha256sum.txt
89+
sha256sum -c perfbase-8.3-linux-amd64-gnu-release.so.sha256sum.txt
90+
```
91+
92+
Alpine Linux:
93+
94+
```bash
95+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-linux-amd64-musl-release.so
96+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-linux-amd64-musl-release.so.sha256sum.txt
97+
sha256sum -c perfbase-8.3-linux-amd64-musl-release.so.sha256sum.txt
98+
```
99+
100+
macOS:
101+
102+
```bash
103+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-darwin-arm64-release.dylib
104+
wget https://cdn.perfbase.com/extension/latest/perfbase-8.3-darwin-arm64-release.dylib.sha256sum.txt
105+
sha256sum -c perfbase-8.3-darwin-arm64-release.dylib.sha256sum.txt
106+
```
107+
108+
Replace `8.3` with your PHP major/minor version and replace `amd64` with `arm64` when using ARM64 Linux.
109+
110+
Find PHP's extension directory and loaded ini scan directories:
111+
112+
```bash
113+
php -i | grep '^extension_dir'
114+
php --ini
115+
```
116+
117+
Copy the extension binary into PHP's extension directory, then create `perfbase.ini` in one of the loaded ini scan directories:
118+
119+
```ini
120+
extension=perfbase.ext
121+
```
122+
123+
Replace `perfbase.ext` with the downloaded filename, such as `perfbase.so` or `perfbase.dylib`.
124+
125+
Restart PHP-FPM, Apache, Nginx Unit, or any long-lived PHP worker after installing the extension, then verify it:
126+
127+
```bash
128+
php -m | grep perfbase
129+
```
130+
131+
For a specific pinned build instead of the mutable latest build, replace `/extension/latest/` with a versioned path such as `/extension/v123/`.
70132

71133
## Quick start
72134

@@ -241,10 +303,26 @@ The plugin also adds context through WordPress hooks such as:
241303

242304
Cache profiling itself is handled by the native Perfbase extension via feature flags rather than by WordPress cache hooks.
243305

244-
For safety and lower cardinality:
306+
Perfbase can send:
307+
308+
- function call trees, function names, source file paths and line numbers, timing, CPU, memory, and host resource metrics
309+
- host operating system, kernel, hostname, CPU architecture, CPU details, disk capacity details, memory usage, CPU usage, disk I/O, and network I/O samples
310+
- capped process-list snapshots when enabled, containing process ID, executable basename, OS user, CPU usage, memory usage, and process runtime, without command-line arguments
311+
- additional native trace metadata such as normalized SQL query text, database DSN/host/database/username/port metadata, MongoDB or Elasticsearch query/filter payload summaries, Redis or Memcached keys and fields, HTTP URL or URI metadata that may include query strings depending on the PHP API or HTTP library used, HTTP method/status/timing/byte-count metadata, file paths and file operation metadata, mail recipient and subject metadata, shell/process command strings, AWS operation names, OPcache and JIT statistics, PHP error or exception samples, compiled file paths, magic method counts, and truncated function argument values when argument capture is separately configured. These fields depend on enabled extension features, loaded PHP libraries, and which code paths run during the trace
312+
- WordPress request metadata such as action name, HTTP method, request URL without query string, HTTP status code, user IP address, user agent, logged-in user ID when available, hostname, environment, application version, PHP version, WordPress version, and Perfbase plugin version
313+
- WordPress context metadata such as AJAX action, REST route, admin page, post/page identifiers, post type/status, taxonomy context, template and theme information, conditional page type flags, plugin lifecycle context, and WooCommerce page, cart, product, or order context when available
314+
- operational summaries such as memory usage, database query count and timing summaries when available, and sanitized outbound HTTP request metadata when HTTP tracking is enabled
315+
316+
Perfbase does not collect:
245317

246-
- outbound HTTP attributes are stored as sanitized `scheme://host/path` values without query strings or fragments
247-
- database visibility is limited to aggregate shutdown-time stats such as total query count, slow query count, and total query time
318+
- source code
319+
- request bodies, full POST payloads (`$_POST`), arbitrary form fields, or uploaded file contents
320+
- cookie values (`$_COOKIE`) or PHP session data (`$_SESSION`)
321+
- authorization header values
322+
- passwords, API keys, nonces, or session IDs from WordPress request, cookie, or session data
323+
- command-line arguments for process-list snapshots
324+
325+
Feature flags control the extra native trace metadata listed under "Perfbase can send", including outbound HTTP URLs or URIs with query strings for some HTTP libraries and truncated function argument values if argument capture is separately configured. Review enabled Perfbase extension feature flags before profiling sensitive workloads, especially flags that capture arguments, errors, exceptions, database/cache/HTTP/file metadata, mail metadata, process metadata, OPcache metadata, or host resource metadata.
248326

249327
## Request metadata
250328

@@ -273,7 +351,20 @@ The plugin keeps action names low-cardinality and avoids leaking sensitive query
273351
- `wordpress.admin_page`
274352
- template, theme, post, taxonomy, and conditional-tag attributes when available
275353

276-
`http_url` is stored without the query string. Important WordPress query parameters are broken out into dedicated attributes instead.
354+
`http_url` for the inbound WordPress request is stored without the query string. Important WordPress query parameters are broken out into dedicated attributes instead. Native HTTP metadata may still include full outbound URLs or URIs with query strings depending on enabled extension features and the HTTP library used.
355+
356+
### Data Perfbase does not collect
357+
358+
Perfbase does not collect:
359+
360+
- source code
361+
- request bodies, full POST payloads (`$_POST`), arbitrary form fields, or uploaded file contents
362+
- cookie values (`$_COOKIE`) or PHP session data (`$_SESSION`)
363+
- authorization header values
364+
- passwords, API keys, nonces, or session IDs from WordPress request, cookie, or session data
365+
- command-line arguments for process-list snapshots
366+
367+
Database metadata added by the WordPress plugin is limited to aggregate query counts and timing information when available. Native HTTP metadata can include outbound URLs or URIs with query strings. The native profiler may capture additional context depending on enabled Perfbase extension feature flags and application code.
277368

278369
## Example production setup
279370

@@ -305,7 +396,7 @@ php -m | grep perfbase
305396
php --ini
306397
```
307398

308-
If needed, reinstall it:
399+
If the extension is missing, repeat the manual extension installation steps above or run the automated installer on a supported server:
309400

310401
```bash
311402
bash -c "$(curl -fsSL https://cdn.perfbase.com/install.sh)"

bin/verify-release-zip

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ unzip -q "$ZIP_PATH" -d "$TMP_DIR"
6060
PLUGIN_DIR="$TMP_DIR/$PLUGIN_SLUG"
6161
PLUGIN_FILE="$PLUGIN_DIR/perfbase.php"
6262
README_FILE="$PLUGIN_DIR/readme.txt"
63+
ADMIN_FILE="$PLUGIN_DIR/src/PerfbaseAdmin.php"
6364

64-
for required_path in "$PLUGIN_FILE" "$README_FILE" "$PLUGIN_DIR/uninstall.php" "$PLUGIN_DIR/composer.json" "$PLUGIN_DIR/vendor/autoload.php" "$PLUGIN_DIR/LICENSE.txt"; do
65+
for required_path in "$PLUGIN_FILE" "$README_FILE" "$ADMIN_FILE" "$PLUGIN_DIR/uninstall.php" "$PLUGIN_DIR/composer.json" "$PLUGIN_DIR/vendor/autoload.php" "$PLUGIN_DIR/LICENSE.txt"; do
6566
if [[ ! -f "$required_path" ]]; then
6667
echo "Expected packaged file missing: ${required_path#$TMP_DIR/}" >&2
6768
exit 1
@@ -76,12 +77,13 @@ for forbidden_path in composer.lock tests .github AGENTS.md CLAUDE.md phpunit.xm
7677
done
7778

7879
php -r '
79-
[$version, $pluginFile, $readmeFile] = array_slice($argv, 1);
80+
[$version, $pluginFile, $readmeFile, $adminFile] = array_slice($argv, 1);
8081
8182
$plugin = file_get_contents($pluginFile);
8283
$readme = file_get_contents($readmeFile);
84+
$admin = file_get_contents($adminFile);
8385
84-
if ($plugin === false || $readme === false) {
86+
if ($plugin === false || $readme === false || $admin === false) {
8587
fwrite(STDERR, "Unable to read packaged metadata\n");
8688
exit(1);
8789
}
@@ -97,6 +99,52 @@ php -r '
9799
$expect((bool) preg_match("/^define\('\''PERFBASE_PLUGIN_VERSION'\'',\s*'\''" . preg_quote($version, "/") . "'\''\);$/m", $plugin), "Plugin constant version does not match {$version}");
98100
$expect((bool) preg_match("/^Stable tag:\s*" . preg_quote($version, "/") . "$/m", $readme), "Readme stable tag does not match {$version}");
99101
$expect((bool) preg_match("/^= " . preg_quote($version, "/") . " =$/m", $readme), "Readme changelog or upgrade notice does not include {$version}");
100-
' "$EXPECTED_VERSION" "$PLUGIN_FILE" "$README_FILE"
102+
$expect(strpos($readme, "== External Services ==") !== false, "Readme is missing External Services section");
103+
$expect(strpos($readme, "Perfbase APM platform") !== false, "Readme is missing service name disclosure");
104+
$expect(strpos($readme, "https://perfbase.com/privacy/") !== false, "Readme is missing Perfbase privacy policy link");
105+
$expect(strpos($readme, "https://perfbase.com/terms/") !== false, "Readme is missing Perfbase terms link");
106+
$expect(strpos($readme, "user IP address") !== false, "Readme is missing user IP disclosure");
107+
$expect(strpos($readme, "user agent") !== false, "Readme is missing user agent disclosure");
108+
$expect(strpos($readme, "normalized SQL query text") !== false, "Readme is missing SQL metadata disclosure");
109+
$expect(strpos($readme, "Redis or Memcached keys") !== false, "Readme is missing cache key disclosure");
110+
$expect(strpos($readme, "HTTP URL or URI metadata that may include query strings") !== false, "Readme is missing native HTTP URL query disclosure");
111+
$expect(strpos($readme, "mail recipient and subject") !== false, "Readme is missing mail metadata disclosure");
112+
$expect(strpos($readme, "shell/process command strings") !== false, "Readme is missing process command disclosure");
113+
$expect(strpos($readme, "OPcache and JIT statistics") !== false, "Readme is missing OPcache metadata disclosure");
114+
$expect(stripos($readme, "process-list tracking") !== false, "Readme is missing process-list disclosure");
115+
$expect(strpos($readme, "host resource") !== false, "Readme is missing host resource disclosure");
116+
$expect(strpos($readme, "Perfbase can send:") !== false, "Readme is missing Perfbase can send disclosure");
117+
$expect(strpos($readme, "Perfbase does not collect:") !== false, "Readme is missing Perfbase does not collect disclosure");
118+
$expect(stripos($readme, "request bodies") !== false, "Readme is missing request body metadata disclosure");
119+
$expect(stripos($readme, "POST payloads") !== false, "Readme is missing POST data metadata disclosure");
120+
$expect(stripos($readme, "arbitrary form fields") !== false, "Readme is missing form field metadata disclosure");
121+
$expect(stripos($readme, "source code") !== false, "Readme is missing source code exclusion disclosure");
122+
$expect(stripos($readme, "cookie values") !== false, "Readme is missing cookie metadata disclosure");
123+
$expect(stripos($readme, "PHP session data") !== false, "Readme is missing session metadata disclosure");
124+
$expect(stripos($readme, "authorization header values") !== false, "Readme is missing authorization header metadata disclosure");
125+
$expect(strpos($readme, "full query strings, passwords") === false, "Readme should not claim full query strings are excluded from native traces");
126+
$expect(strpos($readme, "Feature flags control the extra native trace metadata") !== false, "Readme is missing native feature flag metadata disclosure");
127+
$expect(strpos($readme, "enabled Perfbase extension feature flags") !== false, "Readme is missing feature flag caveat");
128+
$expect(strpos($readme, "shell/server access is required") !== false, "Readme is missing server access installation warning");
129+
$expect(strpos($readme, "shared hosting") !== false, "Readme is missing shared hosting installation warning");
130+
$expect(strpos($readme, "php -r") !== false, "Readme is missing manual PHP version check");
131+
$expect(strpos($readme, "php -i | grep") !== false, "Readme is missing manual extension_dir check");
132+
$expect(strpos($readme, "php --ini") !== false, "Readme is missing manual ini scan check");
133+
$expect(strpos($readme, "uname -m") !== false, "Readme is missing architecture detection guidance");
134+
$expect(strpos($readme, "Debian/Ubuntu") !== false, "Readme is missing Debian/Ubuntu URL guidance");
135+
$expect(strpos($readme, "Alpine Linux") !== false, "Readme is missing Alpine URL guidance");
136+
$expect(strpos($readme, "macOS") !== false, "Readme is missing macOS URL guidance");
137+
$expect(strpos($readme, "linux-amd64-gnu-release.so") !== false, "Readme is missing glibc Linux URL pattern");
138+
$expect(strpos($readme, "linux-amd64-musl-release.so") !== false, "Readme is missing Alpine musl URL pattern");
139+
$expect(strpos($readme, "darwin-arm64-release.dylib") !== false, "Readme is missing macOS URL pattern");
140+
$expect(strpos($readme, "sha256sum -c") !== false, "Readme is missing manual checksum verification");
141+
$expect(strpos($readme, "/extension/v123/") !== false, "Readme is missing pinned version path example");
142+
$expect(strpos($readme, "cdn.perfbase.com") !== false, "Readme is missing CDN installer disclosure");
143+
$expect(strpos($readme, "bash -c \"\$(curl") !== false, "Readme is missing automated installer command");
144+
$expect(strpos($readme, "Automated installer") < strpos($readme, "Manual extension installation"), "Readme should show automated installer before manual instructions");
145+
$expect(strpos($admin, "normalized SQL query text") !== false, "Admin privacy text is missing SQL metadata disclosure");
146+
$expect(strpos($admin, "HTTP URL or URI metadata that may include query strings") !== false, "Admin privacy text is missing native HTTP URL query disclosure");
147+
$expect(strpos($admin, "Perfbase does not collect source code") !== false, "Admin privacy text is missing source code exclusion disclosure");
148+
' "$EXPECTED_VERSION" "$PLUGIN_FILE" "$README_FILE" "$ADMIN_FILE"
101149

102150
echo "Verified $ZIP_PATH"

0 commit comments

Comments
 (0)