mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 14:20:24 +00:00
Merge main into fix/plugin-ignored-grants-shared
This commit is contained in:
+33
-8
@@ -212,7 +212,12 @@ capability model proposed for PhotoCraft plug-ins
|
||||
names shown have control and bidirectional characters escaped (`\u{202E}`) and are cut to 64 characters.
|
||||
Only a person can press its OK: `ui.dialog.confirm`, MCP's `answer_dialog` and injected input (`ui.key`, `ui.click`)
|
||||
are refused and the dialog stays open. Enter confirms it only when OK has the keyboard focus. `ui.dialog.set` can't
|
||||
change what it installs.
|
||||
change what it installs. OK stays disabled until the question has been on screen in the focused window for half a
|
||||
second (VectorCraft's own value, from the delay the security guidance at
|
||||
https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/security/security-considerations-for-browser-ui.md
|
||||
gives for dialog boxes), so a click, Enter or Space, or a press begun before then, installs nothing. The half second
|
||||
starts over for every new question, even one that reads the same, and when the window gets the focus back. Cancel
|
||||
and Escape work at once.
|
||||
- `plugin.install` refuses the module, naming the permissions it needs, unless this module already has a recorded grant
|
||||
(`plugin.inspect`'s `needsApproval` tells it beforehand). A request's `grant` is refused too: `plugin.install` takes
|
||||
it only with the approval the dialog gives. A `vectorcraft-cli mcp` or `run` started with `--allow-plugin-grants`
|
||||
@@ -226,6 +231,13 @@ capability model proposed for PhotoCraft plug-ins
|
||||
`VECTORCRAFT_NO_PREFS` set there is no store, and a `grant` accepted under the flag lasts for that session only.
|
||||
With `--allow-plugin-grants`, pass `hash` set to the `plugin.inspect` entry's `hash` so that the module installed is
|
||||
the one the user saw.
|
||||
- The approval protects against plug-ins and automation clients (MCP, scripts and CLI requests): none of them can
|
||||
approve a module's permissions. VectorCraft's own code records a grant only after that approval and when it loads
|
||||
`grants.json`, and installs a module that lists permissions only under a grant recorded for this very module,
|
||||
also when it loads the Additional Plug-ins Folder. The approval does not protect against native code linked into
|
||||
VectorCraft or against another program running as the same user, which can change the files in the `Plug-ins`
|
||||
folder. `grants.json` is not signed, so such a program can add a grant to it. `--allow-plugin-grants` is a choice
|
||||
the person starting a headless session makes.
|
||||
- **Replacing asks first.** When the file is another module than the plug-in installed with its id, or, with none
|
||||
installed, its id has settings and a cache in the `Plug-ins` folder, Install Plug-in… and File › Open show its id
|
||||
and SHA-256 and ask whether to install it in place of that plug-in, which gives it the settings and cache kept for
|
||||
@@ -240,7 +252,9 @@ capability model proposed for PhotoCraft plug-ins
|
||||
records the new hash. When the new module or its grant can't be written to the `Plug-ins` folder, the folder keeps
|
||||
the old module and its grant, and the old module loads at the next start. If the write that puts the old module back
|
||||
fails as well, the folder holds the new module with the old grant, the grant does not cover that module, and the
|
||||
plug-in is skipped at the next start until it is approved again. A grant whose hash is not 64 lower-case
|
||||
plug-in is skipped at the next start until it is approved again. When the folder held no module for that id, that
|
||||
write removes the new module; when the removal fails, the folder holds the new module and no grant covers it. In
|
||||
both cases a disabled plug-in is turned on, as for any install the folder holds. A grant whose hash is not 64 lower-case
|
||||
hexadecimal digits covers nothing. `plugin.remove` forgets the grant, and so does a successful `plugin.install` of a
|
||||
module that lists no permissions under that id, so the earlier bytes need a new approval. When `plugin.remove` can't
|
||||
remove the grant from `grants.json`, it returns an error, the plug-in stays installed, and a second `plugin.remove`
|
||||
@@ -338,7 +352,11 @@ still returns `1`. `vc_progress`, `vc_cancelled` and `vc_log` need `progress`; t
|
||||
and one the manifest doesn't allow (an `api` below 2, or without the import's permission) refuse the module, and the
|
||||
error names the import and the permission.
|
||||
- A filter's or an exporter's progress is shown as a share: a heavy filter's progress window and the export's progress
|
||||
window draw a bar with a percentage, and Cancel there makes `vc_cancelled` return `1`. A plug-in that checks it can
|
||||
window draw a bar with a percentage, and Cancel there makes `vc_cancelled` return `1`. In the desktop app a light
|
||||
filter that lists `progress` runs in the background as a heavy one does, under its light budget, when it runs at once
|
||||
from Object › Plug-ins or its shortcut, or when OK runs it with Preview off; with Preview on, its dialog keeps the
|
||||
previewed run. A filter that also lists a `commandAllowlist` runs where it is called, since its command calls need
|
||||
the document. A plug-in that checks `vc_cancelled` can
|
||||
stop early, and the host discards what it returns after the Cancel or after its time budget ran out; one that
|
||||
ignores it is still stopped by the instruction and time budgets. With a known total, a report is passed on only when
|
||||
it reaches another tenth of a percent; with an unknown total, each change of `done` is passed on. After 2,000 reports
|
||||
@@ -396,11 +414,18 @@ A live effect runs while the art draws, so keep the entries it uses small.
|
||||
write leaves in the `cache` folder does not count toward the caps, and clearing the cache removes it.
|
||||
- A plug-in reaches only the storage of its own id. Replacing it with another module of the same id
|
||||
(`plugin.install` with `replace: true`, after the user agreed) keeps the storage; `plugin.remove` deletes it, and a run of the plug-in still going gets `-5` from every storage call after that.
|
||||
`plugin.remove` first renames the folder (adding `.removed` to its name). When that fails, `plugin.remove` fails
|
||||
and the plug-in stays installed with its storage as it was. Files that can't be deleted after the rename stay in the
|
||||
`.removed` folder, where no plug-in reaches them. A later `plugin.remove` tries again to delete them when a plug-in
|
||||
with that id is installed or a storage folder for the id exists, and that deletion can fail too. For an id that
|
||||
isn't installed and has only a `.removed` folder, `plugin.remove` does not delete the folder and fails as not found.
|
||||
`plugin.remove` first renames the folder, adding `.removed` to its name (or `.removing` while a `.removed` folder
|
||||
holds settings an earlier removal kept). When that fails, `plugin.remove` fails and the plug-in stays installed with
|
||||
its storage as it was. Before VectorCraft deletes a renamed folder, it writes an empty file beside it with `.delete`
|
||||
added to the folder's name, and removes that file once the folder is gone. When that file can't be written, the
|
||||
folder is not deleted and is treated like any renamed folder without a `.delete` file (see below). Files that can't be deleted stay in the
|
||||
renamed folder with the `.delete` file beside it, where no plug-in reaches them. A later `plugin.remove` tries again
|
||||
to delete them when a plug-in with that id is installed or a storage folder for the id exists, and that deletion can
|
||||
fail too. For an id that isn't installed and has only such a folder, `plugin.remove` does not delete it and fails as
|
||||
not found. When `plugin.remove` can't remove the grant and can't rename the folder back either, its error names the
|
||||
renamed folder. The next load, install or `plugin.remove` of the plug-in renames a renamed folder that has no
|
||||
`.delete` file back while the plug-in has no folder of its own; when it has one, that folder is used and the renamed
|
||||
folder stays until `plugin.remove` deletes both.
|
||||
`plugin.remove` with the id of a plug-in that isn't installed deletes the storage kept for that id, when there is
|
||||
any.
|
||||
`plugin.clearCache` empties the cache and leaves the settings, and `plugin.list` and
|
||||
|
||||
Reference in New Issue
Block a user