OverviewFilesCommitsIssuesDocsReleasesPeers

favela-node commits / c9eb451

README: serve.js is what actually runs here, and the file never mentioned it
favela-node is a running pgh daemon on tabertron — serve.js, from the adopted source checkout — and the README described only the library API. Added a Serve section: the launcher, FAVELA_NODE_CONFIG and its shape, the one-shared-swarm replication model (keet's, many topics muxed over each connection), that it replaced a nohup serve-loser-club-room.mjs, and its failure posture — a community that cannot open is logged and skipped, no config or an empty list exits non-zero. Fixed a contradiction the file had carried since 0.1.5. The header said the community DID "IS the feed-generator + labeler service DID"; 0.1.5 and 897c486 changed exactly that — the record's did is the did:web SERVICE and the community DID is the record's owner. Both statements were in the repo, one in the README and one in the commits. Added recoverCommunityRepo (0.1.4) with the three properties that make it safe to run: same DID and signing key from saved secrets so there is no new PLC submit, repo-only so an intact room is never recreated, and a corrupted store abandoned rather than reused. Also added communityIdentity and openCommunityRepo to the import line — index.js exports eight functions and the README showed five. Placement section, for the same reason favela-community got one: this is the atproto / lens-export stack, and favela-peer's autobee rooms are a different object. Test section: three files, not two. Added License, which the file lacked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
c9eb4515a82a14d584b1632b76537fd1b66b92df
by plankatron <fleeky@gmail.com> · 2026-09-20T20:49:32.000Z

Changed files (1) +46 -3

README.md +46 -3
……@@ -6,18 +6,45 @@ The **full-node** that composes a Favela community's two substrates (see
661. the community's **co-owned atproto DID** — an [hyper-proto-peer](../hyper-proto-peer)-style identity
77 whose admins co-sign its repo ([atproto-room](../atproto-room): `StateBaseV3` admins + `Lease` +
88 `Signer` / `LabelRoom` = the **multiswarm-PDS pattern**). Owns/signs the community's
9 `app.bsky.feed.generator` + `app.bsky.labeler.service` records and its `com.atproto.label` labels;
10 IS the feed-generator + labeler service DID.
9 `app.bsky.feed.generator` + `app.bsky.labeler.service` records and its `com.atproto.label` labels.
10 It is the **owner** of those records; the service each one points at is a `did:web`, not this DID
11 (see Notes).
11122. the keyless **CommunityRoom** roster ([favela-community](../favela-community)) — the MEMBER audience
1213 [favela-web](../favela-web) reads. The room's **mods == the DID's admins** (one attested set).
1314
1415A community is thus a **co-owned did:plc**: to bsky it's one account; behind it, N admins co-author with no
1516single point of key custody — exactly how a multi-device hyper-proto-peer presents one DID.
1617
18## Which stack this belongs to
19
20The atproto / lens-export stack, alongside [favela-community](../favela-community) — not the
21markdown-record stack, whose rooms live in `favela-peer` on autobee and share none of this. Live:
22`serve.js` runs as a pgh daemon on tabertron and `loser-club` is in favela-web's shipped defaults.
23
24## Serve
25
26```sh
27favela-node # pgh-installed launcher; entrypoint is serve.js
28```
29
30A `pgh.type: daemon` app with `autostart`, a user systemd unit and a pidfile readiness check.
31It durably serves each configured community's `CommunityRoom` — the keyless roster favela-web reads
32for the feed skeleton — on **one shared swarm**, replicating every served room's autobase over each
33connection. That is the keet model: one swarm, many topics muxed. It replaced a `nohup`
34`serve-loser-club-room.mjs`.
35
36| var | default | |
37|---|---|---|
38| `FAVELA_NODE_CONFIG` | `~/.config/favela-node/config.json` | `{ communities: [{ roomKey, storage, namespace? }] }` |
39
40Adding a community is one config entry. A community that fails to open is logged and skipped rather
41than taking the daemon down with it; no config, or an empty list, exits non-zero.
42
1743## API
1844
1945```js
20import { createCommunity, attestAdmin, bootCommunityAdmin,
46import { communityIdentity, createCommunity, attestAdmin, bootCommunityAdmin,
47 openCommunityRepo, recoverCommunityRepo,
2148 publishFeedGenerator, publishLabelerService } from 'favela-node'
2249
2350// founder: mint the DID + boot its co-owned repo + create the linked keyless CommunityRoom
……@@ -42,10 +69,26 @@ The community DID's genesis op declares `#bsky_fg` / `#atproto_labeler` services
4269 always-on anchor. Never N=2. Other admin devices default to plain writers.
4370- Key derivation is kept **identical to hpp `bootSwarmDevice`** so a community repo is interoperable with
4471 the hpp / membrane stack.
72- `recoverCommunityRepo` boots a fresh co-owned repo under the **same** recovered DID and signing key
73 from saved secrets alone — no new PLC submit — and republishes the `feed.generator` and
74 `labeler.service` records. It is repo-only: an intact room is reopened separately and never
75 recreated, and a corrupted store is abandoned rather than reused.
76- The `feed.generator` record's `did` is the **`did:web` service**, not the community DID. The
77 community DID is the record's owner; the service is what bsky resolves to fetch a skeleton. Getting
78 these the wrong way round is what 0.1.5 fixed.
4579
4680## Test
4781
4882```sh
83npm test
84```
85
86```
4987bare test/publish.test.mjs # record shapes + genesis service entries (single-node)
5088bare test/community.test.mjs # two admins co-sign the community repo over a testnet + keyless roster read
89bare test/recover.test.mjs # recovery from saved secrets: same DID, fresh repo, records republished
5190```
91
92## License
93
94Not yet declared — `package.json` carries no `license` field and there is no LICENSE file.