Skip to content

Add plugin permission manifests, admin review gating, and version changelog - #497

Open
lessevv wants to merge 5 commits into
NativePHP:mainfrom
lessevv:feat/plugin-manifest-and-changelog
Open

Add plugin permission manifests, admin review gating, and version changelog#497
lessevv wants to merge 5 commits into
NativePHP:mainfrom
lessevv:feat/plugin-manifest-and-changelog

Conversation

@lessevv

@lessevv lessevv commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Plugins now declare native permissions/entitlements/capabilities/background modes via nativephp.json (already a documented format, previously never parsed by this app) — captured per version so they can be diffed and displayed.
  • When a new version expands what a plugin can access, it's logged on the plugin's activity timeline; config('plugins.permission_expansion_mode') can additionally gate the version behind admin approval before it becomes current/visible (default: log only).
  • Admins get a Versions tab on the Plugin resource to inspect a version's declared permissions and approve gated ones.
  • The existing review pipeline now flags Android permissions with no matching iOS Info.plist usage-description string — a common cause of App Store rejection that previously went unnoticed.
  • Fixes three separate, never-reconciled code paths that each re-parsed composer.json/nativephp.json slightly differently (ReviewPluginRepository, PluginSyncService, and now SyncPluginReleases) by routing them all through one PluginManifestParser.
  • The public plugin page now shows "What This Plugin Can Access" (sourced from the same manifest data) and a version history/changelog panel — both skip any version still pending admin review.

Security fix included

While building the changelog panel, an automated review flagged that CommonMark::convertToHtml() (shared by README/license/release-notes rendering) is configured with html_input => 'allow' and outputs via {!! !!} with no sanitization — a plugin author could put a <script> tag in a GitHub release body or README and have it execute for every visitor. This affects existing README/license rendering too, not just this PR's new release-notes surface.

Added league/commonmark's built-in DisallowedRawHtmlExtension (no new dependency) to neutralize script/style/iframe/etc. tags. This is a solid default but not a complete fix — it matches by tag name only, so an event-handler attribute on an otherwise-allowed tag (e.g. <img onerror=...>) still passes through. Fully closing that gap needs either a dedicated HTML sanitizer library or switching to html_input => 'escape', both of which are separate decisions that affect how existing plugin READMEs render.

🤖 Generated with Claude Code

lessevv and others added 4 commits September 4, 2026 22:34
Adds PluginManifestParser, which consolidates the composer.json/
nativephp.json parsing previously duplicated (and drifting) across
ReviewPluginRepository, PluginSyncService, and now SyncPluginReleases.
Each new plugin version now stores its declared native permissions,
entitlements, capabilities, and background modes, diffed against the
previous version.

config('plugins.permission_expansion_mode') controls what happens when
a version expands what a plugin can access: "flag" logs it on the
plugin's activity timeline (default), "gate" additionally withholds
the version from being current/visible until an admin approves it.

Also extends the existing review pipeline with a permission-parity
check: an Android permission with no matching iOS Info.plist usage-
description string is now flagged, catching a common cause of App
Store rejection before it reaches a customer's build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CommonMark::convertToHtml() is configured with html_input => 'allow',
so raw HTML written inside a plugin's README, license, or (as of this
branch) release notes passed straight through to {!! !!} output with
no sanitization — a plugin author could put a <script> tag in a GitHub
release body and have it execute on every visitor to the plugin page.

Adds league/commonmark's built-in DisallowedRawHtmlExtension, which
neutralizes script/style/iframe/textarea/etc. tags. This is a solid
default but not a complete fix: it matches by tag name only, so an
event-handler attribute on an otherwise-allowed tag (e.g. <img
onerror=...>) still passes through untouched. Fully closing that
requires either a real HTML sanitizer library or switching to
html_input => 'escape', both of which change how existing README/
license content renders and need a separate decision.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a Versions tab to the Plugin resource so admins can inspect a
version's declared permissions and approve ones held back under gate
mode. Also surfaces the new App Store permission-parity check result
in the existing Review Checks section.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…gin page

Adds a "What This Plugin Can Access" panel, sourced from the latest
visible version's manifest, and a version history/changelog panel
rendering each release's notes. Both skip any version currently held
back for admin review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@simonhamp

Copy link
Copy Markdown
Member

@lessevv there are some conflicts here now with your earlier work

Resolves conflicts from main's independently-added plugin ratings and
reporting features landing alongside this branch's permission manifest
and version-changelog panels on the same plugin show page:

- config/plugins.php: add/add conflict, both sections kept.
- app/Filament/Resources/PluginResource.php: keep both new relation
  managers (Versions from this branch, Ratings from main).
- resources/views/plugin-show.blade.php: git's merge algorithm
  interleaved the two independently-added collapsible sidebar panels
  (this branch's permissions/version-history, main's rate/report)
  because both use a near-identical structure; reconstructed as four
  self-contained sequential blocks instead of a line-level merge.

Verified: this branch's existing test suite (24 tests) and the
relevant tests from main (39 of 42 — 3 pre-existing Imagick-driver
failures unrelated to this merge, confirmed by the extension being
absent from this environment) pass against the merged tree; the
plugin show page renders all four sidebar panels together with no
console errors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@lessevv

lessevv commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Fixed! @simonhamp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants