This branch is 14 commits behind tribes/tribes-plugin-template:master
self 80101b7e78 fix: tolerate Parrhesia EOSE hints
Handle the NIP-67 EOSE tuple shape emitted by newer Parrhesia while keeping compatibility with the previous message format.
2026-06-08 21:53:24 +02:00
2026-03-25 12:42:19 +01:00
2026-05-25 05:47:49 +02:00
2026-05-27 19:05:51 +02:00
2026-06-08 21:53:24 +02:00
2026-05-27 19:05:51 +02:00
2026-04-26 22:06:08 +02:00
2026-06-01 19:38:21 +02:00
2026-03-25 12:42:19 +01:00
2026-05-24 16:26:21 +02:00
2026-05-27 19:05:51 +02:00
2026-05-27 19:05:51 +02:00
2026-05-27 19:05:51 +02:00

Aether

Aether is an external Tribes plugin that adds local social posting and chat to a Tribes node.

It provides:

  • org.tribe-one.caps.social@1 — a local tribe feed backed by Nostr kind 1 notes.
  • org.tribe-one.caps.chat@1 — reusable chat surfaces for public rooms, embeddable context chat, NIP-17 direct messages, and future chat backends.

Features

Local social feed

  • /aether renders the local tribe feed.
  • Signed-in users can publish Nostr notes with their Tribes identity.
  • Feed subscriptions use the host/Parrhesia Nostr event stream.

Public and embeddable chat

  • /aether/chat and /aether/chat/:slug render standalone chat rooms.
  • /aether/chat/embed/:slug renders an embeddable chat panel for other plugins such as Sender livestream pages.
  • Public chat uses Aether Ash resources as the synced message projection.

Direct messages

  • Signed-in users can start a DM with another local tribe user from the chat recipient picker.
  • New direct conversations default to the :nostr_nip17 backend.
  • NIP-17 DMs are stored canonically as Parrhesia/Nostr kind 1059 giftwrap events and decrypted into local UI message structs at read time.
  • Sender and recipient copies are published so both sides can read the thread.
  • Legacy NIP-04 kind 4 DMs are supported as a read-only import/decrypt path.

Current signing model: Aether uses the existing Tribes session-unlocked Nostr private key. This produces real NIP-17/NIP-59 and NIP-04 protocol artifacts, but it is still a server-trusting web model, not browser-only/non-custodial E2EE. The protocol operations are isolated behind TribeOne.TribesPlugin.Aether.Chat.Nostr.Nak so a native Elixir implementation or NIP-07/NIP-46 signer can replace it later.

Marmot scaffold

A Marmot backend scaffold and UI route exist for future MLS group chat work, but browser transport, storage, signing, and message rendering are not active yet. The package pin is kept at @internet-privacy/marmot-ts@0.5.1.

Plugin contract and API surface

manifest.json declares:

{
  "id": "org.tribe-one.plugins.aether",
  "slug": "aether",
  "display_name": "Aether",
  "version": "0.2.0",
  "entry_module": "TribeOne.TribesPlugin.Aether.Plugin",
  "host_api": "1",
  "otp_app": "tribe_one_aether",
  "provides": ["org.tribe-one.caps.social@1", "org.tribe-one.caps.chat@1"],
  "requires": ["org.tribe-one.caps.ui@1"],
  "assets": {
    "global_js": ["aether.js"],
    "global_css": ["aether.css"]
  },
  "migrations": true
}

Runtime contributions from TribeOne.TribesPlugin.Aether.Plugin include:

  • nav items for Aether and Chat,
  • LiveView pages for /aether and /aether/chat,
  • the TribeOne.TribesPlugin.Aether.Chat Ash domain,
  • plugin config schema for chat backend defaults and Marmot UI enablement,
  • global JS/CSS assets.

The org.tribe-one.caps.chat@1 provider surface is intentionally small and reusable:

  • TribeOne.TribesPlugin.Aether.Chat.chat_panel_component/0 returns the reusable chat panel component.
  • TribeOne.TribesPlugin.Aether.Chat.recipient_picker_component/0 returns the recipient picker.
  • TribeOne.TribesPlugin.Aether.Chat.ensure_context_channel/5 creates context-owned chat rooms.
  • TribeOne.TribesPlugin.Aether.Chat.ensure_direct_conversation/4 creates a NIP-17 DM projection.
  • TribeOne.TribesPlugin.Aether.Chat.send_message/3, list_conversation_messages/2, and subscribe_conversation/3 dispatch to the selected backend.
  • TribeOne.TribesPlugin.Aether.Chat.embed_path/1, standalone_path/1, and marmot_path/1 expose stable route helpers.

Backend modules implement TribeOne.TribesPlugin.Aether.Chat.Backend:

  • TribeOne.TribesPlugin.Aether.Chat.Backends.PublicSync
  • TribeOne.TribesPlugin.Aether.Chat.Backends.NostrNip17
  • TribeOne.TribesPlugin.Aether.Chat.Backends.NostrNip04ReadOnly
  • TribeOne.TribesPlugin.Aether.Chat.Backends.Marmot

These are plugin-local today. If other plugins need the same primitives, the likely host/plugin API candidates are a stable Nostr event publish/query service and a stable session/external signer interface.

Development

Use the plugin-aware commands from the repo devenv shell:

devenv shell -- plugin validate
devenv shell -- plugin test
devenv shell -- plugin precommit

Outside the devenv shell, use the local wrapper:

scripts/plugin validate
scripts/plugin test
scripts/plugin precommit

Plain mix test and mix precommit are not the normal entrypoints; this plugin suite is host-backed and expects the Tribes test environment.

For local development alongside a Tribes checkout, symlink this repo into the host plugin directory:

cd /path/to/tribes
ln -s /path/to/tribes-plugin-aether plugins/aether
iex --sname dev -S mix phx.server

Then edit this repo normally. The host watches symlinked external plugins and reloads changed Elixir, HEEx, assets, manifests, and migrations.

Assets and hooks

Plugin browser assets are declared in manifest.json and served by the host. Aether currently uses:

  • assets/js/aether.js for LiveView hooks such as chat auto-scroll,
  • assets/css/aether.css for plugin-scoped styles.

External plugin hooks are registered through window.TribesPluginHooks; Phoenix colocated hooks from external plugin OTP apps are not auto-imported by the host.

Runtime requirements

  • A Tribes host checkout/runtime with org.tribe-one.caps.ui@1.
  • Parrhesia available through the host for Nostr event storage and streaming.
  • nak available in the runtime path for the current NIP-17/NIP-59/NIP-04 protocol implementation.
  • Node dependencies under assets/ for browser asset builds.

Release packaging

Guix packaging assembles the plugin artifact from the compiled BEAM output, priv/, browser assets, and manifest.json. Enable the plugin from the guix-tribes channel-side node configuration.

S
Description
Tribes Aether Plugin (Twitter/DMs/Chat)
Readme 696 KiB
Languages
Elixir 91.6%
Shell 3.6%
Nix 2.2%
Scheme 1.9%
JavaScript 0.5%
Other 0.2%