Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,13 @@ jobs:
run: sh tools/build-release.sh

- name: Install and test packaged plugin
run: sh tools/smoke-test-release.sh release/basicrum.zip
run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip

- name: Upload release artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: basicrum-release
path: |
release/basicrum.zip
release/basicrum.zip.sha256
release/basicrum-real-user-monitoring.zip
release/basicrum-real-user-monitoring.zip.sha256
if-no-files-found: error
6 changes: 3 additions & 3 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ jobs:
run: sh tools/build-release.sh

- name: Install and test packaged plugin
run: sh tools/smoke-test-release.sh release/basicrum.zip
run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip

- name: Upload release assets
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
files: |
release/basicrum.zip
release/basicrum.zip.sha256
release/basicrum-real-user-monitoring.zip
release/basicrum-real-user-monitoring.zip.sha256
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
run: sh tools/build-release.sh

- name: Install and test packaged plugin
run: sh tools/smoke-test-release.sh release/basicrum.zip
run: sh tools/smoke-test-release.sh release/basicrum-real-user-monitoring.zip

- name: Create GitHub release and upload assets
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
Expand All @@ -54,5 +54,5 @@ jobs:
generate_release_notes: true
fail_on_unmatched_files: true
files: |
release/basicrum.zip
release/basicrum.zip.sha256
release/basicrum-real-user-monitoring.zip
release/basicrum-real-user-monitoring.zip.sha256
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ coverage.xml

# Release artifacts
/release/
/basicrum.zip
/basicrum-real-user-monitoring.zip

# Local research and planning notes
/plan-refs/
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ in the matching skill.

## Conventions

- Follow WordPress-Core/WPCS. The text domain is `basicrum`.
- Follow WordPress-Core/WPCS. The WordPress.org slug and text domain are
`basicrum-real-user-monitoring`.
- Guard PHP files with `ABSPATH`; escape output and sanitize all input.
- Use ASCII hyphens (`-`); do not use typographic dashes in source, comments,
documentation, or user-facing text.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The development site is available at <http://localhost:9080/> with `admin` / `ba

The installable plugin is [`plugins/basicrum/`](plugins/basicrum/). Repository root files provide development, browser-test, Docker, CI, and release tooling.

Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, synchronized version metadata, privacy-safe consent behavior, and immutable GitHub Actions pins.
Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, the assigned WordPress.org text domain, synchronized version metadata, privacy-safe consent behavior, and immutable GitHub Actions pins.

When changing user-facing text, regenerate the WordPress POT template. Locale-specific PO and MO files are not bundled. When changing settings, keep defaults, rendering, validation, runtime behavior, tests, and documentation synchronized.

Expand Down
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ WP_SERVICE = wordpress
DB_SERVICE = db
WPCLI_SERVICE = wpcli
JS_SERVICE = javascript
WPCLI_PLUGIN_WORKDIR = /var/www/html/wp-content/plugins/basicrum
PLUGIN_SLUG = basicrum-real-user-monitoring
RELEASE_ARCHIVE = release/$(PLUGIN_SLUG).zip
WPCLI_PLUGIN_WORKDIR = /var/www/html/wp-content/plugins/$(PLUGIN_SLUG)
PLUGIN_DIR = plugins/basicrum
PLUGIN_WORKDIR = /workspace
TEST_DB_NAME = wordpress_test
Expand Down Expand Up @@ -92,6 +94,7 @@ composer-audit:
conventions:
sh tools/verify-ascii-hyphens.sh
sh tools/verify-version-consistency.sh
sh tools/verify-text-domain.sh
sh tools/verify-boomerang-provenance.sh

translations:
Expand Down Expand Up @@ -128,10 +131,10 @@ package:
$(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/build-release.sh /repo/$(PLUGIN_DIR) /repo/release

package-verify:
$(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/verify-release.sh /repo/release/basicrum.zip
$(COMPOSE) run --rm --no-deps -w /repo $(PHP_SERVICE) sh /tools/verify-release.sh /repo/$(RELEASE_ARCHIVE)

package-smoke: package
sh tools/smoke-test-release.sh release/basicrum.zip
sh tools/smoke-test-release.sh $(RELEASE_ARCHIVE)

clean:
$(COMPOSE) down -v
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Basicrum is a privacy-first Real User Monitoring integration for WordPress. It loads the bundled Boomerang library, tags WordPress and WooCommerce page types, and sends performance beacons to a configured hosted or self-hosted Basicrum collector.

The installable plugin lives in [`plugins/basicrum/`](plugins/basicrum/). Build release artifacts through the repository tooling instead of zipping the source directory directly.
The plugin source lives in [`plugins/basicrum/`](plugins/basicrum/). Release tooling packages it under the assigned WordPress.org directory slug `basicrum-real-user-monitoring`; do not zip the source directory directly.

## Privacy

Expand All @@ -18,7 +18,7 @@ The complete webmaster-facing behavior and consent instructions live in the [Wor

| Path | Purpose |
| --- | --- |
| [`plugins/basicrum/`](plugins/basicrum/) | Installable plugin source |
| [`plugins/basicrum/`](plugins/basicrum/) | Plugin source packaged under the WordPress.org slug |
| [`tools/`](tools/) | Setup, test, and release scripts |
| [`docker/`](docker/) | Local WordPress and WooCommerce environments |
| [`tests/javascript/`](tests/javascript/) | Browser tests for loaders, consent adapters, and settings |
Expand Down Expand Up @@ -53,7 +53,7 @@ See [AGENTS.md](AGENTS.md) for repository invariants, the complete check suite,

## Releases

`make package` creates `release/basicrum.zip` and its SHA-256 checksum from a temporary production Composer install. `make package-smoke` installs that ZIP into clean WordPress and checks activation, the administration page, frontend loading, and PHP logs.
`make package` creates `release/basicrum-real-user-monitoring.zip` and its SHA-256 checksum from a temporary production Composer install. `make package-smoke` installs that ZIP into clean WordPress and checks activation, the administration page, frontend loading, and PHP logs.

The plugin header version, `BASICRUM_VERSION`, WordPress `Stable tag`, top changelog version, and `v<version>` release tag must match.

Expand All @@ -64,7 +64,7 @@ git tag -a vX.Y.Z -m "Basicrum vX.Y.Z"
git push origin vX.Y.Z
```

The tag workflow verifies the version, runs the release tests, builds and smoke-tests the installable ZIP, and only then creates the GitHub Release with `basicrum.zip` and `basicrum.zip.sha256`. Do not create the GitHub Release or upload the ZIP manually.
The tag workflow verifies the version, runs the release tests, builds and smoke-tests the installable ZIP, and only then creates the GitHub Release with `basicrum-real-user-monitoring.zip` and `basicrum-real-user-monitoring.zip.sha256`. Do not create the GitHub Release or upload the ZIP manually.

## Contributing and security

Expand Down
7 changes: 5 additions & 2 deletions checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Acceptance criteria:
- [ ] Record the minifier and its version in a lock file.
- [ ] Make CI regenerate the loaders and fail when the committed output differs.
- [ ] Document the source and version of the bundled Boomerang asset.
- [x] Add a repeatable command for generating `languages/basicrum.pot`.
- [x] Add a repeatable command for generating `languages/basicrum-real-user-monitoring.pot`.
- [x] Keep locale-specific PO and MO files out of the repository and release ZIP.
- [x] Keep POT generation as a local maintenance command; the standalone
translation CI job was removed by product decision.
Expand All @@ -164,7 +164,10 @@ Acceptance criteria:
tracked source, comments, documentation, and user-facing text.
- [x] Add a version consistency check covering the plugin header,
`BASICRUM_VERSION`, `Stable tag`, changelog, and release tag.
- [x] Run both checks in pull requests and pushes to the main branch.
- [x] Add a WordPress.org slug and text-domain consistency check covering the
plugin header, source literals, WPCS configuration, POT filename, and release
package identity.
- [x] Run all convention checks in pull requests and pushes to the main branch.
- [x] Document the checks in `AGENTS.md` and the contributor documentation.

Acceptance criteria:
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ services:
- "${WORDPRESS_PORT:-9080}:80"
volumes:
- wordpress_data:/var/www/html
- ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum
- ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring

wpcli:
image: wordpress:cli-2.12.0-php8.2
Expand All @@ -53,7 +53,7 @@ services:
WP_ADMIN_EMAIL: ${WP_ADMIN_EMAIL:-admin@example.test}
volumes:
- wordpress_data:/var/www/html
- ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum
- ./plugins/basicrum:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring
- ./tools:/tools:ro

php:
Expand Down
2 changes: 1 addition & 1 deletion docker/release-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ services:
WORDPRESS_DB_PASSWORD: wordpress
volumes:
- wordpress_data:/var/www/html
- "${BASICRUM_RELEASE_ZIP}:/artifacts/basicrum.zip:ro"
- "${BASICRUM_RELEASE_ZIP}:/artifacts/basicrum-real-user-monitoring.zip:ro"

volumes:
wordpress_data:
4 changes: 2 additions & 2 deletions docker/woocommerce-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ services:
WORDPRESS_DB_PASSWORD: wordpress
volumes:
- wordpress_data:/var/www/html
- plugin_workspace:/var/www/html/wp-content/plugins/basicrum:ro
- plugin_workspace:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring:ro

wpcli:
# Reviewed tag: wordpress:cli-2.12.0-php8.2
Expand All @@ -49,7 +49,7 @@ services:
HTTP_HOST: wordpress
volumes:
- wordpress_data:/var/www/html
- plugin_workspace:/var/www/html/wp-content/plugins/basicrum:ro
- plugin_workspace:/var/www/html/wp-content/plugins/basicrum-real-user-monitoring:ro
- ../tools:/tools:ro

plugin:
Expand Down
2 changes: 1 addition & 1 deletion docs/audits/evidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ to the original privacy report:
| COOKIE-07 (privacy 2) | high | consent loader `:222-236`; bundle tail init glue | both | Run `tests/javascript/consent-optout-race.spec.js` from worktree `.claude/worktrees/wf_14de6d93-758-3/` (promise-gated delayed script, no timeouts) | Race reproduced deterministically: spec FAILS against unmodified loaders (late script inits, sets cookie, beacons); passes with the 11-line fix; full 93-test suite green incl. byte-contract and global-surface tests | high |
| BR-WP-15 (privacy 3) | medium sev / high conf | `src/Setup.php:57-60`; `src/Compatibility.php:36-54` | static | `grep -rn 'purge\|rocket_clean\|w3tc_flush' plugins/basicrum/src plugins/basicrum/uninstall.php` | No purge call anywhere; deactivate() deletes one transient; the six cache-plugin exclusion filters guarantee the loader survives in cached HTML | high |
| DF-08/COOKIE-13/DISC-04 (privacy 4) | low-disclosure | `src/Admin/Privacy.php:48`; readme.txt | both | `grep -n 'first-party cookies' plugins/basicrum/src/Admin/Privacy.php; grep -ni cookie plugins/basicrum/readme.txt`. Runtime: `context.cookies()` after a page view | RT observed: 7.000-day expiry renewed on every view (rolling), SameSite=Strict, path=/, sub-values `z,dm,si,ss,sl,tt,bcn,ld`; `si` = random UUID stable across views, echoed as `rt.si` on every beacon. No public text names RT, its lifetime, or the identifier. BA never created (runtime + zero bundle occurrences) | high |
| DISC-10 (privacy 5, SUPERSEDED) | resolved by product decision | `.github/workflows/ci.yml`; `tools/update-translations.sh`; `.distignore` | static | `find plugins/basicrum/languages -type f`; `rg -n 'translations:' .github/workflows/ci.yml` | Bulgarian PO/MO catalogs and the standalone translation CI job were removed on 2026-07-19. The local generator now maintains only `basicrum.pot`; release packaging excludes and rejects locale-specific PO/MO files. | high |
| DISC-10 (privacy 5, SUPERSEDED) | resolved by product decision | `.github/workflows/ci.yml`; `tools/update-translations.sh`; `.distignore` | static | `find plugins/basicrum/languages -type f`; `rg -n 'translations:' .github/workflows/ci.yml` | Bulgarian PO/MO catalogs and the standalone translation CI job were removed on 2026-07-19. The local generator now maintains only `basicrum-real-user-monitoring.pot`; release packaging excludes and rejects locale-specific PO/MO files. | high |
| DISC-08 (privacy 6) | low | `readme.txt:22,70`; `src/PageTypeDetector.php` | static | `sed -n '22p;70p' plugins/basicrum/readme.txt; grep -n "return '" plugins/basicrum/src/PageTypeDetector.php` | Readme lists 7+3 types; detector returns 17 incl. checkout_payment, checkout_success, account, product_category, tag, author, date_archive | high |
| DISC-09 (privacy 7) | low | `plugins/basicrum/README.md` | static | `sed -n '4p;14p;51p;86p' plugins/basicrum/README.md` | Stock template stub with placeholder text and fake security-fix changelog; excluded from ZIP by verify-release.sh | high |
| BR-WP-14 (privacy 8) | low | `uninstall.php:13-20` | static | `grep -rn is_multisite plugins/basicrum/uninstall.php plugins/basicrum/src; echo exit=$?` | Exit 1 (no match): no multisite iteration; per-site options persist on other subsites | medium |
Expand Down
5 changes: 3 additions & 2 deletions docs/audits/privacy-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ standalone translation CI job were removed. Keep the POT-only local generator
for future gettext changes, and keep locale-specific catalogs out of release
ZIPs unless bundled translations are deliberately restored.

- [x] Regenerate and commit `languages/basicrum.pot` when source strings change.
- [x] Regenerate and commit `languages/basicrum-real-user-monitoring.pot` when source strings change.
- [x] Exclude and reject locale-specific PO/MO files in release packages.

## 6. Match public page-type lists to the detector (DISC-08)
Expand Down Expand Up @@ -207,7 +207,8 @@ severity: the residue is operator configuration, not visitor personal data.
real WordPress/WooCommerce stack assert `p_type`, `p_gen=wp`, and the
configured `brum_site_id`; collector is a reserved `.test` host answered
with HTTP 204.
- [x] `make conventions`: ASCII hyphen and version consistency checks pass.
- [x] `make conventions`: ASCII hyphen, version consistency, and WordPress.org
text-domain checks pass.

## 13. Residual test gaps (future work)

Expand Down
33 changes: 12 additions & 21 deletions docs/audits/wporg-submission-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned.
the upstream repository, the exact source commit (the bundle header
carries 564759ed70de7801bb64de5e2025fb6ac049ff5f), and the build
procedure; ship Boomerang's BSD license text alongside the bundle. (B2)
- [x] RESOLVED 2026-07-20: phpstan.neon.dist added to .distignore and the verify-release dev-file regex; ZIP rebuilt and verified clean. Original finding: dev file leaks into the ZIP: release/basicrum.zip contains
- [x] RESOLVED 2026-07-20: phpstan.neon.dist added to .distignore and the verify-release dev-file regex; ZIP rebuilt and verified clean. Original finding: dev file leaked into the release ZIP.
basicrum/phpstan.neon.dist. Add it to plugins/basicrum/.distignore and
to the verify-release.sh dev-file regex, rebuild. Plugin Check would
flag it. (D2a, B7)
Expand All @@ -46,27 +46,24 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned.
0.0.x builds and can be misread as shipped-version history. Decide
whether 0.0.7/0.0.6 entries stay (internal history) or fold in. (C13,
C14)
- [x] RESOLVED 2026-08-21: Plugin Check 2.1.0 completed against the exact
- [x] SUPERSEDED 2026-08-27: Plugin Check 2.1.0 completed against the exact
`v0.0.9` ZIP built from tagged commit
`f689a3616e897c07a6dd60c51b4985bebeef2988` (SHA-256
`7321a346e3e9e8cc0b4c8cd749a8fa8f209614281da5133cdfcd704f98b42197`).
WP-CLI ran all stable checks in new-submission mode with slug `basicrum`, no
ignored codes, and Plugin Check's `cli.php` loaded so runtime checks were
included. Strict and raw-result runs completed successfully with no result
rows. The earlier `outdated_tested_upto_header` finding was resolved by the
WordPress 7.1 compatibility update. (B7)
- [x] RESOLVED 2026-08-20: the permanent directory slug is decided. wp.org
autogenerates the slug from the plugin header Plugin Name at submission and
cannot rename it after approval, so `Basicrum - Real User Monitoring` will be
offered `basicrum-real-user-monitoring`. The display name stays descriptive
and the shorter `basicrum` slug is requested through the documented one-time
correction: the FAQ states "You can update your slug once after submitting
it. Every submission gets an automated email with directions." Both
`basicrum` and `basicrum-real-user-monitoring` were unregistered on
2026-08-20 (wordpress.org/plugins/<slug>/ redirects to search for each).
`basicrum` is what the generated POT `Report-Msgid-Bugs-To` and the plugin
directory name already assume, so taking it keeps the support URL correct.
This is a user-only action on submission day; see the list below.
WordPress 7.1 compatibility update. This check used the earlier provisional
`basicrum` package identity and is retained only as historical evidence. (B7)
- [x] RESOLVED 2026-08-27: WordPress.org assigned the permanent directory slug
`basicrum-real-user-monitoring`. The plugin header, every gettext call, WPCS
configuration, POT filename and metadata, local and WooCommerce installation
paths, release ZIP name, and release ZIP root now use that identity. Plugin
Check 2.1.0 completed against the rebuilt ZIP under the assigned slug with no
errors. Repository conventions and release verification prevent the text
domain and package root from drifting back to the provisional `basicrum`
identity.
- [x] RESOLVED 2026-08-20: External services now links the service privacy
information guideline 6 and the common-issues page ask for. The Basicrum
Privacy Notice covers only basicrum.com, its contact form, and beta requests,
Expand Down Expand Up @@ -160,9 +157,3 @@ refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned.
5. Confirm the two outside code contributors are content with the GPLv2-or-later
relicense. MIT permits the sublicense, so this is a courtesy record, not a
blocker.
6. On the submission email, use the one-time slug update to change
`basicrum-real-user-monitoring` to `basicrum` before approval. The slug is
permanent afterwards, and it also sets the SVN path, the installed folder
name, and the support URL the POT already points at. Keep the display name
`Basicrum - Real User Monitoring`; wp.org treats display name and slug
separately, and the display name stays editable after approval.
2 changes: 1 addition & 1 deletion plugins/basicrum/.distignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ playwright*.config.js
/languages/*.mo

coverage.xml
basicrum.zip
basicrum-real-user-monitoring.zip
/release
phpstan.neon.dist
8 changes: 5 additions & 3 deletions plugins/basicrum/basicrum.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Author URI: https://www.basicrum.com/contact/
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: basicrum
* Text Domain: basicrum-real-user-monitoring
* Domain Path: /languages
* Requires at least: 6.0
* Requires PHP: 7.4
Expand All @@ -28,13 +28,15 @@

if ( ! is_readable( $basicrum_autoloader ) ) {
$basicrum_missing_autoloader_notice = static function () {
if ( ! current_user_can( 'activate_plugins' ) ) {
global $pagenow;

if ( 'plugins.php' !== $pagenow || ! current_user_can( 'activate_plugins' ) ) {
return;
}

printf(
'<div class="notice notice-error"><p>%s</p></div>',
esc_html__( 'Basicrum could not start because its Composer dependencies are missing. Reinstall the plugin from an official release ZIP.', 'basicrum' )
esc_html__( 'Basicrum could not start because its Composer dependencies are missing. Reinstall the plugin from an official release ZIP.', 'basicrum-real-user-monitoring' )
);
};

Expand Down
Loading