todo: the marketplace's deferred work, ranked
Split out of docs/marketplace.md so the design document stays about how it works. Ranked by what blocks something rather than by size: submissions first (until a stranger's manifest can be read without executing it, the catalogue is ours only and everything below is cosmetic), then plugin upgrades not migrating, then staleness, then scale. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Marketplace — deferred work
|
||||
|
||||
What `marketplace.officer.dev` and the plugin install path do not do yet, as of 2026-08-16. Design and
|
||||
rationale live in `docs/marketplace.md`; this is the list.
|
||||
|
||||
Ranked by what actually blocks something.
|
||||
|
||||
## Blocks other people using it
|
||||
|
||||
- [ ] **Third-party submissions cannot use the sync.** `scripts/marketplace-sync.ts` reads a manifest by
|
||||
IMPORTING it, which is code execution. Fine for our own repositories, not a mechanism a stranger's
|
||||
plugin can go through. Needs either a sandbox or a published `manifest.json` alongside the
|
||||
TypeScript one. Until this exists the catalogue is ours only, and everything below is cosmetic.
|
||||
|
||||
- [ ] **No write API and no submission flow.** Registering a plugin means running the sync by hand against
|
||||
the database. Deliberate while nobody can submit; the first outside contributor makes it the gap.
|
||||
|
||||
## Blocks a plugin evolving
|
||||
|
||||
- [ ] **Plugin installs CREATE, they do not MIGRATE.** `pushPluginSchema` generates the SQL that builds a
|
||||
schema from nothing and applies it, skipping objects that already exist. A new version that adds a
|
||||
column will not get it — the CREATE is skipped as "already exists" and the column is silently
|
||||
absent. Plugin upgrades need real migrations. The old global `db:push` appeared to handle this, at
|
||||
the price of being able to drop half the database, so this is a known trade rather than a
|
||||
regression.
|
||||
|
||||
- [ ] **No versions table.** `plugin_metadata` is one row per plugin — a snapshot, not a history. A store
|
||||
that can offer "install 1.2 instead of 1.3", or show a changelog, needs a different shape.
|
||||
|
||||
## Staleness
|
||||
|
||||
- [ ] **Nothing refreshes the catalogue automatically.** Publishing a plugin update changes nothing until
|
||||
somebody runs `bun --env-file=.env scripts/marketplace-sync.ts`. A Gitea webhook or a cron is the
|
||||
obvious next step.
|
||||
|
||||
- [ ] **The sync reads local clones, not the remotes.** The machine running it must have every plugin
|
||||
checked out, so the catalogue describes that machine's copies. The version that clones each repo
|
||||
into a temp directory is a small change.
|
||||
|
||||
- [ ] **`rawUrl()` assumes Gitea and a `main` branch.** A GitHub-hosted plugin, or one whose default branch
|
||||
is `master`, gets a 404 for its icon. The forge belongs in the registry rather than inferred from a
|
||||
URL shape.
|
||||
|
||||
## Scale
|
||||
|
||||
- [ ] **`fetchCatalogue()` fetches everything, every time.** ~737 bytes per entry, so 100 plugins ≈ 72KB
|
||||
and 1,000 ≈ 720KB. Correct at three; the fix at that size is search rather than pagination, and
|
||||
search is a server-side query that changes the shape anyway — so this is deliberately not built
|
||||
early. The seam is `fetchCatalogue()` itself, which already returns a promise with three fallback
|
||||
paths behind it.
|
||||
|
||||
- [ ] **The platform fetches the whole catalogue to answer "what can I install", then discards everything
|
||||
already on disk.** Fine at three, wasteful at 300. Moving that filter server-side means the platform
|
||||
telling the store what it has, which would be the first data sent TO the marketplace — worth doing
|
||||
deliberately rather than by accident.
|
||||
|
||||
- [ ] **No search, no categories, no install counts.** Three plugins do not need them.
|
||||
|
||||
## Smaller
|
||||
|
||||
- [ ] **A plugin's own icon is invisible before install.** `assets/` is published to
|
||||
`public/plugins/<app>/` on mount, which only happens once it is installed; the catalogue's `iconUrl`
|
||||
works around it by pointing at the repository, and a plugin author has to know to add one.
|
||||
|
||||
- [ ] **`git`, `pm2` and `sudo` are still PATH lookups** in the install path. They work on both machines we
|
||||
have, and `bunx` did not — see `dc420ba5`. Anything new should follow `pushPluginSchema`'s pattern
|
||||
of resolving a path rather than trusting `$PATH`.
|
||||
|
||||
- [ ] **Uninstall leaves the ecosystem file's PM2 entry removed but the process's logs behind.** Harmless,
|
||||
unexamined.
|
||||
@@ -106,6 +106,8 @@ refused outright, because that string reaches `git clone`.
|
||||
|
||||
## Open items
|
||||
|
||||
The full list, ranked, is `docs/marketplace-todo.md`. The ones that shape the design:
|
||||
|
||||
- **`[blocker]` Third-party submissions cannot use this sync.** It reads a manifest by importing it, which
|
||||
is code execution. Fine for our own repositories; not a mechanism a stranger's plugin can go through.
|
||||
Submissions need either a sandbox or a published `manifest.json` alongside the TypeScript one.
|
||||
|
||||
Reference in New Issue
Block a user