// The atproto ops on a node that holds SEVERAL identities.
//
// ⛔ WHY. Every did-* op read `cfg.dids[0]`. The desktop app on a server boots hpp's own config, which
// holds wj62 AND loser-club (hyper-social #77 §5, change 5), so "this node's identity" was whichever
// happened to be first — and did-carry / did-adopt / did-submit are PERMANENT appends to a global log.
// The rule is pickNode's (lib/project.js): an explicit `did` wins, then the designated credential
// (identity.md §5.1), then the only one; with several and none chosen a WRITE refuses rather than
// guessing. did-status only reads, so it answers for the chosen one and lists them all.
import test from 'brittle'
import fs from 'bare-fs'
import os from 'bare-os'
import process from 'bare-process'
import { join } from 'bare-path'
import { inProcessClient } from '../index.js'
import { atprotoEntry, atprotoConfigPath } from '../lib/atproto.js'
const PASS = 'a passphrase long enough'
async function twoDids (t) {
const root = join(os.tmpdir(), 'fh-multi-' + Date.now() + '-' + Math.random().toString(16).slice(2))
const storage = join(root, 'storage')
fs.mkdirSync(storage, { recursive: true })
const realHome = process.env.HOME
process.env.HOME = join(root, 'home')
fs.mkdirSync(process.env.HOME, { recursive: true })
t.teardown(() => { process.env.HOME = realHome })
const node = { storage }
const client = inProcessClient(node)
// hpp's mint refuses a second identity in one config (by design), so the second entry is written the
// way a co-owner's config gets one — appended to `dids`. Only selection is under test here.
const a = await client.call('did-mint', { passphrase: PASS })
const cfgPath = atprotoConfigPath(node)
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'))
const b = 'did:plc:secondidentityforselect'
cfg.dids.push({ ...cfg.dids[0], did: b })
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2))
return { node, client, a: a.did, b }
}
test('did-status lists every identity and answers for the one asked about', async (t) => {
const { client, a, b } = await twoDids(t)
const st = await client.call('did-status')
t.alike(st.dids, [a, b], 'both identities listed')
t.is((await client.call('did-status', { did: b })).did, b, 'an explicit did is answered for')
})
test('a write with several identities and none chosen REFUSES instead of using the first', async (t) => {
const { node, b } = await twoDids(t)
t.exception(() => atprotoEntry(node, {}, { write: true }), /several identities/)
t.is(atprotoEntry(node, { did: b }, { write: true }).entry.did, b, 'an explicit did is used')
t.exception(() => atprotoEntry(node, { did: 'did:plc:notmine' }, { write: true }), /not an identity/)
})