From 8719e9f01b0f5f30d2b846a9c245f5ebbda5175d Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 7 May 2026 11:33:42 +0200 Subject: [PATCH] Initial catalog migrated from aiolabs/lnbits:main extensions.json --- README.md | 71 ++++++++++++++ extensions.json | 256 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 327 insertions(+) create mode 100644 README.md create mode 100644 extensions.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..be48bbf --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# lnbits-extensions — aiolabs catalog manifest + +A standalone catalog of LNbits extensions we make available across our +deployments. Just `extensions.json` + this README — no server code. + +## Why this is its own repo + +`extensions.json` is a **catalog** (what's available), not a +**dependency** (what's installed). Keeping it out of the lnbits server +fork (`aiolabs/lnbits`) means: + +- The server fork's `main` can be locked-down and slow-moving — only + real server code goes through PR review. +- Catalog updates (new versions, new extensions, deprecating an entry) + happen here on a different cadence and review bar. +- Hosts pull the catalog at runtime via `LNBITS_EXTENSIONS_MANIFESTS`, + so promoting a new extension version is a single commit here, not a + rebuild of every lnbits host. + +## How hosts consume it + +Server-deploy sets `services.lnbits.env.LNBITS_EXTENSIONS_MANIFESTS` to +the raw URL of `extensions.json` on this repo's `main`: + +``` +https://git.atitlan.io/aiolabs/lnbits-extensions/raw/branch/main/extensions.json +``` + +LNbits fetches that URL on boot, builds the in-app catalog from it, and +verifies each downloaded archive against the per-entry `hash` field +(sha256). That `hash` is the integrity guarantee — without a matching +sha256, lnbits refuses to install. So even though the manifest itself +is fetched at runtime, the *artifacts* installed are content-addressed. + +## How to add or update an entry + +Each entry has a stable schema (see `extensions.json`); the required +fields are `id`, `repo`, `name`, `version`, `short_description`, +`archive`, and `hash`. + +To add a new extension or version: + +1. Tag a release in the source extension repo (e.g. + `git.atitlan.io/aiolabs/` `v0.0.5`). +2. Compute the sha256 of the archive: + ```sh + curl -sL https://git.atitlan.io/aiolabs//archive/v0.0.5.zip \ + | sha256sum + ``` +3. Append a new object to `extensions.extensions[]`. Multiple versions + of the same `id` are allowed — lnbits picks the highest the host's + `min_lnbits_version` permits. +4. Commit + push to `main`. Hosts pick up the change on next lnbits + restart. + +## Featured extensions + +`extensions.featured[]` is the array of `id`s shown prominently in the +lnbits "Manage Extensions" UI. Add an `id` here when an extension is +considered the canonical choice for a category (e.g. `libra` for +accounting); remove when superseded. + +## Why we don't include the lnbits upstream manifest + +We could chain ours with +`https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/extensions.json` +in `LNBITS_EXTENSIONS_MANIFESTS`, but a tight curated catalog is a +feature, not a limitation, for our deployments — every available +extension on a host is one we've explicitly vetted. The upstream +catalog is mirrored at `~/dev/refs/repos/lnbits/lnbits-extensions/` for +awareness if we want to lift a specific extension. diff --git a/extensions.json b/extensions.json new file mode 100644 index 0000000..0914208 --- /dev/null +++ b/extensions.json @@ -0,0 +1,256 @@ +{ + "featured": [ + "satmachineclient", + "libra" + ], + "extensions": [ + { + "id": "satmachineadmin", + "repo": "https://git.atitlan.io/aiolabs/satmachineadmin", + "name": "Satoshi Machine Admin", + "min_lnbits_version": "1.4.0", + "version": "0.0.3", + "short_description": "Admin Dashboard for Satoshi Machine", + "icon": "https://git.atitlan.io/aiolabs/satmachineadmin/raw/branch/main/static/image/aio.png", + "archive": "https://git.atitlan.io/aiolabs/satmachineadmin/archive/v0.0.3.zip", + "hash": "0cf520ee62037298320d8c0caa6f15d89858447d826af53472cb369023eda46d" + }, + { + "id": "satmachineadmin", + "repo": "https://git.atitlan.io/aiolabs/satmachineadmin", + "name": "Satoshi Machine Admin", + "version": "0.0.4", + "short_description": "Admin Dashboard for Satoshi Machine", + "icon": "https://git.atitlan.io/aiolabs/satmachineadmin/raw/branch/main/static/image/aio.png", + "archive": "https://git.atitlan.io/aiolabs/satmachineadmin/archive/v0.0.4.zip", + "hash": "f5a6e33e6379984964cd0a4b25225770c4356c5c8a62c8e811b712775a180615" + }, + { + "id": "satmachineadmin", + "repo": "https://git.atitlan.io/aiolabs/satmachineadmin", + "name": "Satoshi Machine Admin", + "version": "0.0.5", + "short_description": "Admin Dashboard for Satoshi Machine", + "icon": "https://git.atitlan.io/aiolabs/satmachineadmin/raw/branch/main/static/image/aio.png", + "archive": "https://git.atitlan.io/aiolabs/satmachineadmin/archive/v0.0.5.zip", + "hash": "a342a349504c25eb99b5d9a45ea88ea6bfcc21d628068dde1b5fda374d01da68" + }, + { + "id": "satmachineclient", + "repo": "https://git.atitlan.io/aiolabs/satmachineclient", + "name": "Satoshi Machine Client", + "version": "0.0.1", + "short_description": "Client Dashboard for Satoshi Machine", + "icon": "https://git.atitlan.io/aiolabs/satmachineclient/raw/branch/main/static/image/aio.png", + "archive": "https://git.atitlan.io/aiolabs/satmachineclient/archive/v0.0.1.zip", + "hash": "05cf74b0f8a39953ad9c063c40a983d6223ebbfa906f5598b6ebe2c58eccfd9a" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "0.0.1", + "short_description": "AIO fork of aiolabs/events", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v0.0.1.zip", + "hash": "410ac9c340551aabe88e0dc7393ed30dc7f4703f1345af5e6b02b0ebc5337d52" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "0.0.2", + "short_description": "AIO fork of aiolabs/events", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v0.0.2.zip", + "hash": "4ac140b97b164f81c482cc19da07a79e961685ae146dc89cba6d12e7d5e80716" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "1.2.1-aio.1", + "short_description": "AIO fork of lnbits/events", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v1.2.1-aio.1.zip", + "hash": "73fa1f8859d6e776768b0669002701707a423781474a57780bed68f70a2b7841" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "1.2.1-aio.2", + "short_description": "NIP-52 Nostr publishing, approval workflow, bidirectional sync", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v1.2.1-aio.2.zip", + "hash": "d20b7c9ee23b5d9ef71528408da94a127a2ef40277b2b30ee7e78e644da55df8" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "1.3.0-aio.1", + "short_description": "Rebased onto upstream v1.3.0; approval workflow, NIP-52 bidirectional Nostr sync, optional user_id tickets", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v1.3.0-aio.1.zip", + "hash": "d7a5f3110eae5402af2d64a890ea6aa8e112c47dd5ce6299224e0231f0706cb0" + }, + { + "id": "events", + "repo": "https://git.atitlan.io/aiolabs/events", + "name": "AIO Events", + "version": "1.3.0-aio.2", + "short_description": "Rebased onto upstream v1.3.0; approval workflow, NIP-52 bidirectional Nostr sync, optional user_id tickets", + "icon": "https://git.atitlan.io/aiolabs/events/raw/branch/main/static/image/events.png", + "archive": "https://git.atitlan.io/aiolabs/events/archive/v1.3.0-aio.2.zip", + "hash": "ccfa652dc0a5ca2474fa138f9ed6af15a33db7f211e3b66cb162bbfe04be2be0" + }, + { + "id": "nostrclient", + "repo": "https://git.atitlan.io/aiolabs/nostrclient", + "name": "AIO nostrclient", + "version": "0.0.1", + "short_description": "AIO fork of aiolabs/nostrclient", + "icon": "https://git.atitlan.io/aiolabs/nostrclient/raw/branch/main/static/images/nostr-bitcoin.png", + "archive": "https://git.atitlan.io/aiolabs/nostrclient/archive/v0.0.1.zip", + "hash": "7f0b1861243a10d16d41d17bc6e64616d61c6b299a86f40dc1a0f9cfc7f9725a" + }, + { + "id": "nostrclient", + "repo": "https://git.atitlan.io/aiolabs/nostrclient", + "name": "AIO nostrclient", + "version": "1.2.0-aio.1", + "short_description": "AIO fork of lnbits/nostrclient", + "icon": "https://git.atitlan.io/aiolabs/nostrclient/raw/branch/main/static/images/nostr-bitcoin.png", + "archive": "https://git.atitlan.io/aiolabs/nostrclient/archive/v1.2.0-aio.1.zip", + "hash": "7f0b1861243a10d16d41d17bc6e64616d61c6b299a86f40dc1a0f9cfc7f9725a" + }, + { + "id": "nostrmarket", + "repo": "https://git.atitlan.io/aiolabs/nostrmarket", + "name": "AIO nostrmarket", + "version": "0.0.1", + "short_description": "AIO fork of aiolabs/nostrmarket", + "icon": "https://git.atitlan.io/aiolabs/nostrmarket/raw/branch/main/static/image/bitcoin-shop.png", + "archive": "https://git.atitlan.io/aiolabs/nostrmarket/archive/v0.0.1.zip", + "hash": "7599485232c600c00896caac15c0fdec07aef26d2cce95c9b2df85b9807bf4f3" + }, + { + "id": "nostrmarket", + "repo": "https://git.atitlan.io/aiolabs/nostrmarket", + "name": "AIO nostrmarket", + "version": "1.1.0-aio.1", + "short_description": "AIO fork of lnbits/nostrmarket", + "icon": "https://git.atitlan.io/aiolabs/nostrmarket/raw/branch/main/static/image/bitcoin-shop.png", + "archive": "https://git.atitlan.io/aiolabs/nostrmarket/archive/v1.1.0-aio.1.zip", + "hash": "edfd11c995a091f71f6439038e6d6ca06cd591abea114e6ac306a6ed5854eb6a" + }, + { + "id": "nostrmarket", + "repo": "https://git.atitlan.io/aiolabs/nostrmarket", + "name": "AIO nostrmarket", + "version": "1.1.0-aio.2", + "short_description": "AIO fork of lnbits/nostrmarket", + "icon": "https://git.atitlan.io/aiolabs/nostrmarket/raw/branch/main/static/image/bitcoin-shop.png", + "archive": "https://git.atitlan.io/aiolabs/nostrmarket/archive/v1.1.0-aio.2.zip", + "hash": "35bd9d20ef43a108ad3b6f0f6a64e3ba56a5b9938ebcf4839f8bc72f3058b23d" + }, + { + "id": "nostrmarket", + "repo": "https://git.atitlan.io/aiolabs/nostrmarket", + "name": "AIO nostrmarket", + "version": "1.1.0-aio.3", + "short_description": "AIO fork of lnbits/nostrmarket", + "icon": "https://git.atitlan.io/aiolabs/nostrmarket/raw/branch/main/static/image/bitcoin-shop.png", + "archive": "https://git.atitlan.io/aiolabs/nostrmarket/archive/v1.1.0-aio.3.zip", + "hash": "f887d25768586920b21c564afd526e218f42bb2ce114b5934c182be1dacb9897" + }, + { + "id": "nostrrelay", + "repo": "https://git.atitlan.io/aiolabs/nostrrelay", + "name": "AIO Nostrrelay", + "version": "0.0.2", + "short_description": "AIO fork of aiolabs/nostrrelay", + "icon": "https://git.atitlan.io/aiolabs/nostrrelay/raw/branch/main/static/image/nostrrelay.png", + "archive": "https://git.atitlan.io/aiolabs/nostrrelay/archive/v0.0.2.zip", + "hash": "6e353358314b740679e55e2ff98c7024a97c6df8bf27d1784e8cee448407bebd" + }, + { + "id": "nostrrelay", + "repo": "https://git.atitlan.io/aiolabs/nostrrelay", + "name": "AIO Nostrrelay", + "version": "1.1.0-aio.1", + "short_description": "AIO fork of lnbits/nostrrelay", + "icon": "https://git.atitlan.io/aiolabs/nostrrelay/raw/branch/main/static/image/nostrrelay.png", + "archive": "https://git.atitlan.io/aiolabs/nostrrelay/archive/v1.1.0-aio.1.zip", + "hash": "0826d16b985be4e9199841223ccd6777aa85120fb6f576dc00c159fef37dd61f" + }, + { + "id": "nostrrelay", + "repo": "https://git.atitlan.io/aiolabs/nostrrelay", + "name": "AIO Nostrrelay", + "version": "1.1.0-aio.2", + "short_description": "AIO fork of lnbits/nostrrelay", + "icon": "https://git.atitlan.io/aiolabs/nostrrelay/raw/branch/main/static/image/nostrrelay.png", + "archive": "https://git.atitlan.io/aiolabs/nostrrelay/archive/v1.1.0-aio.2.zip", + "hash": "2f5435b4849b7d1e8f4af456d88ad336f78132d5db0ec5d60efe304034c1c5cc" + }, + { + "id": "withdraw", + "repo": "https://git.atitlan.io/aiolabs/withdraw", + "name": "AIO Withdraw", + "version": "1.2.2-aio.1", + "short_description": "AIO fork of lnbits/withdraw", + "icon": "https://github.com/lnbits/withdraw/raw/main/static/image/lnurl-withdraw.png", + "archive": "https://git.atitlan.io/aiolabs/withdraw/archive/v1.2.2-aio.1.zip", + "hash": "38c9baf92966b6d8bdb13af12cf324cff4bafd19510cd56650d69e864011492d" + }, + { + "id": "libra", + "repo": "https://git.atitlan.io/aiolabs/libra", + "name": "Libra", + "version": "0.1.0", + "short_description": "Double-entry accounting for collectives", + "icon": "https://git.atitlan.io/aiolabs/libra/raw/branch/main/static/image/libra.png", + "archive": "https://git.atitlan.io/aiolabs/libra/archive/v0.1.0.zip", + "hash": "b3dc77d95047b3ef0733bd2ae761b547bc8d2275cb022ec071a1ab276d9683da" + }, + { + "id": "lnurlp", + "repo": "https://github.com/lnbits/lnurlp", + "name": "Pay Links", + "version": "1.1.3", + "min_lnbits_version": "1.3.0", + "short_description": "Make reusable LNURL pay links", + "icon": "https://github.com/lnbits/lnurlp/raw/main/static/image/lnurl-pay.png", + "details_link": "https://raw.githubusercontent.com/lnbits/lnurlp/main/config.json", + "archive": "https://github.com/lnbits/lnurlp/archive/refs/tags/v1.1.3.zip", + "hash": "913b6880fd824e801f05ae50ed6f57817c9a580f1ed1b02b435823d5754e1b98", + "max_lnbits_version": "1.4.0" + }, + { + "id": "lnurlp", + "repo": "https://github.com/lnbits/lnurlp", + "name": "Pay Links", + "version": "1.3.0", + "min_lnbits_version": "1.4.0", + "short_description": "Make reusable LNURL pay links", + "icon": "https://github.com/lnbits/lnurlp/raw/main/static/image/lnurl-pay.png", + "details_link": "https://raw.githubusercontent.com/lnbits/lnurlp/main/config.json", + "archive": "https://github.com/lnbits/lnurlp/archive/refs/tags/v1.3.0.zip", + "hash": "71701b5756628fec6d7418192158c647e840e1fbf9a65e6fd2372bc73f626562" + }, + { + "id": "lnurlp", + "repo": "https://github.com/lnbits/lnurlp", + "name": "Pay Links", + "version": "1.2.0", + "min_lnbits_version": "1.4.0", + "short_description": "Make reusable LNURL pay links", + "icon": "https://github.com/lnbits/lnurlp/raw/main/static/image/lnurl-pay.png", + "details_link": "https://raw.githubusercontent.com/lnbits/lnurlp/main/config.json", + "archive": "https://github.com/lnbits/lnurlp/archive/refs/tags/v1.2.0.zip", + "hash": "d3872eb5f65b9e962fc201d6784f94f3fd576284582b980805142a2b3f62d8e8" + } + ] +}