spec(leaf): app-leaf-provider-registration — sibling apps register render/data leaves into OpenRegister#2102
Open
rubenvdlinde wants to merge 1 commit into
Open
Conversation
…gister render/data leaves
Contributor
Quality Report — ConductionNL/openregister @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ❌ | ✅ 174/174 | |||
| npm | ✅ | ✅ 555/555 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-07-25 08:13 UTC
Download the full PDF report from the workflow artifacts.
rubenvdlinde
added a commit
that referenced
this pull request
Jul 25, 2026
) Add RegisterLeafProvidersEvent — a typed collect-event mirroring RegisterMcpToolProvidersEvent — so a sibling Nextcloud app can register itself as a leaf on OpenRegister objects (render surface + app-local read/append data) by writing one IEventListener. Render-and-read only by construction: descriptor and provider carry no verb; cross-app commands stay ADR-041 typed events. - LeafDescriptor value object: id, label, icon, requiredApp, group, surfaces, referenceType, requiresPermission, kinds set {render-surface, data-provider, agent-runner (reserved)}. - LeafRegistry: dispatches the event once lazily on first read, validates (non-empty/known kinds, kebab-case id, data-provider-requires-provider), first-wins on duplicate id (ADR-013), swallows a throwing listener so it costs only its own leaf, and lands data-provider leaves on the shared IntegrationRegistry via a lazy loader hook so existing per-object routing reaches them unchanged. - app-local storage strategy documented on the IntegrationProvider contract: data lives in the sibling app's own store; OpenRegister routes list()/optional create() and persists nothing. - Discovery: openregister.integrations.leaves OCS capabilities block (id, label, requiredApp, surfaces, kinds, usability) — discoverable without loading any leaf app's JS. - Tests: 22 PHPUnit tests (event registration, app-local list/create, kinds, first-wins collision, throwing-listener isolation, OCS usability, render-and-read boundary). - Docs: docs/Integrations/leaf-system.md cross-app section + worked notes leaf example, cross-referencing ADR-019/041/013/066. Spec: openspec/changes/app-leaf-provider-registration (PR #2102).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposal only — do NOT merge without human review
This is an OpenSpec change proposal (no PHP/JS implementation). It designs the umbrella "apps hook themselves into OpenRegister" system: a sanctioned server-side seam so any sibling Nextcloud app can register itself as a leaf — contributing render surfaces (tab/widget on an object) and data (notes/records backed by the app's own store) — cleanly and generically.
The gap it fills
IntegrationProvideris already a rich full-CRUD data-provider contract, but every provider registers inside OpenRegister's ownbootBuiltinIntegrationProviders(). There is no event/hook for a sibling app to contribute one, and the storage-strategy enum has no value for data living in another NC app's store. (ADR-041 records this exact limitation.)registerIntegration()+window.OCA.OpenRegister.integrationsstub-queue already exists in@conduction/nextcloud-vue— but it is unspecified in OpenRegister and invisible to the server.The design
RegisterLeafProvidersEvent— a typedIEventDispatchercollect-event mirroringRegisterMcpToolProvidersEvent. Sibling apps write one listener; dispatched once, lazily; a throwing listener costs only its own leaf.LeafDescriptor— server declaration of availability + capability metadata (id, label, icon, requiredApp, surfaces, referenceType, requiresPermission,kinds). No Vue components; render stays on the JS layer under the same id.app-localstorage strategy — data lives in the contributing app's own store; read + optional write served by the provider's own methods in the app's DI context. This is the generalisation of the built-in files/notes/calendar leaves and the concrete shape of "apps offering notes to OpenRegister."Layer decision
Both layers, correlated by a shared
id: server owns discovery + data + capability declaration; JS (already built) owns render-component registration.ADR alignment
Strictly render-and-read only — no command path. Cross-app commands remain ADR-041 typed events. This change deliberately lifts the ADR-041 moratorium ("do not extend the OR registry with cross-app contribution until decided") for the collect/render/read case — so it needs a companion org-wide ADR in
hydra/openspec/architecture/and human ratification before implementation. (Recommended in design.md; not authored here.)Out of scope / cross-refs
Command invocation (ADR-041 events); the hermiq agent-leaf consumer (separate change — only the
agent-runnerkind name is reserved here); the manifesttype: agentaction (nextcloud-vue change); IReferenceProvider convergence (deferred to the companion ADR).Contents
proposal.md,design.md,tasks.mdleaf-provider-registration,leaf-data-providers,leaf-discovery-parityopenspec validate app-leaf-provider-registration --strict→ valid