mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 16:03:02 +00:00
711f6e9881
Closes the four gaps the security review surfaced: - OS permission model on the prod plugin child (Node --permission with fs-read scoped to the compiled server dir + the plugin's own code dir, no fs-write/child_process/worker/native). A plugin can no longer read trek.db or the .jwt_secret/.encryption_key files, nor shell out — the direct-fs and RCE escapes that bypassed the RPC layer. Opt-out via TREK_PLUGIN_PERMISSIONS=off. - Egress guard extended from fetch to the net.Socket connect choke point, so node:http/https/net/tls obey the declared-egress allowlist too (no declared egress = no outbound). Under the permission model there is no clean escape to an unwrapped runtime. Kernel/network-namespace containment remains the container step. - Trip reads are membership-checked against the acting user the HOST binds from the authenticated invocation, not an asUserId the plugin supplies; a job/onLoad (no user) can't read user-scoped trips. - Optional minisign (Ed25519) author signatures verified offline, TOFU-pinned (migration 158). Unsigned plugins install on sha256 alone; a signed plugin can't silently drop its signature or swap its author key. Server suite green (permission-model activation verified against the Koffi reference plugin on dev1).
133 lines
4.6 KiB
Markdown
133 lines
4.6 KiB
Markdown
# Publishing a Plugin
|
|
|
|
Plugins are distributed from a static registry — the
|
|
[TREK-Plugins](https://github.com/mauriceboe/TREK-Plugins) GitHub repo. There is
|
|
no upload server and no account: you host your plugin in your own GitHub repo and
|
|
list it with a pull request.
|
|
|
|
## 1. Host your plugin
|
|
|
|
Put your plugin in a **public GitHub repo** (convention: `trek-plugin-<id>`). It
|
|
must contain a `trek-plugin.json` at the root, a built `server/index.js`, a
|
|
filled-in `README.md`, and (page/widget) a built `client/`.
|
|
|
|
## 2. Tag a release
|
|
|
|
Tag `vX.Y.Z` where `X.Y.Z` **equals** `version` in your manifest. Either attach a
|
|
`plugin.zip` release asset, or rely on the GitHub source archive at that commit.
|
|
|
|
## 3. Validate locally
|
|
|
|
```bash
|
|
npx trek-plugin validate .
|
|
```
|
|
|
|
This runs the exact checks the registry CI runs — a local pass predicts a CI
|
|
pass.
|
|
|
|
## 4. Fork the registry and open a PR
|
|
|
|
You don't have write access to the registry, so **fork
|
|
[TREK-Plugins](https://github.com/mauriceboe/TREK-Plugins)** to your own account,
|
|
add your entry there, and open a pull request from your fork back to the
|
|
registry's `main` branch.
|
|
|
|
Add one file, `registry/plugins/<id>.json`:
|
|
|
|
```jsonc
|
|
{
|
|
"id": "flight-tracker",
|
|
"name": "Flight Tracker",
|
|
"author": "Your Name",
|
|
"description": "Live flight status widget.",
|
|
"repo": "you/trek-plugin-flight-tracker",
|
|
"type": "widget",
|
|
"versions": [{
|
|
"version": "1.0.0",
|
|
"gitTag": "v1.0.0",
|
|
"commitSha": "<40-hex commit the tag points at>",
|
|
"downloadUrl": "https://github.com/you/trek-plugin-flight-tracker/releases/download/v1.0.0/plugin.zip",
|
|
"sha256": "<sha256 of that artifact>",
|
|
"minTrekVersion": "3.2.0",
|
|
"apiVersion": 1,
|
|
"nativeModules": false
|
|
}]
|
|
}
|
|
```
|
|
|
|
CI validates the entry and the artifact, and the maintainer reviews the source at
|
|
the pinned commit before merging.
|
|
|
|
## What CI enforces
|
|
|
|
**Entry:** valid schema · `id` matches the filename and is a valid slug ·
|
|
reserved namespaces (`trek-`, `official-`) blocked · your `id` is bound to your
|
|
GitHub owner on first registration (nobody can repoint it later) · homoglyph
|
|
check · the release tag exists and points at the pinned commit · manifest parity
|
|
· **the artifact's SHA-256 matches the pin** · **no native binaries** ·
|
|
`egress[]` present when `http:outbound` is declared.
|
|
|
|
**README:** must exist, have the required sections (*What it does / Screenshots /
|
|
Permissions / Setup*), contain **at least one screenshot that actually resolves**,
|
|
have real content (not the unfilled template), and explain every declared
|
|
permission.
|
|
|
|
## Provenance & integrity
|
|
|
|
- `commitSha` pins the exact source the maintainer reviewed (git tags are movable).
|
|
- `sha256` pins the exact artifact bytes TREK will run (release assets are mutable).
|
|
|
|
TREK verifies the downloaded bytes against `sha256` and refuses to install on a
|
|
mismatch. A `reviewedAt` date on your entry means a maintainer looked at that
|
|
exact commit — it is **not** an ongoing guarantee.
|
|
|
|
## Signing your releases (optional, recommended)
|
|
|
|
`sha256` proves the bytes are the ones the *registry* vouches for. An author
|
|
signature additionally proves the bytes were signed by **you** — so a compromised
|
|
registry cannot ship attacker code under your name. TREK verifies the signature
|
|
offline (Ed25519, no external service), and pins your key on first install
|
|
(trust-on-first-use): a later release signed with a different key is refused until
|
|
an admin re-trusts it.
|
|
|
|
**One-time — create a key:**
|
|
|
|
```
|
|
minisign -G # writes minisign.key (keep secret) + minisign.pub
|
|
```
|
|
|
|
Put the public key in your registry entry as `authorPublicKey` (the base64 payload
|
|
line from `minisign.pub`). It is stable across versions.
|
|
|
|
**Each release — sign the artifact:**
|
|
|
|
```
|
|
minisign -Sm plugin.zip # writes plugin.zip.minisig
|
|
```
|
|
|
|
Add the base64 signature line from `plugin.zip.minisig` to that version as
|
|
`signature`, next to its `sha256`. Example entry:
|
|
|
|
```jsonc
|
|
{
|
|
"id": "flight-tracker",
|
|
"authorPublicKey": "RWQ…base64 minisign public key…",
|
|
"versions": [{
|
|
"version": "1.2.0",
|
|
"sha256": "3b2a…",
|
|
"signature": "RUR…base64 .minisig payload…"
|
|
}]
|
|
}
|
|
```
|
|
|
|
Signing is **opt-in**: an entry without `authorPublicKey`/`signature` installs on
|
|
`sha256` alone, exactly as before. But once a plugin has shipped signed, an
|
|
*unsigned* update for it is refused — don't drop the signature between versions.
|
|
|
|
## Updating
|
|
|
|
Add a new version entry (new `version`/`gitTag`/`commitSha`/`sha256`) to your
|
|
plugin file and PR it. Instances see the update on their next registry poll;
|
|
updating is always an explicit admin action, and if a new version requests **more**
|
|
permissions the admin must re-approve.
|