| … | … | @@ -2,7 +2,8 @@ |
| 2 | 2 | |
| 3 | 3 | The **web / SSR surface of Favela** — the native, P2P-local, community-owned social client + appview over |
| 4 | 4 | the self-custody atproto stack ([hyper-proto-peer](../hyper-proto-peer)). One of the Favela surfaces |
| 5 | | (alongside `favela-cli` and `favela-native`). Bluesky is an optional POSSE **lens export**, not the home. |
| 5 | (alongside `favela-surface` and `favela-surface-android`). Bluesky is an optional POSSE **lens |
| 6 | export**, not the home. |
| 6 | 7 | |
| 7 | 8 | A Bare backend that reads a roster of DIDs over pure P2P ([atproto-did-peer](../atproto-did-peer)), folds |
| 8 | 9 | them into a local appview index, and serves the views **server-rendered** (no-JS HTML at real URLs) plus |
| … | … | @@ -33,7 +34,7 @@ Then set the two things that have **no default** (see Config), and start it: |
| 33 | 34 | pgh app start favela-web # http://localhost:4041 |
| 34 | 35 | ``` |
| 35 | 36 | |
| 36 | | ⚠ **Unconfigured means inert, on purpose.** With no `FAVELA_ROSTER` this node indexes nothing, and with |
| 37 | **Unconfigured means inert, on purpose.** With no `FAVELA_ROSTER` this node indexes nothing, and with |
| 37 | 38 | no write transport it refuses every write. Earlier versions defaulted both to the author's own fleet, |
| 38 | 39 | so a fresh install silently indexed someone else's timeline and aimed its writes at their production |
| 39 | 40 | node. Empty is the correct unconfigured state; the errors tell you what to set. |
| … | … | @@ -55,7 +56,7 @@ Overrides go in `~/.config/pgh/apps.json` under `favela-web.env` (there is no CL |
| 55 | 56 | | Var | Default | Meaning | |
| 56 | 57 | |---|---|---| |
| 57 | 58 | | `FAVELA_PORT` | `4041` | HTTP port | |
| 58 | | | `FAVELA_HOST` | `0.0.0.0` (manifest) / `127.0.0.1` (code) | ⚠ a hand-run `bare bin/favela-web.js` binds loopback | |
| 59 | | `FAVELA_HOST` | `0.0.0.0` (manifest) / `127.0.0.1` (code) | a hand-run `bare bin/favela-web.js` binds loopback | |
| 59 | 60 | | `ATPROTO_OVERLAY_ROOT` | hpp's `data/atproto-repo` | shared record byte store; wrong path silently downgrades every DID to firehose backfill | |
| 60 | 61 | | `FAVELA_STORE_ROOT` | `~/.config/favela-web/data` | appview corestore — keep it OUTSIDE the install tree or `pgh app update` wipes it | |
| 61 | 62 | | `FAVELA_EXTERNAL_URL` | — | public URL published in did:web / feed records | |
| … | … | @@ -64,7 +65,7 @@ Overrides go in `~/.config/pgh/apps.json` under `favela-web.env` (there is no CL |
| 64 | 65 | | `FAVELA_REQUIRE_MEMBERSHIP` | off | `1` = writers must also be on a community roster | |
| 65 | 66 | | `FAVELA_LABELER_SEED` | off | enable favela's own atproto labeler (interim) | |
| 66 | 67 | |
| 67 | | `bin/favela-web.js` reads ~38 env vars in total; the rest are tuning (`FAVELA_SPACEDUST`, |
| 68 | `bin/favela-web.js` reads 33 env vars in total; the rest are tuning (`FAVELA_SPACEDUST`, |
| 68 | 69 | `FAVELA_RETENTION_BUDGET`, `FAVELA_AP_BRIDGE`, …) and are safe to ignore. |
| 69 | 70 | |
| 70 | 71 | ## Who may read and write |
| … | … | @@ -74,7 +75,7 @@ delegated — any atproto account can prove that about itself. |
| 74 | 75 | |
| 75 | 76 | - **Reads** are public by default. A community closes its site with `set-meta visibility members`; the |
| 76 | 77 | sign-in path, static assets and `/xrpc/*` stay reachable regardless (`lib/gate-policy.js`). |
| 77 | | ⚠ `/xrpc/*` must stay open: bsky's AppView reads the lens anonymously. |
| 78 | `/xrpc/*` must stay open: bsky's AppView reads the lens anonymously. |
| 78 | 79 | - **Writes** pass one default-deny gate (`lib/check.js`). A new POST route is treated as a repo write |
| 79 | 80 | until it is deliberately classified otherwise. |
| 80 | 81 | - repo writes require **owning the repo** — `viewer.did` must equal the DID this node's hpp signs for; |
| … | … | @@ -89,9 +90,20 @@ reachable instance can front the lens without exposing an authoring path. |
| 89 | 90 | |
| 90 | 91 | ```sh |
| 91 | 92 | bare bin/favela-web.js # FAVELA_PORT=4041 by default |
| 92 | | npm test # node suite; npm run test:ws for the bare-ws firehose test |
| 93 | npm test # the pure modules — render, gates, codecs — under node |
| 94 | npm run test:bare # the appview and everything that opens a corestore, under bare |
| 95 | npm run test:ws # the bare-ws label firehose |
| 93 | 96 | ``` |
| 94 | 97 | |
| 98 | 74 test files across the three scripts. `npm test` runs under node rather than `brittle-bare` |
| 99 | because those files are the runtime-agnostic layer and say so, which is a divergence from the rest of |
| 100 | the fleet; anything touching a store or a swarm is in `test:bare`. |
| 101 | |
| 102 | `npm test` currently fails at `test/strip-vectors.test.mjs`: it reads |
| 103 | `spec/vectors/markdown-strip.json`, and that file moved to `favela-markdown` on 2026-09-02 (see |
| 104 | `spec/MOVED-record-specs.md`) without the test moving with it. favela-markdown's `test/strip.test.js` |
| 105 | covers the same vectors against the real stripper, which this one never did. |
| 106 | |
| 95 | 107 | Deployed as a pgh app (`pgh.type: daemon`, `runtime: bare`); the [atproto-bridge](../atproto-bridge) |
| 96 | 108 | membrane proxies the lens-export XRPC to it (`FAVELA_WEB_UPSTREAM`). |
| 97 | 109 | |