Skip to content

Latest commit

 

History

History
184 lines (149 loc) · 10.4 KB

managed-plugins.md

File metadata and controls

184 lines (149 loc) · 10.4 KB

Managed plugin sources

An organization, or a tool that manages a machine for it, can declare "these plugin sources are recommended here" by writing one JSON file. Buzz reads the file and offers the listed plugins in Settings → Plugins. Nothing in Buzz depends on who writes the file.

The file only recommends. It never installs, enables, updates or removes anything. Each plugin still goes through the Git import and its access review, and the person using Buzz confirms every change. The desktop app reads the file; the browser build has no native plugin storage, so the feature is absent there.

File location

managed-plugins.json lives in the app data folder, next to profiles/ and outside the profile storage Buzz owns. Plugin storage and the policy therefore share one root, which BUZZODZ_HOME moves.

App Identifier
Installed Buzz xyz.block.buzz.desktop
Development builds (just desktop) xyz.block.buzz.desktop.dev
OS App data folder Policy file
macOS ~/Library/Application Support/<identifier>/ <folder>/managed-plugins.json
Windows %APPDATA%\<identifier>\ <folder>\managed-plugins.json
Linux ${XDG_DATA_HOME:-~/.local/share}/<identifier>/ <folder>/managed-plugins.json

Resolution order, the same one buzzodz uses for plugin storage:

  1. BUZZ_MANAGED_PLUGINS, when set and non-empty, is the full path of the file. It must be absolute; a relative value makes the policy unusable. Use it for tests.
  2. Otherwise $BUZZODZ_HOME/managed-plugins.json, when BUZZODZ_HOME is set.
  3. Otherwise managed-plugins.json in the identifier's app data folder above.

One file serves every local profile (BUZZODZ_PROFILE) under that folder. A tool that wants both an installed and a development Buzz to see the policy writes both paths. The pre-1.0 dev.local.buzz.foundation folder is not read.

A missing file means no policy. Buzz never creates, edits or deletes the file; the writer creates the folder if needed. "Sign out and erase local data" clears the whole app data folder, including this file, so a writer should restore it on its next run.

Writing the file safely

  • Write UTF-8 JSON, at most 256 KiB, as a regular file. A symlink to a regular file is followed; a directory, FIFO or other special file is reported as unusable and never opened for reading.
  • Write a temporary file in the same folder and rename it over the target, so Buzz never reads a half-written file. A truncated file would be reported as unusable, then recovered on the next read.
  • The file is advisory configuration, not a secret. Anything that can write the app data folder can write it, so the review dialog, not the label, is what protects the user.

Schema (version 1)

{
  "version": 1,
  "source": "Example Org",
  "plugins": [
    {
      "id": "example.notes",
      "repository": "https://github.com/example-org/buzz-plugins",
      "reference": "v1.4.0",
      "commit": "0123456789abcdef0123456789abcdef01234567",
      "path": "plugins/notes/dist"
    }
  ]
}
Field Required Rules
version yes The number 1. Any other value makes the whole file unusable.
source yes Display name of the managing organization or tool, shown as "Recommended by source" and "Managed by source". 1 to 80 characters after trimming. Only visible characters and ordinary spaces: no control characters, no Unicode format characters (such as bidirectional overrides or zero-width characters) and no non-ASCII space or line separators.
plugins yes Array of at most 64 entries. Later entries beyond 64 are ignored.
plugins[].id yes The plugin manifest ID: lowercase letters, digits, dots and hyphens, starting with a letter. Not a plugin included with Buzz.
plugins[].repository yes An HTTPS or SSH Git URL, or GitHub owner/repository, as the Add dialog accepts. No credentials, query or fragment. Buzz stores the normalized HTTPS or SSH URL.
plugins[].reference yes A branch or tag name: letters, digits, ., _, /, -, at most 200 characters, not starting with -.
plugins[].commit yes The full 40 digit (SHA-1) or 64 digit (SHA-256) hexadecimal object ID the reference must resolve to. Matching ignores case. Abbreviated IDs are rejected.
plugins[].path no Relative folder of the built plugin (containing manifest.json and plugin.js, or a signed release pair) inside the repository. Default .. Written canonically: . alone, or plain segments joined by single / (plugins/notes/dist). No empty, . or .. segments, so no leading or trailing /, // or ./, and no \, : or control characters. A path that is not written this way is rejected, because it could never match the folder Buzz finds.

Unknown fields are errors, at the top level and inside entries, so a typo is reported instead of silently ignored. A new schema revision gets a new version.

What makes a file or entry invalid

  • Unusable file. The file is not readable, not UTF-8 or JSON, larger than 256 KiB, not a regular file, not an object, has a wrong or missing version, an invalid source, a plugins value that is not an array, or an unknown top-level field. Buzz recommends nothing and shows the reason in Settings → Plugins.
  • Ignored entry. Any entry that breaks the rules above is skipped and reported by position (Plugin 2: …) while valid entries still apply. A repeated id keeps the first entry and reports the others. At most 16 problems are reported.

Neither case crashes Buzz or blocks other plugin management.

How Buzz compares entries with installed plugins

The pinned commit identifies exactly what the organization means. When a plugin is installed or updated from a recommendation, Buzz records that commit in the plugin's saved source. Plugins added any other way (the Add dialog, an earlier Buzz) have no recorded commit.

State Meaning Offered
Missing No plugin with this ID is installed. Review and install
Current Installed from the same repository at the pinned commit and path. Marked "Managed by source"
Outdated Installed from the same repository, but at another or an unrecorded commit or path. Review update; marked "Managed by source"
Other Installed from a folder, an unrecorded source, another repository, or included with Buzz. A note only. Buzz does not replace it. Remove it to see the recommendation again.

Repositories match when scheme, user, host, port and path agree after normalization. The host is compared without regard to case, and a trailing / or .git is ignored. The path is case-sensitive, and an SSH form and an HTTPS form of the same repository are different sources: a plugin installed over one is Outdated for an entry written with the other.

What the person using Buzz sees

  • Settings → Plugins shows a Recommended by source group listing Missing and Outdated plugins, and a note for Other ones. Each row shows the repository, reference and path. Installed managed plugins carry Managed by source in their row and details.
  • Review and install and Review update open the existing import review. Buzz reads the repository at the pinned commit, shows the commit, and lists the plugin's host access. For an update it shows what changed from the installed version. Nothing is installed until the person chooses Install plugin or Update. A new plugin can be installed disabled using the same "Enable plugin" switch as any import; an update keeps the plugin's enabled state.
  • Pending recommendations show as a small count beside Plugins in the profile menu and beside Manage plugins in Settings. There is no startup prompt or modal.
  • Details of a managed plugin do not offer the generic update check, which would install the reference's tip instead of the pinned commit. They show the same Review update as the group above when the plugin is Outdated.
  • Disable works as for any plugin.
  • Remove works as for any plugin. The recommendation stays visible, so a removed plugin returns to the Recommended group and can be reinstalled. Buzz never removes a plugin because the file changed or a line was deleted; a plugin no longer listed simply loses its Managed by label.
  • An invalid file or ignored entries are reported in the same section.

Pinned commit behavior

The Git import resolves reference with a shallow clone, then requires HEAD to be exactly commit, and the app checks again that the commit it received is the pinned one. If the reference has moved, the review shows the two commits and refuses to continue; there is no fallback to the new commit. If the policy entry changes while a review is open, the review reads the new entry again, and it closes if the entry is removed. Pin a tag, or rewrite the entry's commit when you intend a branch to advance. Because only the reference's tip is fetched, a commit that is no longer the tip of its reference cannot be installed.

Only an install or update from a recommendation records commit in the plugin's saved source in the profile registry. Older Buzz versions reject that field and offer settings recovery, so downgrading after installing from a recommendation is not supported, as with other registry additions. Plugins added through the Add dialog are unaffected.

Refresh timing

Buzz reads the file when it starts, and again each time it refreshes the plugin catalog, about once per second while it runs. A new or changed file therefore appears without a restart, in Settings and in the pending counts.

Inspecting a policy

buzzodz plugin managed
buzzodz --home /path/to/app-data plugin managed
BUZZ_MANAGED_PLUGINS=/tmp/policy.json buzzodz plugin managed

The command prints the file path, the source name, each valid entry with its state for the selected profile, and the reason for each ignored entry. buzzodz and the desktop share one implementation, so a writer can use it to check a file it wrote.

Writer checklist

  1. Pick the app data folder (or paths) for the identifiers you manage.
  2. Build the JSON exactly as above: version 1, a short source, and for every plugin the ID, repository, reference, full commit and built-plugin path.
  3. Write it atomically.
  4. Run buzzodz plugin managed and confirm no entry is reported as ignored.
  5. Rewrite the file only when the recommendation changes.