| … | … | @@ -172,6 +172,9 @@ export async function startApBridge (config, { log = defaultLog, bootstrap = nul |
| 172 | 172 | } |
| 173 | 173 | // The router's observation-feed sink (router.js observe/unobserve). Keyed by the REGISTRATION generation, so a |
| 174 | 174 | // released and re-claimed name writes to a new feed, never its predecessor's. |
| 175 | // favela feed key → its registration, for OTHER roles in this process (the gateway's bsky ingest, #82 I2b): what |
| 176 | // reaches a registered identity from another network goes into the same observation feed. Filled at admission. |
| 177 | const feedRegs = new Map() |
| 175 | 178 | if (obsFeeds && registrations) { |
| 176 | 179 | const genOf = async (user) => { const reg = await registrations.get(user.username); return reg ? reg.generation : null } |
| 177 | 180 | ctx.observe = { |
| … | … | @@ -402,7 +405,10 @@ export async function startApBridge (config, { log = defaultLog, bootstrap = nul |
| 402 | 405 | // Their observation feed exists from admission on, so a node can hold it before the first observation. |
| 403 | 406 | if (obsFeeds && registrations) { |
| 404 | 407 | registrations.get(username) |
| 405 | | .then((reg) => (reg ? obsFeeds.open(username, reg.generation) : null)) |
| 408 | .then((reg) => { |
| 409 | if (reg && feedKey) feedRegs.set(String(feedKey).toLowerCase(), { username, generation: reg.generation }) |
| 410 | return reg ? obsFeeds.open(username, reg.generation) : null |
| 411 | }) |
| 406 | 412 | .then((e) => { if (e) log({ msg: 'observation feed', username, key: e.key }) }) |
| 407 | 413 | .catch((err) => log({ msg: 'observation feed open failed', username, error: err.message })) |
| 408 | 414 | } |
| … | … | @@ -725,6 +731,18 @@ export async function startApBridge (config, { log = defaultLog, bootstrap = nul |
| 725 | 731 | port, |
| 726 | 732 | adminPort, |
| 727 | 733 | bridgeKey: open.reg ? open.reg.key : null, |
| 734 | // For other roles in this process (the gateway's bsky ingest, hyper-social #82 I2b): a held favela feed by key |
| 735 | // (read-only), and the observation-feed sink for the identity that feed belongs to — null unless it is |
| 736 | // registered here. Narrow on purpose: no registry, no keys, no write path into anyone's own feed. |
| 737 | heldFeed: (feedKey) => (holder ? holder.get(String(feedKey || '').toLowerCase()) : null), |
| 738 | observationsForFeed: (feedKey) => { |
| 739 | const reg = obsFeeds ? feedRegs.get(String(feedKey || '').toLowerCase()) : null |
| 740 | if (!reg) return null |
| 741 | return { |
| 742 | note: (obs) => obsFeeds.note(reg.username, reg.generation, obs), |
| 743 | remove: (activity) => obsFeeds.remove(reg.username, reg.generation, activity) |
| 744 | } |
| 745 | }, |
| 728 | 746 | ...callbacks, |
| 729 | 747 | metrics, |
| 730 | 748 | handlers: bridgeHandlers({ name: 'ap-bridge', version, ...callbacks }), |