Replace official plugin release assets with single .lapis-plugin bundles #348

Closed
opened 2026-06-06 21:00:59 +00:00 by steve · 0 comments
Owner

Official plugin releases currently publish a signed manifest, audit metadata,
zip, and every installable file as separate Forgejo release assets. This makes
the download surface confusing and leaves the app/registry maintaining two
distribution concepts.

Problem

Forgejo release pages for official plugins expose many assets for a single
plugin version. Users should see one plugin download, matching VS Code and
Obsidian-style distribution expectations.

Goal

Replace the official registry distribution format with one signed
.lapis-plugin bundle per plugin/version and remove the old file-based release
path from the app repo and registry repo.

Scope

  • App repo release tooling stages and publishes exactly one
    <plugin-id>-<version>.lapis-plugin asset per official plugin version.
  • App registry schemas, installer, manager, tests, and settings UI consume
    bundle metadata only.
  • Plugin registry settings show plugin bundle sizes and can install a local
    official .lapis-plugin bundle through the same verification path.
  • /Users/stevejuma/code/lapis-plugin-registry syncs deterministic Forgejo
    releases from .lapis-plugin bundles only, updates schemas/generated metadata,
    removes legacy file-asset sync code, and shows bundle sizes on the registry
    site.
  • Specs in both package-local and rendered spec pages describe the new bundle
    contract.

Non-goals

  • Do not change the runtime install location under
    .obsidian/plugins/<plugin-id>/.
  • Do not add support for unsigned or community .lapis-plugin bundles.
  • Do not keep legacy official registry support for releaseManifest,
    artifact.json, uploaded .zip, file-* release assets, or optional
    post-install file downloads.

Acceptance Criteria

  • registry-assets:publish -- --dry-run stages one .lapis-plugin per selected
    plugin/version and no signed manifest, artifact JSON, zip, or file-* assets.
  • New catalog detail metadata records bundle: { url, sha256, size } for each
    release and does not record releaseManifest or remote per-file URLs.
  • App install/update downloads one bundle, verifies bundle hash/size, verifies
    the embedded signed release manifest, validates each embedded file hash/size
    and safe path, then installs the plugin folder.
  • Tampered bundle, tampered signature, mismatched embedded file hash/size, and
    unsafe embedded file paths fail before final install.
  • Plugin registry settings show formatted plugin size in browse/detail/update
    and installed views, with installed-size fallback when detail metadata is not
    loaded.
  • Manual .lapis-plugin install in Plugin registry settings verifies official
    signature and records official provenance.
  • /Users/stevejuma/code/lapis-plugin-registry syncs bundle-only releases,
    removes legacy release-asset sync code, validates generated metadata, and
    shows bundle sizes plus a single primary bundle download on plugin pages.

Implementation Notes

  • Keep deterministic release tags:
    official-plugin-assets-<plugin-id>-<version>.
  • Define .lapis-plugin as a deterministic zip-compatible archive containing
    release.signed.json and all plugin files at archive root.
  • Keep the current stored/no-compression ZIP writer for v1 and reject compressed,
    encrypted, ZIP64, duplicate, or unsafe entries in the bundle reader.
  • Remove optional/lazy release-file fetch behavior instead of adapting it.
  • Use the app repo backlog issue for the app-repo implementation commit. The
    registry repo has no local AGENTS/backlog requirement, but its changes must be
    committed separately with jj.

Suggested Files or Specs To Inspect

  • scripts/plugin-release.mjs
  • scripts/publish-official-plugin-assets.mjs
  • packages/api/src/lib/plugin-distribution/**
  • packages/workspace/src/lib/components/configuration/plugins-registry-panel.svelte
  • spec/src/30-cross-package-contracts/plugin-registry.md
  • spec/src/80-maintenance/monorepo-scripts.md
  • /Users/stevejuma/code/lapis-plugin-registry/scripts/sync-forgejo-releases.mjs
  • /Users/stevejuma/code/lapis-plugin-registry/schemas/**
  • /Users/stevejuma/code/lapis-plugin-registry/src/pages/plugins/[id].astro

Validation Commands

  • pnpm test:scripts
  • pnpm --filter @lapis-notes/api check:all
  • pnpm --filter @lapis-notes/api test
  • pnpm --filter @lapis-notes/workspace check:all
  • pnpm --filter @lapis-notes/workspace test
  • pnpm check:all
  • pnpm test
  • pnpm test:smoke
  • mdbook build spec
  • In /Users/stevejuma/code/lapis-plugin-registry: pnpm test
  • In /Users/stevejuma/code/lapis-plugin-registry: pnpm check

Follow-up Tasks

Implementation Summary

Replaced official plugin distribution with deterministic .lapis-plugin bundles, updated app install/update/manual install flows, removed legacy per-file release downloads and notebook lazy release hooks, added bundle size display, and synced specs/tests.

Official plugin releases currently publish a signed manifest, audit metadata, zip, and every installable file as separate Forgejo release assets. This makes the download surface confusing and leaves the app/registry maintaining two distribution concepts. ## Problem Forgejo release pages for official plugins expose many assets for a single plugin version. Users should see one plugin download, matching VS Code and Obsidian-style distribution expectations. ## Goal Replace the official registry distribution format with one signed `.lapis-plugin` bundle per plugin/version and remove the old file-based release path from the app repo and registry repo. ## Scope - App repo release tooling stages and publishes exactly one `<plugin-id>-<version>.lapis-plugin` asset per official plugin version. - App registry schemas, installer, manager, tests, and settings UI consume bundle metadata only. - Plugin registry settings show plugin bundle sizes and can install a local official `.lapis-plugin` bundle through the same verification path. - `/Users/stevejuma/code/lapis-plugin-registry` syncs deterministic Forgejo releases from `.lapis-plugin` bundles only, updates schemas/generated metadata, removes legacy file-asset sync code, and shows bundle sizes on the registry site. - Specs in both package-local and rendered spec pages describe the new bundle contract. ## Non-goals - Do not change the runtime install location under `.obsidian/plugins/<plugin-id>/`. - Do not add support for unsigned or community `.lapis-plugin` bundles. - Do not keep legacy official registry support for `releaseManifest`, `artifact.json`, uploaded `.zip`, `file-*` release assets, or optional post-install file downloads. ## Acceptance Criteria - `registry-assets:publish -- --dry-run` stages one `.lapis-plugin` per selected plugin/version and no signed manifest, artifact JSON, zip, or `file-*` assets. - New catalog detail metadata records `bundle: { url, sha256, size }` for each release and does not record `releaseManifest` or remote per-file URLs. - App install/update downloads one bundle, verifies bundle hash/size, verifies the embedded signed release manifest, validates each embedded file hash/size and safe path, then installs the plugin folder. - Tampered bundle, tampered signature, mismatched embedded file hash/size, and unsafe embedded file paths fail before final install. - Plugin registry settings show formatted plugin size in browse/detail/update and installed views, with installed-size fallback when detail metadata is not loaded. - Manual `.lapis-plugin` install in Plugin registry settings verifies official signature and records official provenance. - `/Users/stevejuma/code/lapis-plugin-registry` syncs bundle-only releases, removes legacy release-asset sync code, validates generated metadata, and shows bundle sizes plus a single primary bundle download on plugin pages. ## Implementation Notes - Keep deterministic release tags: `official-plugin-assets-<plugin-id>-<version>`. - Define `.lapis-plugin` as a deterministic zip-compatible archive containing `release.signed.json` and all plugin files at archive root. - Keep the current stored/no-compression ZIP writer for v1 and reject compressed, encrypted, ZIP64, duplicate, or unsafe entries in the bundle reader. - Remove optional/lazy release-file fetch behavior instead of adapting it. - Use the app repo backlog issue for the app-repo implementation commit. The registry repo has no local AGENTS/backlog requirement, but its changes must be committed separately with `jj`. ## Suggested Files or Specs To Inspect - `scripts/plugin-release.mjs` - `scripts/publish-official-plugin-assets.mjs` - `packages/api/src/lib/plugin-distribution/**` - `packages/workspace/src/lib/components/configuration/plugins-registry-panel.svelte` - `spec/src/30-cross-package-contracts/plugin-registry.md` - `spec/src/80-maintenance/monorepo-scripts.md` - `/Users/stevejuma/code/lapis-plugin-registry/scripts/sync-forgejo-releases.mjs` - `/Users/stevejuma/code/lapis-plugin-registry/schemas/**` - `/Users/stevejuma/code/lapis-plugin-registry/src/pages/plugins/[id].astro` ## Validation Commands - `pnpm test:scripts` - `pnpm --filter @lapis-notes/api check:all` - `pnpm --filter @lapis-notes/api test` - `pnpm --filter @lapis-notes/workspace check:all` - `pnpm --filter @lapis-notes/workspace test` - `pnpm check:all` - `pnpm test` - `pnpm test:smoke` - `mdbook build spec` - In `/Users/stevejuma/code/lapis-plugin-registry`: `pnpm test` - In `/Users/stevejuma/code/lapis-plugin-registry`: `pnpm check` ## Related Issues - Follow-up to #347 — [Use deterministic official plugin release tags](../closed/347-use-deterministic-official-plugin-release-tags.md) ## Follow-up Tasks ## Implementation Summary Replaced official plugin distribution with deterministic .lapis-plugin bundles, updated app install/update/manual install flows, removed legacy per-file release downloads and notebook lazy release hooks, added bundle size display, and synced specs/tests. <!-- backlog:task_id=TASK-PLUGINS-REGISTRY-012 source_spec=spec/src/30-cross-package-contracts/plugin-registry.md related_issue=347 -->
steve added this to the Full Registry V1 milestone 2026-06-06 21:00:59 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#348
No description provided.