PublicAddress blocks every private/reserved IPv4 and IPv6 range
(169.254/16, 100.64/10, fc00::/7, fe80::/10, IPv4-mapped/NAT64/6to4 by
their embedded address, ...) independent of the core version; checked
before the request and on every redirect (Requests before_redirect).
Network failures return only "Die Datei konnte nicht geladen werden.";
the detail goes to the error log. DNS-rebinding pinning stays deferred.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
The change summary is the wide primary column (key "title", so it cannot
be hidden) with the tool's human label below and row actions "Revision
ansehen" / "Objekt öffnen". Objects get human names ("Seite: Kontakt",
"Menü: …", "Einstellungen: Titel der Website"; deleted/trashed marked),
primed per page with one query each for posts, menus and users. Times are
relative within 24 h. Non-ok results show a badge and a marked row instead
of an Ergebnis column. Page size and columns via Screen Options; the tool
filter shows labels grouped by integration, dates have visible labels,
and an active filter offers "Filter zurücksetzen" (also in the empty state).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- Header: h1 + logo in a wrapping flex row, hr.wp-header-end before the tabs,
aria-current on the active tab; own CSS/JS enqueued only on this screen.
- Verbindung: ordered "So verbindest du Claude" steps, copy button (core
clipboard.js + wp.a11y.speak), Site-Health-style status list, German details.
- Zugriff: roles as form-table fieldset, connections with site date format,
empty-state row, confirm on revoke; ConnectionUsage records last use via
WP_Application_Passwords::record_application_password_usage (once a day).
- Tools: plain-language legend, counter as inline notice, groups as core
postboxes (postbox.js toggles, per-user closed state, summary when closed),
fixed column widths with new "Art" column, submit above and below.
- Protokoll: site-timezone times with UTC tooltip, result icons, filters with
labels in the list table nav, retention link to Limits.
- Limits: short labels with units and descriptions; snapshot count hidden but
preserved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ChangeLog gains query()/abilities()/clear() (filters: ability, user,
result, date range - all optional and additive). LogTab/LogListTable
render the "Protokoll" admin tab: WP_List_Table with pagination, links
to the post/attachment/nav_menu edit screen by object_type, a revision
link shown only when the user may edit the revision's parent post, and
a nonce+manage_options-gated "Protokoll leeren" with a JS confirmation
and highlighted 'partial' rows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- PostGuard::editable() refuses trashed entries unless the caller opts in
(content-get, revisions-list, post-trash); publish/schedule/unpublish/update/
restore/duplicate/replace now refuse them.
- PostGuard::statusStable(): content-update, revision-restore and
replace-with-copy refuse a future post whose date has passed (any save would
publish it); the content-update rollback and PostCloner row writes re-check.
- PostCloner::ownMeta() treats a failed SELECT as an error; replace() reads the
copy before its first write.
- replace-with-copy needs create_posts (backup clone) and reports backup_id in
write_failed/partial_write.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
All-or-nothing writes: validation (fields, terms, featured image, parent,
template) before any write; failed extras delete the new draft (create) or
restore revision, old columns, fields, terms and featured image (update).
content-update requires rev; Rev::ofPost covers content, title, excerpt,
status and post_modified_gmt. MetaFieldSource::write() now throws on failure.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- Autoloader: add automattic/jetpack-autoloader and load
vendor/autoload_packages.php; require wordpress/mcp-adapter directly (^0.5).
- ServerRegistrar: make the adapter create_server() call and the
OAuthServerRegistrar class_exists() check injectable so createServer()'s
unhook-before-create ordering and the "mcp-oauth absent" branch are unit
tested; add a smoke-test check that booting REST triggers no
_doing_it_wrong().
- mcp-smoke.sh: assert mcp-adapter's default server route 404s, and that the
subscriber role-gate denial actually carries our/the adapter's denial text
(not just any isError/error).
- Guard tests/Integration/mint-token.php and tec-probe.php with
`defined('WP_CLI') && WP_CLI || exit;`; add .gitattributes export-ignore
for tests/docs-superpowers/.superpowers/phpunit/phpcs config.
- Security: add Server/RequestContext, tracking via
rest_request_before_callbacks whether the current REST dispatch is our
OAuth-protected /mcp/mcp-oauth-server route; AbilityRegistrar's
permission_callback now denies (after the role gate) when abilities are
invoked outside that route. Wired in Plugin::boot().
- Minors: single Plugin::VERSION constant used by ServerRegistrar;
IntegrationRegistry caches its computed abilities list; tec-probe.php
checks wp_insert_post's result and cleans up its probe post in a
try/finally.
composer test: 47/47 green. composer lint: clean. Full mcp-smoke.sh run ends
ALL CHECKS PASSED (plus the expected /.well-known WARN).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7