mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
docs/architecture/plugins.md records the experimental WASM boundary (BPR-080/ 081, BG-17): disabled by build tag and by config, absent from release.yml and Dockerfile builds, the HP-2 configuration audit (fresh, upgraded, Docker, standalone), the beta release-notes wording, what exists today with its limits and tests, the post-beta plugin candidates that stay in core during beta, and the core concerns that never move. Linked from architecture/README.md, architecture/server.md and docs/README.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rg9QQWVN3E5UUgBD2dydtu
119 lines
16 KiB
Markdown
119 lines
16 KiB
Markdown
# Plugins — the experimental boundary
|
|
|
|
**Kind:** reference + boundary record. **Verified against:** `dev` @
|
|
`2b2d58ab`, 2026-08-29. **Satisfies:** BPR-080, BPR-081, BG-17; feeds HP-2
|
|
question 6.
|
|
|
|
OwnCord has a WASM plugin runtime. It is **experimental, off by default, and
|
|
absent from every shipped artifact**. This document says exactly what exists,
|
|
what it may not be relied on for, what could become a plugin after beta, and
|
|
what never will.
|
|
|
|
## Status: off, twice — and not in the release at all
|
|
|
|
| Layer | Fact | Anchor |
|
|
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
| Build tag | WASM execution compiles only under `-tags wazero`. The default build discovers and lists manifests but **never executes a module** | `Server/plugin/sandbox_default.go:1-5` (`//go:build !wazero`); `sandbox_wazero.go` is the tagged twin |
|
|
| Config | `plugins.enabled` defaults to `false`; the example config block is commented out and says "Disabled by default so existing operators are unaffected" | `Server/config/config.go:352`; `:449-457` |
|
|
| Startup | The registry is only built when the flag is on; otherwise the plugin admin handler gets `nil`, lifecycle calls answer 503 and the list is empty | `Server/main.go:394`; `Server/api/router.go:35-37`, `:184` |
|
|
| Release builds | `release.yml` builds `chatserver.exe` / `chatserver` with a plain `go build` — no `wazero` tag. The Docker image does the same. **No shipped binary can run a plugin.** | `.github/workflows/release.yml:261`, `:268`; `Server/Dockerfile:13` |
|
|
| CI | The `wazero` variants are compiled on every PR so they cannot rot, but their tests run only under the tag | `.github/workflows/ci.yml:52-55`, `:79` |
|
|
|
|
Configuration audit for HP-2 question 6 — is WASM off in every shape a server
|
|
can take?
|
|
|
|
| Shape | Verdict | Why |
|
|
| -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| Fresh install | off | default `false` (`config.go:352`); the generated `config.yaml` has the block commented out (`:452-457`) |
|
|
| Upgraded install | off | an older `config.yaml` has no `plugins` key; koanf loads defaults first, so the absent key reads as `false`. Unknown keys are rejected, not silently ignored (`Server/config/unknown_keys_test.go`) |
|
|
| Docker | off | image built without the tag (`Dockerfile:13`); `OWNCORD_PLUGINS_ENABLED=true` (`config.go:525-526` env provider) would flip the flag but the binary still cannot execute a module |
|
|
| Standalone release binary | off | same — no tag (`release.yml:261`, `:268`) |
|
|
| Source build with the flag | **on** | only `go build -tags wazero` **and** `plugins.enabled: true` together run WASM. This is the developer path and the only one |
|
|
|
|
## No API promise
|
|
|
|
The plugin ABI — the five guest exports (`command_dispatch`, `allocate`,
|
|
`deallocate`, `list_commands`, and the manifest contract) — **may change or be
|
|
removed in any release without a deprecation period**
|
|
(`Server/plugin/examples/hello/README.md:6-10`). There are no supported
|
|
plugins, so there is nothing to keep compatible with. The example under
|
|
`Server/plugin/examples/hello/` is a reference for the ABI as it stands, not a
|
|
promise about the ABI to come; its prebuilt `.wasm` is not tracked
|
|
(`.gitignore:59`) and is not byte-reproducible (TinyGo embeds host paths —
|
|
`hello/README.md:70-74`).
|
|
|
|
**Release-notes wording for beta.** Use this text, unchanged, in the beta
|
|
release notes and anywhere plugins are mentioned to operators:
|
|
|
|
> Plugins are experimental. The WASM runtime is compiled out of release
|
|
> binaries and disabled by default in source builds. The plugin API carries no
|
|
> compatibility promise and may change or be removed without notice. Do not
|
|
> build on it for production use.
|
|
|
|
## What exists today (for the record)
|
|
|
|
Enough to know what "experimental" is guarding. All paths under `Server/plugin/`.
|
|
|
|
| Aspect | State | Anchor |
|
|
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
|
| Runtime | wazero, one module instance per plugin, closed on context done | `sandbox_wazero.go:102-103` |
|
|
| Manifest | JSON `plugin.json`; TOML `plugin.toml` only under the tag and preferred when both exist. Entrypoint must be a relative `.wasm` path. A zip with both is rejected as ambiguous (OC-0318) | `manifest.go:52-61`, `:115`, `:144-148`; `manifest_toml.go:1-5`; `loader.go:39`; test `registry_test.go:696-700` |
|
|
| Capabilities | closed set `commands`, `events`, `storage`, `http`, `ui`; anything else fails load | `manifest.go:97-112`, `:151` |
|
|
| Memory | per-plugin linear-memory cap from manifest or `plugins.max_memory_mb` (default 64 MiB), clamped to the wazero page limit | `sandbox_wazero.go:84-97`, `:102`; `config.go:126`, `:354` |
|
|
| CPU | a wall-clock deadline per invocation — manifest, then `plugins.cpu_budget_ms`, then a hard 100 ms floor. Not fuel-based: a runaway loop is killed by closing the module | `sandbox_wazero.go:300-325`; `config.go:128`, `:355`; TOML resource keys decode (OC-0338) — test `manifest_test.go:149-155` |
|
|
| HTTP | only hosts on `plugins.http_allowlist` (empty by default), 10 s timeout, body cap, at most 5 redirects re-validated, through the guarded dialer that refuses private, loopback, link-local and CGN answers | `host_http.go:39`, `:66`, `:87-102`, `:112`, `:136-155`, `:182-249`; tests `TestGuardedDial_*` |
|
|
| Storage | a per-plugin key/value namespace, scan size clamped; no other table is reachable | `pluginstore.go:12-24`; `host_storage.go:27-66` |
|
|
| Filesystem | none — no WASI preview-1 filesystem is mounted | `sandbox_wazero.go:77-78` |
|
|
| Host imports | **none are wired into the runtime yet.** The `http`, `storage`, `events` and `ui` APIs exist on the Go side of the registry; a guest module today can only receive `command_dispatch` | `sandbox_wazero.go:311-316` |
|
|
| Admin surface | `GET /`, `POST /install` (zip), `POST /{id}/enable`, `POST /{id}/disable`, `DELETE /{id}` under `/api/v1/admin/plugins`, behind the admin IP allowlist **and** an admin session — a LAN peer on the allowed CIDR cannot install without one. Install and uninstall are audited | `Server/api/plugins_handler.go:43-47`; `Server/api/router.go:171-186`; test `TestAuditCoverage_PluginLifecycle` |
|
|
| Client | no plugin UI exists in the desktop client | `grep -rn plugin Client/src` hits only `@tauri-apps/plugin-*` imports |
|
|
|
|
## Could become a plugin after beta (BPR-081)
|
|
|
|
Cohesive features and provider integrations that are natural plugin shapes.
|
|
**During beta they stay where they are**, in core, behind the same tests — the
|
|
audit names them so the boundary is a decision, not drift. Nothing on this list
|
|
moves behind the experimental runtime before a supported plugin API exists.
|
|
|
|
| Candidate | Lives today | Why it is a candidate |
|
|
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
| GIF provider (Klipy) | `Server/api/gif_handler.go` (server proxy, `gif.api_key`) | one vendor behind one endpoint; swapping vendors should not touch core |
|
|
| Link-preview and embed providers (YouTube oEmbed, OG) | `Client/src/components/message-list/media.ts`, `embeds.ts` (moves behind the B7 native broker first — C-09) | provider-shaped; the destination policy stays core |
|
|
| Slash commands and automation | the `plugin_command` protocol family already exists (`protocol/schema.json`) | the one thing the runtime can dispatch today |
|
|
| Webhooks (inbound and outbound) | not implemented | classic integration seam |
|
|
| Optional moderation automation | not implemented; human moderation in `Server/service/moderation.go` | may _suggest_; **human authority and the moderation audit trail stay core** |
|
|
| UI tabs / panels | `ui` capability reserved (`host_ui.go`), no client side | display-only extension point |
|
|
| Import/export bridges (other chat platforms) | not implemented | one-shot data movers with no security surface of their own |
|
|
| Observability exporters | `Server/telemetry/` (OTel, `-tags otel`, exporter `none` by default) | already a build-tagged optional edge |
|
|
|
|
## Core that never moves
|
|
|
|
These stay in the server and client proper, permanently, whatever the plugin
|
|
system becomes. A plugin may _call_ some of them; none may _replace_ or
|
|
_bypass_ them.
|
|
|
|
| Concern | Owner |
|
|
| ----------------------------- | ------------------------------------------------------------------------------------------ |
|
|
| Authentication, sessions, 2FA | `Server/auth/`, `Server/api/auth_handler.go` |
|
|
| Authorization | `Server/permissions/` (one predicate per property — B2-5) |
|
|
| TLS and certificate pinning | `Server/auth/tls.go`; `Client/src-tauri/src/tofu.rs` |
|
|
| Safe outbound fetch | `Server/plugin/host_http.go` guarded dialer; the B7 native broker (C-09) |
|
|
| Quotas and rate limits | `Server/auth/ratelimit*.go`, per-action limits in `Server/service/` |
|
|
| Voice/video E2EE | `Client/src/lib/e2eeCrypto.ts`, `livekitE2EE.ts`, `identity.ts`; `Server/ws/voice_e2ee.go` |
|
|
| Updates and signatures | `Server/updater/`, `Server/api/client_update.go` |
|
|
| Deletion and account removal | `Server/db/account.go` |
|
|
| Backup and recovery | `Server/admin/handlers_backup.go`, `Server/db/admin_queries.go` |
|
|
| Moderation audit | `Server/db/audit*.go`, `Server/db/audittest/`, `TestAuditCoverage_*` |
|
|
|
|
The trust statements these back are in [../trust-model.md](../trust-model.md).
|
|
|
|
## Maintenance
|
|
|
|
**Source of truth:** `Server/plugin/`, `Server/config/config.go` (`PluginsConfig`
|
|
and its defaults), `Server/main.go` (registry construction),
|
|
`.github/workflows/release.yml` and `Server/Dockerfile` (build flags),
|
|
`Server/plugin/examples/hello/README.md` (ABI and toolchain). A change to any of
|
|
those that alters a row above updates this document in the same PR. The
|
|
release-notes paragraph is quoted verbatim by the beta release; change it here
|
|
first.
|