Skip to content

feat(ui): derive advanced/composite-child kind flag from the backend#117

Merged
astrojerms merged 1 commit into
mainfrom
feat/adv-kind-backend-signal
Jul 8, 2026
Merged

feat(ui): derive advanced/composite-child kind flag from the backend#117
astrojerms merged 1 commit into
mainfrom
feat/adv-kind-backend-signal

Conversation

@astrojerms

Copy link
Copy Markdown
Owner

Why

The UI's "adv" chip (nav) and create-form banner for composite-child kinds — K3sNode, AgentInstall — were driven by a hardcoded ADVANCED_KINDS map in catalogue.ts. That map only knew the two built-in k3s kinds; an external plugin's composite children got no chip. This moves the "advancedness" of a kind to a backend-derived signal so it's provider-agnostic.

What

  • providers.AdvancedKindDescriber — a new optional provider capability. A provider declares which of its own kinds are composite-children, each with an owner kind + note. Only own-kinds are eligible, which is exactly why a k3s Cluster's proxmox VirtualMachine child stays un-flagged (it's proxmox's first-class kind).
  • k3s provider implements it (K3sNode + AgentInstallCluster), moving the note prose out of the frontend to the provider that owns the knowledge.
  • SchemaInfo gains advanced / owner_kind / advanced_note. SchemaService.ListSchemas stamps them by joining schema.Registry() against the provider registry (now wired into the schema handler). A nil registry flags nothing.
  • External plugins carry it too: pluginproto.KindInfo gains ownerKind / advancedNote (JSON handshake, no codegen), forwarded by the external adapter's AdvancedKinds().
  • UI drops ADVANCED_KINDS; advancedKind() reads the backend fields off the catalogue, and the "Create a <owner> instead →" link derives the owner's apiVersion from the child (same provider) rather than hardcoding k3s.openctl.io/v1.

No behavior change for users: the same two kinds are flagged with the same prose — but now any plugin composite is flagged with zero client-side list.

Tests

  • schema_test.go: ListSchemas stamps the declared child, leaves the owning Cluster and an undeclared VirtualMachine un-flagged, and flags nothing with a nil registry.
  • external_test.go: adapter forwards ownerKind/advancedNote from the handshake through AdvancedKindDescriber.

Local CI

gofmt / go vet / staticcheck / golangci-lint (root + both plugins) / modernize (generated-filtered) / make test / go test -race all green. UI svelte-check clean.

The UI's "adv" chip + create-form banner for composite-child kinds
(K3sNode, AgentInstall) were driven by a hardcoded ADVANCED_KINDS map in
catalogue.ts. That map only knew the two built-in k3s kinds and couldn't
flag an external plugin's composite children.

Make it a backend-derived signal instead:

- providers.AdvancedKindDescriber: an optional provider capability. A
  provider declares which of its OWN kinds are composite-children, each
  with an owner kind + note. Only own-kinds are eligible, so a k3s
  Cluster's proxmox VirtualMachine child is correctly NOT flagged.
- k3s provider implements it (K3sNode + AgentInstall -> Cluster), moving
  the note prose out of the frontend.
- SchemaInfo gains advanced/owner_kind/advanced_note; ListSchemas stamps
  them by joining schema.Registry() against the provider registry
  (wired into the schema handler). Nil registry -> nothing flagged.
- External plugins carry it too: pluginproto.KindInfo gains
  ownerKind/advancedNote, forwarded by the external adapter's
  AdvancedKinds().
- UI drops ADVANCED_KINDS; advancedKind() now reads the backend fields off
  the catalogue, and the "Create a <owner> instead" link derives the
  owner's apiVersion from the child (same provider) instead of hardcoding
  k3s.

Tests: schema handler stamping (flagged child, unflagged owner + VM, nil
registry) and external adapter forwarding.
@astrojerms astrojerms merged commit a042fb0 into main Jul 8, 2026
6 checks passed
astrojerms added a commit that referenced this pull request Jul 8, 2026
…e-child (#118)

The pluginproto ownerKind/advancedNote handshake field (from #117) had no
plugin exercising it. Make plugins/example a reference for it.

- New Notebook kind: a Planner composite that expands (via Plan) into one
  Note child per spec.page, stamping owner labels on each child. Notebook
  itself is file-backed (a .notebook marker lists its children) so its
  Apply/Get/List/Delete are complete CRUD; the plugin creates its child
  Notes directly (there's no controller-side auto-expansion for external
  composites — Plan feeds the UI children graph).
- Note is declared a composite-child of Notebook in the handshake
  (OwnerKind + AdvancedNote), so the UI flags it "advanced" and nudges
  toward creating a Notebook — driven entirely by the backend signal, no
  client-side list. Note stays directly authorable.
- The external e2e test now asserts the advanced declaration survives the
  real subprocess wire round-trip into AdvancedKindDescriber.
- docs/plugin-protocol.md documents OwnerKind/AdvancedNote and points at
  the Notebook->Note composite.
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