# Trust Tribe-to-tribe alliances and trust ## Getting Started 1. Edit `manifest.json` - set description, capabilities, requirements 2. Implement your plugin in `lib/trust/plugin.ex` 3. Run validation, smoke checks, and tests: ```bash mix deps.get mix tribes.plugin.validate scripts/plugin smoke scripts/plugin test ``` If you are using the shared `tribes` devenv, run through the local helper instead: ```bash devenv shell -- plugin validate devenv shell -- plugin smoke devenv shell -- plugin test devenv shell -- plugin precommit ``` Generate AshPostgres resource migrations through the same wrapper so they target the host `Tribes.Repo` and the plugin migration directory: ```bash plugin ash.codegen update_example_resources ``` Manual Ecto migrations are the rare exception for schema work not derived from Ash resources: ```bash plugin ecto.migration add_example_table ``` ## Development For local development alongside a Tribes checkout: ```bash # Symlink into the host plugins directory once cd ../tribes ln -s ../tribes-plugin-trust plugins/trust # Start Tribes dev server iex --sname dev -S mix phx.server ``` Then edit the plugin in its own repo. In development, the host watches symlinked external plugins and automatically: - runs `mix compile` for Elixir/HEEx or manifest changes - runs `npm run build --prefix assets` when `assets/package.json` is present and plugin asset files change - reloads the plugin in the running Tribes VM - triggers a Phoenix browser reload after the rebuild finishes Browser hooks for external plugins should live in plugin JS assets declared in `manifest.json` `assets.global_js` and register themselves through `window.TribesPluginHooks`. Phoenix colocated hooks are not auto-imported from external plugin OTP apps by the host `app.js` bundle. That means the normal edit/compile loop is: ```bash cd /path/to/tribes-plugin-trust mix deps.get # in another terminal cd /path/to/tribes iex --sname dev -S mix phx.server ``` Inside the plugin repo's devenv shell, the `plugin` helper forwards to the host devenv automatically: ```bash plugin validate plugin smoke plugin test plugin precommit ``` If your plugin does not need a custom frontend pipeline, you can skip `assets/package.json` and write browser-ready files directly under `assets/js` and `assets/css`; the host dev watcher will copy them into `priv/static` for you in development. The default generator uses TypeScript under `assets/ts`. ## LiveView Hooks External plugins do not participate in the host asset bundle, so the host cannot statically import arbitrary plugin `phoenix-colocated/` modules. Register browser hooks from your plugin JS instead: ```typescript window.TribesPluginHooks = window.TribesPluginHooks ?? {}; window.TribesPluginHooks.TribeOneTribesPluginTrustExample = { mounted() { console.info("trust hook mounted"); } }; ``` Keep the compiled JS file listed in `manifest.json` `assets.global_js` so it loads before the host LiveSocket connects. ## Project Structure ``` trust/ |-- manifest.json # Plugin metadata (Nix build + runtime) |-- mix.exs # Dependencies |-- config/ # Host-backed test config |-- lib/ | |-- trust/ | | |-- plugin.ex # Tribes.Plugin entry point | | `-- application.ex # OTP supervision tree (optional) | `-- trust_web/ | `-- live/ # LiveView pages |-- assets/ # TS/CSS (one bundle per plugin) | |-- ts/ # TypeScript browser entry points | |-- package.json # Optional build script used by dev + Guix packaging | |-- tsconfig.json # TypeScript compiler settings | `-- package-lock.json # Optional, recommended for reproducible builds |-- priv/ | |-- static/ # Built assets for release | `-- repo/migrations/ # Ecto migrations |-- scripts/ | `-- plugin # Shared devenv/non-devenv test wrapper `-- test/ ``` ## Manifest `manifest.json` declares your plugin's identity and capabilities: ```json { "id": "org.tribe-one.plugins.trust", "slug": "tribe-one-trust", "display_name": "Trust", "entry_module": "TribeOne.TribesPlugin.Trust.Plugin", "host_api": "1", "otp_app": "tribe_one_trust", "provides": ["org.tribe-one.caps.some_capability@1"], "requires": ["org.tribe-one.caps.ui@1"], "enhances_with": ["org.tribe-one.caps.inference@1"] } ``` - **entry_module** - must be a valid module ending in `.Plugin` - **otp_app** - required OTP application name; vendor-prefix it to avoid collisions - **provides** - capabilities this plugin makes available - **requires** - hard plugin/API contracts (build fails without them) - **enhances_with** - optional dependencies (plugin degrades gracefully) The default generator includes `org.tribe-one.caps.ui@1` because the generated LiveView renders inside the host chrome through `Tribes.Plugin.Layouts.app`. Keep `org.tribe-one.caps.ui@1` when a plugin uses host chrome, imports `Tribes.UI.Components`, or uses `use Tribes.UI`. ## Plugin Data If your plugin adds Ash resources that should replicate cluster-wide, use `extensions: [AshNostrSync]` on those resources and assign a sync lane per resource. The host default lane is `bulk`; latency-sensitive topology or orchestration resources should opt into `control`. Keep resource-specific side effects explicit in actions. ## Testing The generated plugin starts with two host-backed test layers: - **Contract tests** (`test/trust/plugin_contract_test.exs`) - manifest and runtime spec stay aligned - **Page tests** (`test/trust/home_page_test.exs`) - the plugin renders through the real host page pipeline Run them with: ```bash mix tribes.plugin.validate scripts/plugin smoke scripts/plugin test ``` Use `plugin test` / `plugin precommit` for host-backed tests. The helper invokes Mix with the host database/services and host plugin-manager paths, including built-in providers such as `tribe-one-tribes-ui`. Raw `mix test` in a plugin checkout is guarded and prints this guidance; `mix raw_test` / `mix raw_precommit` are available only for unusual manual debugging when you have set the same host environment yourself. ## Building for Release ```bash MIX_ENV=prod mix compile devenv shell -- npm run build --prefix assets mkdir -p dist/trust cp -r _build/prod/lib/tribe_one_trust/ebin dist/trust/ cp -r priv dist/trust/ cp manifest.json dist/trust/ ``` ## Licence TODO: Choose a licence.