OverviewFilesCommitsIssuesDocsReleasesPeers

favela-web commits / f28d63a

0.3.80: wire the resolver handoff and the handset's update section
The two lines #53 left pending. Both are gated on env the servers do not set, so deployed behaviour is unchanged — verified by booting it both ways rather than by reading the code: FAVELA_NAMESERVERS=192.168.50.1,8.8.8.8 FAVELA_SHELL_STATE=<file> [favela] DNS TXT handle verification via 2 nameserver(s) from env /settings renders the running hash, "An update is staged", and both buttons neither set (the production shape) [favela] DNS TXT handle verification via 1 nameserver(s) from resolv.conf /settings contains zero occurrences of "App updates" or "data-ota" FAVELA_NAMESERVERS exists for the one environment that has a resolver and no file naming it: Android, where netd owns resolution, there is no /etc/resolv.conf and net.dns1 has been empty since Android 8. The embedder passes the OS's own servers for the active network, so the objection to third-party resolvers is untouched — this is the same resolver the network already uses, arriving by another route. FAVELA_SHELL_STATE is read PER REQUEST, not at boot: a check performed while the page is open has to be visible on the next render, and the file is four fields. Suite green (exit 0). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f28d63acb3cf97e89d8695b0e133b0509a654e31
by plankatron <fleeky@gmail.com> · 2026-08-25T14:27:03.000Z

Changed files (2) +30 -12

bin/favela-web.js +28 -10
……@@ -36,7 +36,7 @@ import { resolveVerifyKey } from '../lib/plc.js'
3636import net from 'bare-net'
3737import { PlcDirectory } from 'atproto-identity/lib/plc-directory.js'
3838import { createHandleResolver } from '../lib/handles.js'
39import { createTcpResolveTxt, parseResolvConf } from '../lib/dns-txt.js'
39import { createTcpResolveTxt, chooseNameservers } from '../lib/dns-txt.js'
4040import { createFollowerLens } from '../lib/followers.js'
4141import { createApFollowers } from '../lib/ap-followers.js'
4242import { createConstellationClient } from '../lib/constellation.js'
……@@ -295,15 +295,25 @@ async function getRecordStore (did) {
295295// Same resolver as before: whatever /etc/resolv.conf points at, which is what c-ares defaulted to. No
296296// third-party DoH, because handle verification is the last place to hand a stranger the list of every
297297// identity we look up.
298const nameservers = (() => {
299 try {
300 return parseResolvConf(fs.readFileSync('/etc/resolv.conf', 'utf8'))
301 } catch {
302 return []
303 }
304})()
298//
299// FAVELA_NAMESERVERS is for the one environment that HAS a resolver and no file naming it: Android,
300// where netd owns resolution, there is no /etc/resolv.conf, and `net.dns1` has been empty since Android
301// 8 (confirmed on a handset 2026-08-24). The embedder passes the OS's own servers for the active network
302// — favela-android reads them from ConnectivityManager — so this is still the network's resolver, it
303// just arrives by a different route, and the objection above to third-party resolvers is untouched.
304//
305// Without it the phone logs "verification is OFF" and every custom-domain handle renders
306// handle.invalid, which by the measurement above is most of the interesting identities on the network.
307// An unusable env value falls through to the file rather than shadowing it: exporting the variable
308// wrong must not silently turn verification off on a server.
309const { servers: nameservers, source: nsSource } = chooseNameservers({
310 envValue: process.env.FAVELA_NAMESERVERS,
311 resolvConf: (() => { try { return fs.readFileSync('/etc/resolv.conf', 'utf8') } catch { return null } })()
312})
305313if (nameservers.length === 0) {
306 console.log('[favela] no nameserver in /etc/resolv.conf — DNS TXT handle verification is OFF')
314 console.log('[favela] no nameserver (FAVELA_NAMESERVERS unset, none in /etc/resolv.conf) — DNS TXT handle verification is OFF')
315} else {
316 console.log('[favela] DNS TXT handle verification via ' + nameservers.length + ' nameserver(s) from ' + nsSource)
307317}
308318const handleResolver = createHandleResolver({
309319 plc: new PlcDirectory({ fetchImpl: bareFetch }),
……@@ -1372,7 +1382,15 @@ const server = http.createServer(async (req, res) => {
13721382 // (pair / revoke) are progressive enhancement, matching how the avatar section already works.
13731383 let devices = []
13741384 if (viewer) { try { devices = await writer.listDevices() } catch { devices = [] } }
1375 return html(res, 200, settingsPage({ viewer, profile, did, devices, theme: res._theme }))
1385 // App updates, on a handset only. FAVELA_SHELL_STATE is set by favela-android's worklet and by
1386 // nothing else, so a server never renders the section — `appUpdateSection(null)` is ''. Read per
1387 // request rather than at boot: a check performed while this page is open must be visible on the
1388 // next render, and the file is four fields.
1389 let shell = null
1390 if (process.env.FAVELA_SHELL_STATE) {
1391 try { shell = JSON.parse(fs.readFileSync(process.env.FAVELA_SHELL_STATE, 'utf8')) } catch { shell = null }
1392 }
1393 return html(res, 200, settingsPage({ viewer, profile, did, devices, theme: res._theme, shell }))
13761394 }
13771395 if (path === '/login') {
13781396 // Sign-in UI: the client script (/static/login.js) generates the browser's secp256k1 sub-key,
package.json +2 -2
……@@ -1,7 +1,7 @@
11{
22 "name": "favela-web",
3 "version": "0.3.79",
4 "description": "favela-web \u2014 the web/SSR surface of Favela, the native P2P-local, community-owned social client + appview over the self-custody atproto stack (hyper-proto-peer). One of the Favela surfaces (alongside favela-cli and favela-native). bsky is an optional POSSE export, not the home. See DESIGN.md.",
3 "version": "0.3.80",
4 "description": "favela-web — the web/SSR surface of Favela, the native P2P-local, community-owned social client + appview over the self-custody atproto stack (hyper-proto-peer). One of the Favela surfaces (alongside favela-cli and favela-native). bsky is an optional POSSE export, not the home. See DESIGN.md.",
55 "type": "module",
66 "main": "bin/favela-web.js",
77 "bin": {