Files
self 4658b76241
CI / Test (push) Failing after 22s
feat: prefix Kobold plugin slug
Rename Kobold and Trust plugin identity references to tribe-one-prefixed slugs across runtime API, e2e fixtures, and docs.
2026-06-17 22:33:25 +02:00

124 lines
4.5 KiB
Markdown

# Plugin Contract
## Manifest
`manifest.json` is the runtime contract consumed by Tribes:
- `id` is the globally unique plugin identity; `slug` is the local URL/assets namespace.
- `otp_app` should be vendor-prefixed and must match the Mix application name.
- `entry_module` must be a loadable module ending in `.Plugin`.
- `provides` declares capabilities exported by the plugin.
- `requires` declares hard plugin/API contracts beyond the `host_api` foundation.
- `enhances_with` declares optional host capabilities.
- `migrations` should be `true` when `priv/repo/migrations` contains plugin migrations.
- `children` should be `true` when the plugin starts its own supervision tree.
`host_api` is the versioned foundation contract. It provides the supported
Phoenix, Ash, PubSub, data, and cluster-event APIs for plugins. Do not add
separate framework capability requirements for APIs that belong to that
foundation.
Declare `org.tribe-one.caps.ui@1` in `requires` when rendering through `Tribes.Plugin.Layouts.app`,
importing `Tribes.UI.Components`, or using `use Tribes.UI`.
## Entry Modules
The plugin entry module is:
```elixir
defmodule TribeOne.TribesPlugin.Kobold.Plugin do
use Tribes.Plugin.Base, otp_app: :tribe_one_kobold
end
```
Keep plugin implementation code under your own namespace. The default
generator uses `TribeOne.TribesPlugin.*`; third-party plugins should use their own
organization or project namespace.
## Host Dependencies
`tribes_plugin_api` is the release-facing `host_api` foundation. It carries
the supported plugin behaviours, helpers, Phoenix/Ash data surface, and sync
DSL. Do not add the full `:tribes` app as a production dependency.
Host services are exposed through public facade modules in
`Tribes.Plugin.Services`. Use `Tribes.Plugin.Services.Alliance` for local
tribe metadata and tribe users, `Tribes.Plugin.Services.Metrics` for compact
metric rollups, and `Tribes.Plugin.Services.Logs` for operational plugin
logging.
## Localization
Keep Kobold-specific copy in Kobold's own Gettext backend and `priv/gettext`
catalogs. For shared Tribes UI labels that are documented as public plugin API,
import `Tribes.Plugin.Gettext` and call `tgettext/2`:
```elixir
import Tribes.Plugin.Gettext
tgettext("Cancel")
tgettext("Save")
```
Do not call arbitrary internal Tribes Gettext domains from plugin code.
The generated plugin intentionally splits the `:tribes` path dependency by
environment:
- In `:dev`, `:tribes` is compile-only. This lets `mix compile` create the
entry-module beam expected by the host plugin manager without starting a
nested Tribes application.
- In `:test`, `:tribes` is runtime-enabled. Host-backed tests need the real
repository, endpoint pipeline, and plugin contract helpers.
## Ash Resources
For cluster-synced plugin data, add Ash resources under the plugin namespace
and use `extensions: [AshNostrSync]` only for data that should replicate
across the cluster. Prefer one UUID primary key per synced resource. Document
any local-only tables, retention policies, or side effects in plugin docs.
## Kobold Dataset Resources
Kobold's MVP uses fixed plugin-owned Ash resources as its storage and sync
contract. User-defined dataset resources are dynamic schema data, not runtime
Elixir modules, runtime Ash resources, or per-resource database tables.
Initial fixed resources:
- `Dataset`
- `ResourceDefinition`
- `DatasetEvent`
- `RecordProjection`
- `MergeProposal`
The first shipped foundation includes `Dataset`, `ResourceDefinition`,
`DatasetEvent`, and local-only `RecordProjection`. Public dataset/resource/event
mutations use `AshNostrSync.PublishChange`; private mutations deliberately do
not publish and remain local. `RecordProjection` is rebuildable from
`DatasetEvent` history. `MergeProposal` remains planned for the fork/merge
milestone.
Do not generate Ash resources or migrations for each user-defined dataset
resource in the first cut. If a future optimized dataset type needs dedicated
Ash resources, document that as a specialized plugin compatibility layer rather
than the generic Kobold storage model.
## Local Supertest API
Kobold exposes a loopback-only JSON API under `/plugins-api/tribe-one-kobold` for smoke and
supertest scenarios:
- `GET /health`
- `GET /schema`
- `POST /reset`
- `POST /datasets`
- `POST /datasets/:dataset_id/resources`
- `POST /datasets/:dataset_id/records`
- `GET /state?run_id=...`
- `POST /projections/rebuild`
This API is not the durable user-facing federation contract; it exists to prove
plugin install, migrations, public dataset sync, and private local-only dataset
behavior in live scenarios.