Skip to content

feat(marketplace): serve plugin presets from the catalog - #409

Open
ChielTimmermans wants to merge 2 commits into
feat/marketplace-catalog-consumersfrom
feat/marketplace-catalog-presets
Open

feat(marketplace): serve plugin presets from the catalog#409
ChielTimmermans wants to merge 2 commits into
feat/marketplace-catalog-consumersfrom
feat/marketplace-catalog-presets

Conversation

@ChielTimmermans

Copy link
Copy Markdown
Member

Stacked on #408. Adds catalog.v1.ListPresets so the console's plugins page reads the whole storefront from the catalog — presets were the last organization.v1 call left on that page.

schema (migration 037)

appstore.presets and appstore.preset_plugins had no RLS at all. 037 enables it on both and adds four policies: unrestricted for fun_fundament_api (keeps organization-api's own ListPresets working — enabling RLS without it would have silently emptied that endpoint), and reads for fun_marketplace_catalog_api.

Preset rows are public curation, readable unconditionally as categories are. Membership is gated through the plugin's own policy — the same EXISTS categories_plugins_select_catalog uses — so a preset never names a RESTRICTED or soft-deleted listing.

the part worth reviewing

That policy is not sufficient on its own, and TestListPresetsOmitsHiddenPluginsFromMembership caught it: since #395's migration 036 relaxed plugins_select_catalog to let the catalog serve plugin-controller unpublished manifests, a public-but-unpublished plugin is visible at table level — so a draft leaked into preset membership. PresetPluginsList carries the published IS NOT NULL check for the same reason PluginList, PluginGetByID and PublisherList do.

This is the first case of that trade-off biting: every new catalog query has to remember the storefront rule the policy no longer enforces.

console

The plugins page drops its organization.v1 client entirely. The cluster-side views (cluster-plugins, cluster-details, shared-plugins-form) keep theirs — they list plugins to name what is installed, and the catalog only returns PUBLIC listings, so moving them would hide an organization's own private plugins from its clusters.

verification

  • go build ./..., go test ./marketplace-api/..., golangci-lint clean
  • db/fundament.sql regenerated from the model (pgmodeler-cli --pgsql-ver 18.0), diff scoped to the preset policies
  • console typecheck, build and tests at baseline (app.spec.ts and the observable-client.ts lint error both pre-exist on master)

Presets are storefront curation — the plugins page uses them as a browse filter —
but catalog.v1 had no equivalent, so that page still called
organization.v1.PluginService.ListPresets. It now reads everything from the
catalog.

appstore.presets and appstore.preset_plugins had no RLS at all, so migration 037
enables it on both and adds four policies: unrestricted for fun_fundament_api,
which keeps organization-api's own ListPresets working, and reads for
fun_marketplace_catalog_api. Preset rows are public curation and readable
unconditionally, as categories are; membership is gated through the plugin's own
policy, the same EXISTS categories_plugins uses, so a preset never names a
RESTRICTED or soft-deleted listing.

That policy is not sufficient on its own, and a test caught it: since migration
036 relaxed plugins_select_catalog, a public-but-unpublished plugin is visible at
table level, so a draft leaked into preset membership. PresetPluginsList carries
the published check for the same reason PluginList and PublisherList do — the
storefront's own rule now lives in the queries.

The console's plugins page drops its organization.v1 client entirely. The
cluster-side views keep theirs: they list plugins to name what is installed, and
the catalog only returns PUBLIC listings.
The image did not build: defclient moved to catalog.v1 but both Dockerfiles
still copied organization-api/pkg/proto and never copied marketplace-api's, so
the build context was missing the package it now imports. plugin-controller is
not in the CI build matrix, which is why nothing caught it — reproduced and
fixed against a real `docker build` of both images.

`just plugins sandbox-catalog` also failed on any machine that had run the old
sandbox-orgapi recipe: the new NodePort Service asks for the same fixed 30080
the old one still holds, and the relay rename meant `docker rm -f` no longer
matched the container binding the host port. The recipe now removes both first.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant