// user-keys.test.js — a registered user gets its own keypair.
//
// ⛔ Sharing the primary's key made two actors one identity: Mastodon indexes by publicKey.id, so a
// registered user resolved to the incumbent. Distinct key IDS fix the resolution; distinct key
// MATERIAL is what makes the separation real, because a signature is what proves who acted.
import test from 'brittle'
import fs from 'bare-fs'
import { join } from 'bare-path'
import { UserKeys } from '../lib/user-keys.js'
let n = 0
const tmp = () => join('/tmp/claude-1000/-storage-projects-code-hypercore-kb/c3f731e9-2bec-4052-9d87-28d0c39fbacf/scratchpad', 'keys' + (n++) + '-' + Date.now())
test('★★ a user gets a keypair, and the same one every time', async (t) => {
const keys = new UserKeys({ dir: tmp() })
const a = await keys.forUser('ashatron')
t.ok(a.publicKeyPem.includes('BEGIN PUBLIC KEY'), 'a real public key')
t.ok(a.privateKeyPem.includes('PRIVATE KEY'), 'and a private half')
const again = await keys.forUser('ashatron')
t.is(again.publicKeyPem, a.publicKeyPem, '⛔ STABLE — a key that changed would break every remote server that cached it')
})
test('★★ two users get DIFFERENT keys', async (t) => {
const keys = new UserKeys({ dir: tmp() })
const a = await keys.forUser('ashatron')
const b = await keys.forUser('someone')
t.not(a.publicKeyPem, b.publicKeyPem, 'which is the entire point')
})
test('★ keys survive a restart', async (t) => {
const dir = tmp()
const first = await new UserKeys({ dir }).forUser('ashatron')
const second = await new UserKeys({ dir }).forUser('ashatron')
t.is(second.publicKeyPem, first.publicKeyPem, 'from disk, not minted afresh')
})
test('⛔ a key file is not world-readable', async (t) => {
const dir = tmp()
await new UserKeys({ dir }).forUser('ashatron')
const mode = fs.statSync(join(dir, 'ashatron.key')).mode & 0o777
t.is(mode, 0o600, 'private key, private mode')
})