Repository navigation
Plugin routes: move route-write rights when an Installation's config moves a target - #1775
michielbdejong wants to merge 5 commits into
Conversation
The install review gives the plugin's agent `write` on each resolved write target's parent, and revoke or uninstall takes it back, but editing the config on the Installation page so `inbox` names another resource moved nothing: the old parent kept the plugin's `write` and the new one got none, so route writes there were refused. Saving the config now goes through `saveInstallationConfig`: - `routeWriteConfigChange` compares the saved config with the edit. When a `config:` target resolves to another parent, the page asks again, like an upgrade review: a "Move incoming items" dialog reusing RouteWriteApproval, the new parent marked New, unchecked by default. - Approving moves the rights in commits the signed-in agent signs (`write` given on the new parent, taken back from the old one) and keeps `route-writes` in `grants`. Saving unchecked drops the route grant and every right it came with, as declining an upgrade's new targets does. - A target the edit leaves unresolved refuses the save: Save is disabled with a note naming the key, and the lib throws before committing. - A config change that moves nothing is saved as before. Tests: lib vitest for detecting a move, approving it, declining it, an unresolved target committing nothing, and a change that moves nothing; data-browser vitest for the dialog's New marker, default and both choices. Closes #1758 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pre-commit format check was skipped when this branch was committed with --no-verify. The plugin-manifest-http.ts padding and the PublicEndpoints.test.tsx format are the same fix as on claude/catalog-gated-ui, repeated so this branch passes the hook alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oxlint's padding-line-between-statements and oxfmt flagged these, so the pre-commit lint step failed on this branch before any other change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plugin.spec "install a plugin" saves the config twice while offline. Since the route-write change, the page cleared its edited flag only after saveInstallationConfig resolved. Offline, the first save settles after the next edit, so it cleared that edit's flag too: the outbox entry makes the save state 'queued', not 'dirty', and Save stayed disabled for the newer draft. The plugin has no write targets; the route grant was never involved. The draft bookkeeping moves into useConfigDraft, which counts edits: a save only clears the flag when no edit happened since it started. Its saved config still follows the draft that was written, so the route-write rights diff keeps comparing against the last saved config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fixes) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merge-risk triage (2026-09-28). This is a read-only review of this PR's own diff. The rule it applies: nothing that works today may break for existing users or clients, and new behaviour is added alongside the old. The stack is being rebased onto Verdict: SAFE The config Save button now goes through 🤖 Generated with Claude Code |
|
Closing as part of the plugin-host stack cleanup (Q-101): not needed by atomic-plugins now. See the inventory at #1726 (comment). The branch is kept, and pin candidates are unaffected. Closed by Claude (VPS coordinator) on behalf of Michiel. |
Follow-up to #1754 and #1757. Stacked on #1757 (
claude/route-write-grant-ui).Before this PR, editing an Installation's config so that a write target's
config:key named another resource left the plugin'swriteon the old parent and gave the new parent nothing. Route writes to the new parent were then refused.What changes
routeWriteConfigChange(grants, savedConfig, editedConfig)(lib) lists the route-grant targets whose resolved parent changes, and throwsUnresolvedWriteTargetErrorwhen the edit leaves one unresolved.RouteWriteApprovalwith the new parent marked New, unchecked by default.saveInstallationConfig(lib) saves the config and rewritesroute-writesingrants. When approved, it giveswriteon the new parent and takes it back from the old one, in commits the signed-in agent signs. When saved unchecked, it drops the route grant and every right it came with, as declining an upgrade's new targets does.Screenshots
Taken against a
--features plugin-routesserver at--plugin-routes read-write, with the #1754 inbox fixture published from a draft, installed with the route grant, then itsinboxchanged from an Inbox folder to an Archive folder. After approving, the server reportedwriteon Archive for the plugin agent and no longer on Inbox. Files (local):followup-1758-move-approval-{desktop,mobile}.png,followup-1758-unresolved-{desktop,mobile}.png.The
[i18n-404]after "Pinned to" in the unresolved screenshot was already there: it is the "from …" line in a conditional with nested elements, which this PR doesn't touch.Tests
plugin-route-grant.test.ts: detecting a move (including a config stored as a JSON string), approving it (rights moved, grant kept, commits signed by the installer), declining it (grant and rights dropped), an unresolved target (nothing committed, no agent fetch), and a change that moves nothing.RouteWriteMoveDialog.test.tsx: New marker, unchecked default, save approved and declined.cargo test -p atomic-server --libwith and withoutplugin-routes, clippy both ways, data-browser and lib typecheck.Closes #1758
🤖 Generated with Claude Code