OverviewFilesCommitsIssuesDocsReleasesPeers

favela-markdown / test / reach.test.js

95 lines · javascript ref:
// maxReach — library.md §6.1, record-vocabulary.md §5.2, interaction.md §5.2
//
// ⛔ THIS IS THE ONE PLACE A DEFECT IS A PRIVACY BUG RATHER THAN A RENDERING BUG (library §6.1),
// so every case below asserts the DENY direction as well as the allow direction, and the default
// for anything unrecognised is the empty-est answer the model has: {favela}.
//
// Signature changed 2026-09-05. §6.1 signs it `maxReach(visibility)`, from when visibility was a
// frontmatter field. Visibility is now a PLACE — the room you wrote in (SOCIAL-MODEL §4) — so the
// inputs are the room's kind and the verb. The codec has no storage and cannot inspect a room, so
// the caller passes the kind; that is honest about the library boundary rather than pretending.

import test from 'brittle'
import { maxReach, NETWORKS } from '../lib/reach.js'

const set = (r) => [...r].sort().join(',')

test('a PUBLIC room reaches everywhere a verb allows', (t) => {
  t.is(set(maxReach({ roomType: 'public', verb: 'post' })), 'bsky,favela,fediverse')
  t.is(set(maxReach({ roomType: 'public', verb: 'like' })), 'bsky,favela,fediverse')
})

test('⛔ a FOLLOWERS room reaches the fediverse but NEVER bsky (§5.2)', (t) => {
  // AP has addressing — a followers room maps onto the followers collection. atproto has NONE, so
  // a projection it cannot restrict is a leak, and the only safe answer is to withhold it.
  t.is(set(maxReach({ roomType: 'followers', verb: 'post' })), 'favela,fediverse')
})

test('⛔ a MEMBERS room and a DM reach nothing but favela', (t) => {
  // AS2 can address actors, but an arbitrary room's membership is not expressible as an audience
  // the receiving server will honour, so it fails CLOSED rather than approximating.
  t.is(set(maxReach({ roomType: 'members', verb: 'post' })), 'favela')
  t.is(set(maxReach({ roomType: 'dm', verb: 'post' })), 'favela')
})

test('⛔ an UNKNOWN room type reaches only favela — deny by default', (t) => {
  for (const roomType of ['', null, undefined, 'PUBLIC', 'public ', 'anything', 42, {}]) {
    t.is(set(maxReach({ roomType, verb: 'post' })), 'favela',
      'unrecognised room type ' + JSON.stringify(roomType) + ' fails closed')
  }
})

test('⛔ an UNKNOWN verb reaches only favela (interaction §5.2)', (t) => {
  // "An unknown verb's maximum reach is {favela}." That IS the extension mechanism: a native-only
  // verb cannot fork a signed projection because it never reaches a shared derivation.
  for (const verb of ['net.example.rsvp', 'bookmark', 'pin', '', null, undefined, 99]) {
    t.is(set(maxReach({ roomType: 'public', verb })), 'favela',
      'unknown verb ' + JSON.stringify(verb) + ' is native-only')
  }
})

test('internal verbs never leave, even from a public room', (t) => {
  // alias and variant-of are how a node knows two names/byte-sets denote one thing. They have no
  // projection anywhere, by design (interaction §5.5, record-vocabulary §3.5).
  t.is(set(maxReach({ roomType: 'public', verb: 'alias' })), 'favela')
  t.is(set(maxReach({ roomType: 'public', verb: 'variant-of' })), 'favela')
})

test('flag projects to bsky as a label, and nowhere on the fediverse', (t) => {
  // AS2 `Flag` is a REPORT to the origin's moderators — a different act from a shared signal, so
  // conflating them would misrepresent the moderator (SOCIAL-MODEL §6.7).
  t.is(set(maxReach({ roomType: 'public', verb: 'flag' })), 'bsky,favela')
})

test('the meet is per-input: a restrictive room narrows a permissive verb', (t) => {
  t.is(set(maxReach({ roomType: 'followers', verb: 'flag' })), 'favela',
    'flag would reach bsky, but a followers room cannot')
})

test('maxReach is TOTAL — never throws, always returns a Set containing favela', (t) => {
  const hostile = [undefined, null, {}, { roomType: 'public' }, { verb: 'post' },
    { roomType: [], verb: {} }, { roomType: 'dm', verb: 'alias' }]
  for (const arg of hostile) {
    try {
      const r = maxReach(arg)
      t.ok(r instanceof Set && r.has('favela'), 'total on ' + JSON.stringify(arg))
    } catch (err) {
      t.fail('threw on ' + JSON.stringify(arg) + ': ' + err.message)
    }
  }
})

test('favela is ALWAYS reachable — local is the substrate, not a scope (§5.4)', (t) => {
  // "Every post is local. The canonical record always exists on the P2P side; that is what authoring
  // one means. 'Local' is therefore not a destination you opt into, and there is no way to opt out."
  for (const roomType of ['public', 'followers', 'members', 'dm', 'nonsense']) {
    for (const verb of ['post', 'like', 'alias', 'net.example.unknown']) {
      t.ok(maxReach({ roomType, verb }).has('favela'), roomType + '/' + verb + ' is always local')
    }
  }
})

test('NETWORKS is exported and favela leads it', (t) => {
  t.ok(NETWORKS.includes('favela') && NETWORKS.includes('bsky') && NETWORKS.includes('fediverse'))
})