// ⛔ ISOLATION. Routing many actors through one process while they share a record source, a follower
// list or a key is worse than not routing them at all: the second user serves the first's posts,
// their followers are the same people, and one key signs for both.
import test from 'brittle'
import { Users } from '../lib/users.js'
import { PerUser } from '../lib/per-user.js'
const users = () => new Users([
{ username: 'p2p', primary: true },
{ username: 'ashatron', favelaSocket: '/tmp/ash.sock' }
], 'ap.7rnx.net')
const mk = (shared = {}) => new PerUser({ users: users(), dataDir: '/tmp/apb-test', shared })
test('★★ a second user NEVER inherits the shared instances', async (t) => {
// The failure this class exists to prevent: ashatron serving p2p's posts to p2p's followers.
const shared = { records: { tag: 'shared' }, followerStore: { tag: 'shared' }, signer: { tag: 'shared' } }
const pu = mk(shared)
const u = pu.users.get('ashatron')
t.not(pu.records(u), shared.records)
t.not(pu.followers(u), shared.followerStore)
t.not(pu.signer(u), shared.signer)
})
test('⚠ the PRIMARY does inherit them — its followers are real people', async (t) => {
// A fresh follower store for the incumbent would silently stop delivering to everyone already
// following it.
const shared = { records: { tag: 'shared' }, followerStore: { tag: 'shared' }, signer: { tag: 'shared' } }
const pu = mk(shared)
const p = pu.users.primary
t.is(pu.records(p), shared.records)
t.is(pu.followers(p), shared.followerStore)
t.is(pu.signer(p), shared.signer)
})
test('★★ a user with a peer gets a REMOTE signer — the bridge holds no key', async (t) => {
const s = mk().signer(users().get('ashatron'))
t.ok(s, 'there is a signer')
t.is(s.custody, 'remote', 'and it holds nothing')
t.is(s.keyId, 'https://ap.7rnx.net/ap/users/ashatron/actor#main-key', 'keyed to THEIR actor')
})
test('⛔ no key and no peer means NO SIGNER, and that is the safe direction', async (t) => {
// An actor with no signer can still be fetched, followed and read; it simply cannot push. Failing
// the other way would mean signing with somebody else's key.
const u = new Users([{ username: 'p2p', primary: true }, { username: 'nobody' }], 'ap.7rnx.net')
const pu = new PerUser({ users: u, dataDir: '/tmp/apb-test' })
t.is(pu.signer(u.get('nobody')), null)
})
test('⚠ resolvers are memoised — a socket per request is not a design', async (t) => {
const pu = mk()
const u = pu.users.get('ashatron')
t.is(pu.signer(u), pu.signer(u))
t.is(pu.followers(u), pu.followers(u), 'and a store rebuilt per request forgets what it was told')
})