You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] An install-local uninstall (DELETE /api/v1/marketplace/install-local/:id) leaves the package's permission sets in sys_permission_set: the "no ghost grants" uninstall cleanup never runs on that door #21490
Filing gate: ① a defect with a named position, a finding of class (a). reach: was measured at a public door.
Source: the os-dev report on #21322 (5962851713), out_of_scope_findings[0], measured on main4c8363f4. Filed by the domain:cli seat, session_016GiHYRmLSNWTfbX9gVQkpz. ⛔ Not a claim.
Reader who acts: triage grades and routes. The door is packages/cloud-connection; the cleanup it skips is plugin-security's.
What happens (measured, public door)
A package is installed through install-local. It declares a permission set, and the set is projected into sys_permission_set with managed_by: package.
After a restart, the package's object answers 404, but GET /api/v1/data/sys_permission_set?name=SET_NAME still returns the package-managed row.
The path that existed before #21322's change gives the same orphan row: install, restart, DELETE, restart.
Why (read from source at origin/main)
The install-local route's handleUninstall (packages/cloud-connection/src/marketplace-install-local-plugin.ts:1074) removes the ledger entry. It never runs the protocol's uninstall cleanups.
plugin-security registers exactly that cleanup: protocol.registerUninstallCleanup('security.package-permissions', …) at packages/plugins/plugin-security/src/security-plugin.ts:4293. It removes package-owned sets with their position and user bindings and the package's suggestion rows, "so grants die with the package".
Governing text
ADR-0090 (docs/adr/0090-permission-model-v2-concept-convergence.md:232): "(removing its sets by packageId, ADR-0086 D3) revokes it everywhere at once. No ghost grants."
Dedupe
MCP search_issues, repo-scoped, open and closed together:
Filing gate: ① a defect with a named position, a
findingof class (a).reach:was measured at a public door.Source: the os-dev report on #21322 (
5962851713),out_of_scope_findings[0], measured onmain4c8363f4. Filed by thedomain:cliseat,session_016GiHYRmLSNWTfbX9gVQkpz. ⛔ Not a claim.Reader who acts: triage grades and routes. The door is
packages/cloud-connection; the cleanup it skips isplugin-security's.What happens (measured, public door)
sys_permission_setwithmanaged_by: package.DELETE /api/v1/marketplace/install-local/PACKAGE_IDanswers 200.GET /api/v1/data/sys_permission_set?name=SET_NAMEstill returns the package-managed row.The path that existed before #21322's change gives the same orphan row: install, restart, DELETE, restart.
Why (read from source at
origin/main)handleUninstall(packages/cloud-connection/src/marketplace-install-local-plugin.ts:1074) removes the ledger entry. It never runs the protocol's uninstall cleanups.plugin-securityregisters exactly that cleanup:protocol.registerUninstallCleanup('security.package-permissions', …)atpackages/plugins/plugin-security/src/security-plugin.ts:4293. It removes package-owned sets with their position and user bindings and the package's suggestion rows, "so grants die with the package".Governing text
ADR-0090 (
docs/adr/0090-permission-model-v2-concept-convergence.md:232): "(removing its sets bypackageId, ADR-0086 D3) revokes it everywhere at once. No ghost grants."Dedupe
MCP
search_issues, repo-scoped, open and closed together:sys_metadatarows #7557 and [finding]uninstallPackageunregisters the namespace BEFORE the verb that can refuse — a rejected uninstall leaves the package half-mutated #7970 are closed and concern the protocol uninstall door.DELETE /packages/:idthrough the dispatcher removes the package from the live registry, then refuses withTENANT_SCOPE_REQUIRED: a 400 that leaves the uninstall half applied #20492, Product question: an uninstall with no organizationId deletes EVERY organization's rows for that package (measured 5 of 5, including a foreign org's) #7780, Package disable and uninstall never reach the metadata/data layer: a disabled package's objects still serve rows, and uninstall leaves 7 orphanedsys_metadatarows #7557, [finding]uninstallPackageunregisters the namespace BEFORE the verb that can refuse — a rejected uninstall leaves the package half-mutated #7970, Uninstalling a package orphans its tenants' bare-key ADR-0005 overlays — warned about, but nothing resolves them #7951,protocol.deletePackagefinds zerosys_metadatarows the data plane finds 3 of — uninstall leaves orphaned rows (persistence half of #7557) #7705. All six concernprotocol.deletePackage/uninstallPackage, ⛔ not install-local'shandleUninstall.None covers this door.
Dedupe words: install-local uninstall orphan permission set; registerUninstallCleanup install-local; ghost grants after package DELETE; sys_permission_set survives uninstall.
Generated by Claude Code