Who Can Do What? Accessibility Checker Permissions ![rw-book-cover](https://i.ytimg.com/vi/RSVapIrLlZg/maxresdefault.jpg) 🔗 **Source:** [Who Can Do What? Accessibility Checker Permissions](https://www.youtube.com/watch?v=RSVapIrLlZg) > [!note]+ Document Notes > > [!info] Analysis generated 2026-08-27 by Claude (Opus 5) via readwise-deep-read. > > **Source:** YouTube livestream — https://www.youtube.com/watch?v=RSVapIrLlZg · ~6,723 words · 46.6 min (Accessibility Checker changelog stream, Equalize Digital). > > **Speakers:** Steve Jones (CTO) and William Patton (Senior Developer), Equalize Digital. Reader's author field said "youtube.com." > > Register key: [STATED] · [EVIDENCE] · [INFERENCE] · [RECOMMEND]. Transcript recovered by local Whisper (base.en) — YouTube never produced VOD captions for this stream; minor mishearings noted (e.g. "sayings"=settings, "restaurant"=restriction, "all the history"=audit history, "full sex again"=full-site scan, "80 posts"=edit posts). > > # 🏷️ Title: Who Can Do What? Accessibility Checker Permissions > <!-- deep-read:sections start --> ## 🧭 Table of Contents - [📝 Summary](#-summary) - [📖 Main Content](#-main-content) - [🗒️ Notes](#️-notes) - [📚 References](#-references) - [🗣️ Paraphrase](#️-paraphrase) - [📰 Newsletter](#-newsletter) - [✅ Action Items](#-action-items) - [🧪 Hypotheses](#-hypotheses) - [📊 Methodology](#-methodology) - [❓ Questions](#-questions) - [🔮 Future Research](#-future-research) - [💡 Implications](#-implications) - [🧠 Learning Styles Assessment](#-learning-styles-assessment) - [📊 Accessibility Assessment](#-accessibility-assessment) - [🌍 DEIB Assessment](#-deib-assessment) - [✅ Logical Validity](#-logical-validity) - [🛡️ DARVO Analysis](#-darvo-analysis) - [🎯 Conclusion](#-conclusion) ## 📝 Summary **What shipped.** [STATED] A granular role-based permissions system across the whole Accessibility Checker suite: free plugin 1.48, Pro 2.3.0, Export 1.5, Audit History 1.6 (Multisite got a notification-only update). A new **Permissions tab** in settings offers per-role capability grants — administrators deliberately excluded from the selector. **The capability inventory.** [STATED] Free: dismiss own issues · dismiss issues on any post · front-end highlighter. Pro: dismiss globally · Issue Explorer access · full-site scan. Audit History: view history. Export: export data. Custom roles appear in the selector alongside core roles. **The security architecture — the "double gate."** [STATED] Every custom capability check *also* checks a core-capability **floor** (`edit_posts` or `edit_others_posts`), enforced by helper functions at every mutation point: UI, REST API, and WP-CLI. William: even if a role editor plugin grants the custom capability to a subscriber, *"anytime we check a custom capability, we also check whatever the floor is as well. And the floor is what enforces security."* The floor also future-proofs against role drift: *"if someone changes the level of a role later on, we still need to be gating them."* **The one deliberate overstep.** [STATED] "Dismiss issues on any post" requires only `edit_posts` (not `edit_others_posts`) — the single capability that steps below core's expectation, built for auditor-type roles who should triage issues site-wide without content-edit rights. The UI labels it: *"even if the user cannot otherwise edit it."* **Upgrade philosophy.** [STATED] *"Never give someone access to something they don't already have."* Existing installs migrate the old ignore-permissions setting; new installs default to editors + authors getting dismiss-own + front-end highlighter. Permissions are **excluded from import/export and multisite cloning** — *"exports from one site should never carry permissions to another site for security reasons."* **The AI-scanner motive, said out loud.** [STATED] Steve: security has become *"of the utmost paramount concern… with the rise of AI… agents being able to scan and find security vulnerabilities."* William: *"If we weren't being considerate… we would have got flagged by some AI bot that found the vulnerability."* ## 📖 Main Content ### Why permissions, why now [STATED] Support tickets kept asking "why can't this user do X / why *can* this user do Y." The old model was one global "ignore permissions" setting from ~5 years ago that other features piggybacked on. Recent audit-remediation client projects surfaced stricter customer permission policies: *"people seem to be adding more strict policies around permissions inside their WordPress admins."* Customers also wanted **view separated from mutate** — some roles should see reports but not act, or vice versa. [STATED] Scope ballooned: *"It started as 'a role needs to be able to scan their pages' and it became weeks of pain."* ### The floor model [STATED] Rationale for gating dismissals on `edit_posts`: dismissed issues are stored in **post meta**, and editing post meta is a post-edit operation. *"You can absolutely bypass that very easily. We have chosen not to because that feels a bit like a security risk."* Dismiss-globally floors on `edit_others_posts` because global dismissal necessarily touches other authors' content. [STATED] Data-exposure reasoning: scanner results can contain content excerpts — *"it could be PII… that's been scanned in our database that we then don't want to over-expose."* The worked example: granting an author `edit_others_posts` (via another plugin) does **not** cascade into export rights — *"unexpectedly granting access by allowing people to edit things shouldn't give them access to all of the things."* [STATED] Ineligible grants are greyed out in the UI with helper text naming the missing core capability; expired Pro licenses grey out Pro capabilities with a license message. The same validation runs server-side, so the UI gate is cosmetic and the API gate is authoritative: *"regardless of what the UI shows, if they're not supposed to be able to do something, the API will also still block it."* ### The contributor caveat [STATED] Contributors have `edit_posts` but only for their **own unpublished** posts — once published, they can't dismiss, scan, or touch anything on it. The any-post overstep capability is partly aimed at this shape of user: audit access without content authority. ### Administrators and manage_options [STATED] Admins are absent from the permissions UI by design: *"if you have manage_options… you can almost do anything you choose at all times"* — including editing your own capabilities — so admin-level restriction is both self-lockout risk and theater. *"Core's own ethos is that manage_options is top-tier permission."* ### Live demo [EVIDENCE] Using the User Switching plugin across test roles: subscriber sees no front-end highlighter until granted it, and even then gets a read-only view (no ignore, no rescan — no mutation capabilities). Editor role has highlighter revoked and it disappears. Export-only role reaches only the export page; audit-history-only and explorer-only roles see exactly one menu item each. [EVIDENCE] One known UI gap: the Issue Explorer detail panel still renders its dismiss control for users who can't dismiss — hiding it per-post was *"too unperformant to check every single post one at a time"* in the React app — but the API returns "sorry, you're not allowed to do that." ### Escape hatches [STATED] Developer filters can raise or bypass the floors — *"a developer decision only, not something that we expose anywhere."* The capabilities are standard WordPress capabilities, so `WP_Role`/user-level grants work for per-user (not just per-role) assignment outside the plugin's UI. ### Multisite and import/export [STATED] Debated and rejected: cloning permission settings across subsites. Most multisites are multi-admin; subsite admins should decide their own access. Doing it safely would need *"a governance layer and an approval layer"* — deferred. The multisite add-on **stops** exporting the old ignore-roles setting. Both screens carry the notice: *"Security-related settings, user permissions and role capabilities are not included in export or import; configure permissions manually on each site."* ### Install/upgrade matrix [STATED] New install defaults: editors and authors get dismiss-own-issues + front-end highlighter. Upgrades with a saved custom setting migrate it (old ignore-grant → dismiss own, dismiss globally, front-end highlighter — never any-post, *"that's always a selective choice"*). Free→Pro upgrades inherit conservative Pro defaults. Deactivating/deleting add-ons preserves permission settings; only the base plugin's delete-all-data uninstall removes them. Plugins can update in any order without breaking gates. ## 🗒️ Notes - [INFERENCE] The "double gate" is the textbook fix for the most common WordPress permission bug: trusting a custom capability alone, which any role-editor plugin can hand to a subscriber. Checking custom cap AND core floor at every enforcement point (UI, REST, WP-CLI) via shared helper functions is the pattern worth stealing for any plugin adding capabilities — including post-kinds/Outpost work. - [INFERENCE] The deliberate, *documented* overstep is as instructive as the floors: they broke core parity exactly once, on the least dangerous mutation (issue dismissal), labeled it in the UI, and called it out unprompted on the stream. Security exceptions should be this legible. - [INFERENCE] The refusal to export/clone permission settings is the same decision class as the CRA/steward material in this batch: security configuration is site-local trust, not portable data. Their stated test — "people should know up front what they were importing" — generalizes. - [EVIDENCE] The AI-scanner quote is a field report matching this week's other reading (Wordfence Argus/PRISM, wp2shell): plugin authors now design permission systems with "an AI bot will diff my capability checks" as an explicit threat model. That's new, and they said it on a changelog stream. - [INFERENCE] The unperformant-to-hide-UI admission (per-post capability lookups in the React panel) is honest engineering: they shipped authoritative server-side denial with cosmetic UI leakage rather than an N+1 capability check. Right trade, clearly explained. - [STATED] Feedback window is open now on the chosen floors: *"let us know if we were correct in the floors that we picked… now is the time to get those in."* ## 📚 References [EVIDENCE] Named: **Accessibility Checker** (free, 1.48), **Accessibility Checker Pro** (2.3.0), **Audit History add-on** (1.6), **Export add-on** (1.5, CSV), **Multisite add-on**, **Issue Explorer** (prior livestream exists on it), **front-end highlighter**, **User Switching** plugin (demo), user-role-editor plugins (category), **WP_Role** class, **WP-CLI**, core capabilities `edit_posts` / `edit_others_posts` / `manage_options`, **Equalize Digital** docs page: equalizedigital.com/accessibility-checker/permissions-settings/. People: **Steve Jones** (CTO), **William Patton** (Senior Developer). ## 🗣️ Paraphrase Equalize Digital rebuilt Accessibility Checker's permissions from one global "who can ignore issues" checkbox into per-role, per-capability grants across the whole plugin suite. Every custom capability is double-gated behind a WordPress core capability floor (edit_posts / edit_others_posts) enforced in the UI, REST API, and WP-CLI alike, so role-editor plugins can't accidentally hand a subscriber the site's scan data. They broke core parity in exactly one documented place (dismiss-on-any-post, for auditor roles), excluded admins from the UI (manage_options makes restriction meaningless), migrate upgrades without ever widening access, and refuse to carry permissions through import/export or multisite cloning. The stated reason for the rigor: AI agents now scan plugins for capability mistakes, and they'd rather not be a finding. ## 📰 Newsletter **Permission floors, not permission flags.** Accessibility Checker 1.48 (+ Pro 2.3.0) ships granular role permissions with an architecture worth copying: custom capabilities that are always checked *together with* a core-capability floor, at every entry point — UI, REST, WP-CLI. Grant "dismiss globally" to a subscriber with a role editor and the API still says no, because the floor (`edit_others_posts`) isn't met. One deliberate, labeled exception exists for auditor roles. Upgrades never widen access; permissions never ride along in exports or multisite cloning. Steve Jones and William Patton were candid about the motive: with AI agents hunting capability bugs at scale, "if we weren't being considerate… we would have got flagged by some AI bot." ## ✅ Action Items 1. [RECOMMEND] #action/h2 Adopt the double-gate pattern in Courtney's plugin reviews as a checklist item: does every custom capability check pair with a core-capability floor, and is it enforced server-side (REST permission callbacks, WP-CLI), not just in the UI? This slots directly into the wp-security-reviewer checklist alongside the Security Trinity. 2. [RECOMMEND] #action/h3 Send Equalize Digital floor feedback while the window is open — Courtney's auditor-role experience (roles that review but don't publish) is exactly the persona the any-post overstep serves; confirm or challenge the `edit_posts` minimum. 3. [RECOMMEND] #action/h3 Read the docs page (equalizedigital.com/accessibility-checker/permissions-settings/) before citing specifics — the stream says it predates the changelog post and carries the authoritative capability list. ## 🧪 Hypotheses - [INFERENCE] H1: "Permissions excluded from config export" will become a WordPress-ecosystem norm within a couple of years, driven by the same AI-audit pressure they cite — portable security config is now a findable vulnerability class. - [INFERENCE] H2: The per-user (not per-role) grant demand they deflected to `WP_Role` code will return as a Pro feature request; the framework ("sets the stage for many capabilities to come") suggests they expect it. - [INFERENCE] H3: Their support-ticket-driven design loop (tickets → personas → floors) predicts fewer post-release permission CVEs than spec-first capability systems; audit history of the plugin over the next year is the test. ## 📊 Methodology [EVIDENCE] Design method, as narrated: start from support tickets and audit-remediation client needs → separate view from mutate per feature → map each action to a core-capability floor based on what data it touches (post meta ⇒ edit_posts; others' content ⇒ edit_others_posts) → centralize enforcement in helper functions used by UI, REST, and CLI → deviate from core parity only once, with UI labeling → conservative upgrade migration. [INFERENCE] Verification shown on stream is manual role-switching, not automated tests; nothing in the stream demonstrates test coverage of the gates, so the enforcement claims rest on the demo plus the helper-function design. ## ❓ Questions - [INFERENCE] Are the floor checks covered by automated tests, and do the REST permission callbacks use the same helpers as the admin UI paths (claimed, not shown)? - What exactly does the developer filter for bypassing floors look like, and is it capability-scoped or global? (Named but never shown.) - Does the Issue Explorer UI leak (visible dismiss control without capability) also leak issue *content* to explorer-only roles that the floor model would otherwise restrict? - How does the migration handle sites where the old ignore setting listed roles that no longer exist? ## 🔮 Future Research - [RECOMMEND] Watch the next changelog stream for the promised follow-on capabilities built on this framework, and whether a governance/approval layer for multisite permission cloning materializes. - [INFERENCE] Compare this capability architecture against Block Accessibility Checks' hook model (`ba11yc_*`) — the two plugins now represent distinct extensibility philosophies (capability gates vs. validation filters) in the same WordPress a11y niche. - [RECOMMEND] Track whether wordpress.org plugin review starts asking the double-gate question of new capability-registering plugins. ## 💡 Implications - [INFERENCE] For Courtney's WPOCC/a11y work: the stream is a citable, current example of a WordPress accessibility vendor treating permissions as an accessibility-adjacent trust feature — auditor roles who can triage without publish rights is a governance pattern content teams keep asking for. - [INFERENCE] For plugin authors broadly: the quote "we would have got flagged by some AI bot" marks the moment AI-driven audit pressure visibly changed a shipping plugin's architecture. Defensive design is no longer only about human researchers or Plugin Check. - [STATED→INFERENCE] Their closing pitch — don't promote users to author/admin just to reach one plugin feature — is the least-privilege argument in product form; granular plugin capabilities directly reduce the blast radius of the "just make them an admin" workaround they tell a story about. ## 🧠 Learning Styles Assessment [EVIDENCE] Strong demo-driven structure: every capability claim is immediately shown via role-switching, which suits visual and kinesthetic learners; the Steve-asks/William-answers format gives auditory learners a natural Q&A rhythm. [INFERENCE] Weak for reference use: version numbers, capability names, and floor mappings are spoken once and never shown as a table — the companion docs page has to carry that load. ## 📊 Accessibility Assessment [EVIDENCE] An accessibility-product livestream with **no usable captions**: YouTube produced no VOD caption track (this analysis required local Whisper transcription), which is a jarring gap given the subject matter and the team's standing (Equalize Digital leads WordPress Accessibility Day and the a11y plugin space). Screen-share demos are narrated well ("if I switch to the subscriber role, visit the front end, there is no highlighter") — the narration mostly works audio-only. [RECOMMEND] Upload corrected captions for the VOD; their own audience disproportionately needs them. ## 🌍 DEIB Assessment [EVIDENCE] Collegial two-presenter dynamic with explicit credit ("William, great work on the user permissions") and candor about design mistakes ("the time was five years ago to do this"). Content directly serves disabled users' interests via the product, and the permission design serves organizational inclusion (auditor roles for non-publishing staff). No concerns identified; the register stays respectful throughout, including toward users who made insecure choices ("someone… just decided to make that person a full administrator" is told as a systems failure, not user-blaming). ## ✅ Logical Validity - [EVIDENCE] Strong: floor choices are argued from mechanism (dismissals live in post meta ⇒ post-edit floor), not vibes; the overstep is acknowledged rather than hidden; the export-exclusion decision is argued from a concrete threat scenario (local-site settings imported into production). The upgrade principle (never widen access) is stated and consistently applied through the migration details. - [INFERENCE] Weaker: enforcement completeness is asserted ("every single instance… helper functions") but evidenced only by demo sampling; the UI-leak admission shows they know cosmetic and authoritative layers can drift. The AI-bot line is motive framing, not evidence any scanner found anything. William's aside that the post-meta floor "can absolutely be bypassed very easily" but they "chose not to" is slightly confusing as stated — the surrounding context clarifies he means they chose not to bypass core's requirement themselves, not that the shipped gate is bypassable. - No fallacies identified; the one rhetorical question (why no admin row) is answered on the merits. ## 🛡️ DARVO Analysis Not applicable to this source — a product changelog livestream between colleagues; no accusations, reversals, or victim-offender dynamics. Support-ticket complaints are handled as design input, not deflected. ## 🎯 Conclusion The most quietly instructive WordPress engineering content in this batch: a granular permissions release where the interesting part is the **discipline** — core-capability floors under every custom capability, one labeled exception, no permission portability, upgrades that never widen access, and admin restriction rejected as theater. The double-gate helper pattern belongs in any capability-adding plugin and in any security review checklist. And the throwaway line about AI bots flagging inconsiderate code is a primary-source data point for the thesis running through this whole reading queue: automated audit pressure is now shaping WordPress plugin architecture before release, not after disclosure. <!-- deep-read:sections end --> 📄 **Full text:** [[Full Document Contents/Articles/Who Can Do What Accessibility Checker Permissions.md|Who Can Do What? Accessibility Checker Permissions by Steve Jones & William Patton (Equalize Digital)]] ## Highlights - Yes, so we actually have two gates. We have the custom capability, which is what we have added, which can be granted granularly to individual roles. However, anytime we check a custom capability, we also check whatever the floor is as well. And the floor is what enforces security. It means you can accidentally give a subscriber access to dismiss issues globally where they could effectively read all of the issues or disable all the issues on your website. So that would be a potential leak of data if we allowed the capability singularly to override the core base requirement that we picked when we created the features. Right, so, so from a programmatic standpoint, there's a gate here in the settings to not allow you to choose that. ([View Highlight](https://read.readwise.io/read/01m12x367g8vts9tbd7z23hctm)) - Note: The double-gate pattern: every custom capability check also enforces a core-capability floor (edit_posts / edit_others_posts), at UI, REST, and WP-CLI alike — so role-editor plugins can't hand a subscriber the scan data. Checklist item for any capability-adding plugin review. #atom/literature/h1 - And we've been taking a lot of care with accessibility checker. Throughout its, its life, but even more now with the rise of AI. And, you know, AI bots being able, and agents being able to scan and find security vulnerabilities. We're not. You know, if we weren't being considerate. Yeah. Yeah. We would have got flagged by some AI board that found the vulnerability. We were very. Yeah, explicit and making sure that almost everything we have included here is gated by existing capabilities. Aside from the one that is a slight overstep. But being consider if that actually allows any of the plugins to be updated in any order. Or one plugin never to be updated. And nothing will break everything that was previously the gates would still exist. ([View Highlight](https://read.readwise.io/read/01m12x3qyxy7260vytaaccn8zg)) - Note: Primary-source datum: plugin authors now design permission systems with AI vulnerability scanners as an explicit threat model, pre-release. Pairs with the Wordfence Argus/PRISM reporting from this same reading batch. ("AI board" = Whisper mishearing of "AI bot.") #atom/literature/h2