Skip to content

Commit d130088

Browse files
Tsvetan StoychevTsvetan Stoychev
authored andcommitted
Prepare plugin for WordPress.org submission
1 parent 6bddbff commit d130088

9 files changed

Lines changed: 158 additions & 31 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# WordPress.org Submission Checklist (2026-07-19)
2+
3+
Factuality and ambiguity audit of the submission surfaces (readme.txt,
4+
basicrum.php header, wordpress-org-assets, release ZIP) at version 0.0.8,
5+
ahead of the plugin-directory submission. Method: four auditors (line-by-line
6+
readme factuality vs code, current wp.org handbook requirements, two-persona
7+
ambiguity sweep, hands-on official readme validator + reviewer-style ZIP
8+
inspection); every non-clean verdict adversarially re-checked by two
9+
refuters. 84 claims audited: 52 clean, 24 upheld findings, 8 overturned.
10+
11+
## 1. Blockers - must be resolved before submission
12+
13+
- [x] RESOLVED 2026-07-20: user registered the wordpress.org account `basicrum`; readme.txt Contributors updated to `basicrum`. Original finding: Contributors username did not exist. The OFFICIAL wp.org readme
14+
validator returned verbatim: "The following contributors listed were
15+
ignored, as the WordPress.org user could not be found. tstoychev."
16+
Register the wordpress.org account with exactly that username (or change
17+
readme.txt line 2 to the registered account that will submit), and
18+
confirm profiles.wordpress.org/tstoychev resolves. (D1a, R02, B6)
19+
- [x] RESOLVED 2026-07-20: Boomerang BSD LICENSE.txt now ships at assets/js/boomr/LICENSE.txt; readme.txt Third-party section and THIRD-PARTY-NOTICES.txt name the source commit and repositories. UPGRADED 2026-07-20: build reproduced BYTE-IDENTICAL (SHA-256 90e8a1c8...) from basicrum/boomerang master commit ead2783a with Node 12 + npm ci + grunt clean build --build-flavor=cutting-edge --build-number=815; the in-file banner stamps parent commit 564759ed because the final continuity.js change was uncommitted at original build time - docs now state both hashes; tools/verify-boomerang-provenance.sh guards bundle/docs sync via make conventions. Original finding: human-readable source for the bundled Boomerang (guideline 4:
20+
reviewers require public, maintained access to source and build tools
21+
for minified files). assets/js/boomr/ ships only the .min.js; its header
22+
says "See the accompanying LICENSE.txt" and none accompanies it. Add to
23+
readme.txt (Development or Third-party section) and THIRD-PARTY-NOTICES.txt:
24+
the upstream repository, the exact source commit (the bundle header
25+
carries 564759ed70de7801bb64de5e2025fb6ac049ff5f), and the build
26+
procedure; ship Boomerang's BSD license text alongside the bundle. (B2)
27+
- [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
28+
basicrum/phpstan.neon.dist. Add it to plugins/basicrum/.distignore and
29+
to the verify-release.sh dev-file regex, rebuild. Plugin Check would
30+
flag it. (D2a, B7)
31+
32+
## 2. Reviewer-flag items - fix to avoid review friction
33+
34+
- [x] RESOLVED 2026-07-20: External services section added to readme.txt. Original: add an "External services" readme section in the current
35+
reviewer-requested format: name the service (operator-configured
36+
collector; basicrum.com hosted option), what data is sent and when
37+
(performance beacons: URLs, timings, page type, site id; IP and user
38+
agent visible to the collector), and links to the service terms/privacy
39+
pages. The FAQ covers parts of this but not in the expected form. (B4)
40+
- [x] RESOLVED 2026-07-20: "Does Basicrum set cookies?" FAQ added (RT named with attributes and lifetime; BA described as legacy removal); RT also named in the Privacy Policy Guide text (Privacy.php) with test assertions. Original: add a cookies FAQ: the readme never names the first-party RT and BA
41+
cookies the listing's own privacy story depends on ("Does Basicrum set
42+
cookies?" - names, purpose, consent-mode behavior, opt-out removal).
43+
(C10)
44+
- [x] RESOLVED 2026-07-20: changelog collapsed to a single first-release entry. Original: collapse the 0.0.8 changelog into a single first-release feature
45+
entry; the current six bullets describe diffs against never-published
46+
0.0.x builds and can be misread as shipped-version history. Decide
47+
whether 0.0.7/0.0.6 entries stay (internal history) or fold in. (C13,
48+
C14)
49+
- [ ] Run Plugin Check against the BUILT release/basicrum.zip (not the
50+
repo tree) after the fixes and keep the output for the submission. (B7)
51+
- [ ] Tested up to 7.0: internally defensible (blocking CI rows for wp
52+
7.0 exist; format correct - verdict overturned by refuters), but
53+
re-confirm on submission day that WordPress 7.0 is the current released
54+
stable. (R05)
55+
56+
## 3. Ambiguity fixes - upheld copy issues
57+
58+
- [x] RESOLVED 2026-07-20: FAQ reworded (hosted account is one way; self-hosted needs no account). Original: account FAQ answered "Yes." then contradicts
59+
itself: self-hosted collectors need no account. Reword: collector
60+
endpoint + Brum Site ID required; hosted account is one way to get
61+
them. (R24, C04)
62+
- [ ] Vocabulary bridge: the compliance FAQ says "immediate and
63+
consent-controlled loading" while the settings radios say "Monitor
64+
without consent" / "Require consent before monitoring". Bridge both
65+
vocabularies once, then use the radio labels. (C02)
66+
- [ ] Define the server-side nouns once: collector (receives beacons) vs
67+
backoffice (dashboard where the Brum Site ID lives) vs account (hosted
68+
option); "backoffice" is currently undefined jargon. (C15)
69+
- [ ] Disambiguate "Basicrum" = plugin vs company vs service in the
70+
query-string FAQ: data goes only to the operator-configured Beacon URL;
71+
the plugin makes no requests to basicrum.com. (C16)
72+
- [ ] HTTP Strictness FAQ still inverts the semantics (enabling
73+
"Strictness" relaxes enforcement). Rewrite the FAQ to lead with the
74+
default (auto-upgrade to HTTPS) and what the toggle actually allows;
75+
the label rename remains open from the operator-experience audit. (C08)
76+
- [ ] "eligible pages" in the contributed privacy-policy text
77+
(Privacy.php immediate-mode sentence) is undefined for site owners;
78+
spell out: frontend pages, admins excluded unless Track Admin Users.
79+
(C12)
80+
- [ ] Define "connected" CookieYes at first use (linked to the CookieYes
81+
web app so its browser consent API is present). (C07)
82+
- [ ] Replace "fails closed" jargon: "keeps monitoring switched off until
83+
its consent API reports a decision". (C19)
84+
- [ ] "How it works" step 2 orders enable-before-Site-ID, contradicting
85+
Installation steps 4-5 and triggering the enabled-but-inactive notice;
86+
align the order. (C22)
87+
- [ ] "after the configured Script Position" forward-references an
88+
undefined setting; name it: Basicrum > Performance > Script Position
89+
(header or footer). (C23)
90+
91+
## 4. Optional but recommended
92+
93+
- [ ] Screenshots: the section was correctly removed (no files existed),
94+
but an image-free listing forces users to imagine the settings-driven
95+
consent workflow. Capture screenshot-1..N.png using the exact current
96+
labels (Visitor Consent, Consent Tool Connection) and restore a
97+
matching section. (C24)
98+
- [ ] Spot-check the two basicrum.com URLs (home, /contact/) resolve;
99+
reviewers click them. (R45)
100+
- [ ] CookieYes "modern ... runtime" - one refuter pair split on this;
101+
consider "CookieYes 3.x" with a one-line legacy note for precision.
102+
(C06)
103+
104+
## 5. Verified clean (highlights)
105+
106+
- [x] Version consistency: header, BASICRUM_VERSION, Stable tag, top
107+
changelog all 0.0.8; no git tags, consistent with first release. (R07)
108+
- [x] Short description 95 chars (under 150), byte-identical to the
109+
header Description; privacy-first claim backed by defaults. (R09, C01
110+
overturned)
111+
- [x] MIT license declared consistently (readme, header, LICENSE.md,
112+
composer.json); GPL-compatible; Boomerang BSD is GPL-compatible;
113+
THIRD-PARTY-NOTICES.txt scopes correctly. (R08, B1)
114+
- [x] All five tags valid and implemented; Requires at least 6.0 and
115+
Requires PHP 7.4 match headers, composer, and CI matrix. (R03, R04, R06)
116+
- [x] Feature claims verified against code: page-type values verbatim in
117+
PageTypeDetector.php with correctly hedged non-exhaustive lists;
118+
detection markers and version floors match ConsentIntegration.php;
119+
cache-plugin list matches Compatibility.php; guideline 7 satisfied
120+
(off by default, consent-controlled default). (R12-R15, B4-part)
121+
- [x] Plugin header complete: Requires at least, Requires PHP, Text
122+
Domain, Domain Path present; validator returned only the Contributors
123+
warning - readme parses cleanly otherwise. (D1a)
124+
- [x] ZIP contents otherwise reviewer-clean: no repo README, tests,
125+
docs/, node_modules, or scratch; readable+minified loader pairs and all
126+
five adapters present; production-only vendor/. (D2)
127+
128+
## User-only actions before submission day
129+
130+
1. Register/confirm the wordpress.org username matching Contributors.
131+
2. Re-confirm WordPress 7.0 is the current released stable.
132+
3. Verify basicrum.com pages linked from the listing are live.

‎plugins/basicrum/.distignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
/.distignore
99

1010
.phpunit.result.cache
11-
composer.json
1211
composer.lock
1312
patchwork.json
1413
phpcs.ruleset.xml
@@ -24,3 +23,4 @@ playwright*.config.js
2423
coverage.xml
2524
basicrum.zip
2625
/release
26+
phpstan.neon.dist

‎plugins/basicrum/languages/basicrum.pot‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ msgid "Suggested text:"
5757
msgstr ""
5858

5959
#: src/Admin/Privacy.php:48
60-
msgid "This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor's browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang may use first-party cookies to maintain measurement state."
60+
msgid "This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor's browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang stores measurement state in a first-party cookie named RT, which contains a random session identifier that links page views, uses SameSite=Strict, is marked Secure on HTTPS sites, and expires seven days after the last monitored page view. Opting out removes the RT cookie and any legacy BA cookie."
6161
msgstr ""
6262

6363
#: src/Admin/Privacy.php:52

‎plugins/basicrum/readme.txt‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
=== Basicrum - Real User Monitoring ===
2-
Contributors: tstoychev
2+
Contributors: basicrum
33
Tags: analytics, performance, rum, real-user-monitoring, web-vitals
44
Requires at least: 6.0
55
Tested up to: 7.0
@@ -56,7 +56,7 @@ Boomerang.js is an open source JavaScript library by Akamai that measures the pe
5656

5757
= Do I need a Basicrum account? =
5858

59-
Yes. You need a Basicrum collector endpoint and the matching Brum Site ID. Visit [basicrum.com](https://www.basicrum.com/) for hosted options, or use your own self-hosted collector.
59+
You need a Basicrum collector endpoint and the matching Brum Site ID. A hosted account from [basicrum.com](https://www.basicrum.com/) is one way to get them; running your own self-hosted collector requires no account.
6060

6161
= Does Basicrum make my site compliant with privacy laws? =
6262

@@ -76,6 +76,10 @@ Detection confirms that a supported integration is present, not that its consent
7676

7777
By default, Basicrum may send complete query strings in page, navigation, referrer, and resource URLs. Enable **Basicrum > Visitor Privacy > Strip Query Strings** to replace them with `?qs-redacted` before sending beacons. URL paths are still collected. Review whether your URLs can contain personal or sensitive information before deciding whether to enable this setting.
7878

79+
= Does Basicrum set cookies? =
80+
81+
When Boomerang runs, it sets a first-party `RT` cookie that maintains timing state across consecutive pages. It uses `SameSite=Strict`, carries the `Secure` flag on HTTPS sites, and expires seven days after the last monitored page view. In **Require consent before monitoring** mode no cookie is set until your consent tool reports an allow decision, and the opt-out callback removes the `RT` cookie together with any legacy `BA` cookie left by older Boomerang setups.
82+
7983
= Does it work with WooCommerce? =
8084

8185
Yes. When WooCommerce is active, the plugin emits `shop`, `product`, `product_category`, `cart`, `checkout`, `checkout_payment`, `checkout_success`, and `account` page types when the corresponding WooCommerce conditional is true.
@@ -84,6 +88,14 @@ Yes. When WooCommerce is active, the plugin emits `shop`, `product`, `product_ca
8488

8589
Yes. Enable HTTP Strictness under Basicrum's Developer Settings to preserve HTTP beacon URLs. Keep it disabled on production sites so HTTP beacon URLs are automatically upgraded to HTTPS.
8690

91+
== External services ==
92+
93+
This plugin sends visitor performance beacons to the collector endpoint that the site administrator configures under **Basicrum > General Settings > Beacon URL**. No beacon is sent until monitoring is enabled and, in the default **Require consent before monitoring** mode, an allow decision is reported by the site's consent tool.
94+
95+
Each beacon carries performance data: page and resource URLs (with optional query-string redaction), timing metrics, the detected page type, and the configured Brum Site ID. As with any HTTP request, the collector also observes the visitor's IP address and user agent. Beacons go only to the configured Beacon URL; the plugin makes no requests to basicrum.com or any other service on its own.
96+
97+
The collector can be the hosted Basicrum service or a self-hosted installation. For the hosted service, see the [Basicrum website](https://www.basicrum.com/) for service and privacy information. Operators of self-hosted collectors are responsible for their own hosting arrangements.
98+
8799
== Third-party software ==
88100

89101
Basicrum-owned code is licensed under the MIT License. The bundled Boomerang 1.815.60 library retains its upstream BSD license and copyright notices. See `THIRD-PARTY-NOTICES.txt` and `assets/js/boomr/LICENSE.txt` in the plugin package.
@@ -93,10 +105,4 @@ The bundled file `assets/js/boomr/boomerang-1.815.60.cutting-edge.min.js` is a m
93105
== Changelog ==
94106

95107
= 0.0.8 =
96-
* First public release.
97-
* Reordered the Visitor Consent choices and hid Consent Tool Connection when consent is not required.
98-
* Replaced the unused consent-mode selector with clear immediate and consent-controlled loading choices.
99-
* Made external consent tools authoritative on every page through two explicit callbacks.
100-
* Added a privacy-safe default, transparent integration guidance, and WordPress Privacy Policy Guide content.
101-
* Added first-class query-string protection under Visitor Privacy, disabled by default.
102-
* Added fail-closed automatic selection for WP Consent API, Borlabs Cookie 3.2+, and the modern CookieYes plugin marker, with manual callbacks available as an explicit choice.
108+
* First public release: Real User Monitoring via the bundled Boomerang.js with WordPress and WooCommerce page-type detection, a consent-required default with fail-closed automatic consent-tool detection (WP Consent API, Borlabs Cookie 3.2+, CookieYes 3.x) plus manual callbacks, optional query-string redaction, editable WordPress Privacy Policy Guide text, and optimization-plugin script exclusions.

‎plugins/basicrum/src/Admin/Privacy.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function add_policy_content() {
4545
$content .= '</p>';
4646
$content .= '<p><strong>' . esc_html__( 'Suggested text:', 'basicrum' ) . '</strong></p>';
4747
$content .= '<p>';
48-
$content .= esc_html__( 'This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor\'s browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang may use first-party cookies to maintain measurement state.', 'basicrum' );
48+
$content .= esc_html__( 'This site uses Basicrum to measure real-user performance. When monitoring runs, a visitor\'s browser sends page and resource URLs, performance and interaction timing metrics, page type, the configured site identifier, and technical browser, device, and network information to a performance collector. The collector also receives request information such as the IP address and user agent. Boomerang stores measurement state in a first-party cookie named RT, which contains a random session identifier that links page views, uses SameSite=Strict, is marked Secure on HTTPS sites, and expires seven days after the last monitored page view. Opting out removes the RT cookie and any legacy BA cookie.', 'basicrum' );
4949
$content .= '</p>';
5050
$content .= '<p>';
5151
if ( '1' === $settings['strip_query_string'] ) {

‎plugins/basicrum/src/Admin/Settings/Page.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ public function render_text_field( $args ) {
632632
'<input id="basicrum_%1$s" name="%2$s" type="text" size="%3$d" value="%4$s" placeholder="%5$s" class="%6$s"',
633633
esc_attr( $id ),
634634
esc_attr( $name ),
635-
$size,
635+
absint( $size ),
636636
esc_attr( $value ),
637637
esc_attr( $placeholder ),
638638
esc_attr( implode( ' ', $input_classes ) )
@@ -691,9 +691,9 @@ public function render_number_field( $args ) {
691691
'<input id="basicrum_%1$s" name="%2$s" type="number" min="%3$d" max="%4$d" value="%5$d"',
692692
esc_attr( $id ),
693693
esc_attr( $name ),
694-
$min,
695-
$max,
696-
$value
694+
absint( $min ),
695+
absint( $max ),
696+
absint( $value )
697697
);
698698
if ( $is_disabled ) {
699699
echo ' disabled="disabled"';

‎plugins/basicrum/src/Plugin.php‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class Plugin {
2222
* @return void
2323
*/
2424
public function register() {
25-
add_action( 'init', array( $this, 'load_textdomain' ) );
2625

2726
// Services loaded on every request (frontend + admin).
2827
new Setup();
@@ -48,17 +47,4 @@ private function register_admin_services() {
4847
new Admin\Settings\Page();
4948
new Admin\Privacy();
5049
}
51-
52-
/**
53-
* Load plugin text domain for translations.
54-
*
55-
* @return void
56-
*/
57-
public function load_textdomain() {
58-
load_plugin_textdomain(
59-
'basicrum',
60-
false,
61-
dirname( plugin_basename( BASICRUM_PLUGIN_FILE ) ) . '/languages'
62-
);
63-
}
6450
}

‎plugins/basicrum/tests/unit/PrivacyTest.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ function( $policy_title, $policy_content ) use ( &$title, &$content ) {
6767
$this->assertStringContainsString( '?qs-redacted', $content );
6868
$this->assertStringContainsString( 'URL paths are still collected', $content );
6969
$this->assertStringContainsString( 'IP address and user agent', $content );
70+
$this->assertStringContainsString( 'cookie named RT', $content );
71+
$this->assertStringContainsString( 'expires seven days after the last monitored page view', $content );
7072
$this->assertStringContainsString( '<code>https://collector.example.test/beacon</code>', $content );
7173
$this->assertStringContainsString( 'consent tool on every page', $content );
7274
$this->assertStringContainsString( 'does not persist consent across page loads', $content );

‎tools/verify-release.sh‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ require_entry 'basicrum/uninstall.php'
3838
require_entry 'basicrum/readme.txt'
3939
require_entry 'basicrum/LICENSE.md'
4040
require_entry 'basicrum/THIRD-PARTY-NOTICES.txt'
41+
require_entry 'basicrum/composer.json'
4142
require_entry 'basicrum/src/Plugin.php'
4243
require_entry 'basicrum/src/Assets.php'
4344
require_entry 'basicrum/src/ConsentIntegration.php'
@@ -112,7 +113,7 @@ if ! unzip -p "$ARCHIVE_PATH" basicrum/THIRD-PARTY-NOTICES.txt | grep -Fq 'Boome
112113
exit 1
113114
fi
114115

115-
if printf '%s\n' "$ARCHIVE_ENTRIES" | grep -Eq '^basicrum/(\.distignore|composer\.(json|lock)|package(-lock)?\.json|playwright[^/]*\.config\.(js|cjs|mjs|ts)|patchwork\.json|phpcs\.ruleset\.xml|phpunit[^/]*\.xml|README\.md|coverage\.xml|\.phpunit\.result\.cache)$'; then
116+
if printf '%s\n' "$ARCHIVE_ENTRIES" | grep -Eq '^basicrum/(\.distignore|composer\.lock|package(-lock)?\.json|playwright[^/]*\.config\.(js|cjs|mjs|ts)|patchwork\.json|phpcs\.ruleset\.xml|phpunit[^/]*\.xml|phpstan\.neon\.dist|README\.md|coverage\.xml|\.phpunit\.result\.cache)$'; then
116117
printf '%s\n' 'Release archive contains a development file.' >&2
117118
exit 1
118119
fi

0 commit comments

Comments
 (0)