| … | … | @@ -93,4 +93,23 @@ const E2 = 'did:plc:e2jevhuurrhlm36ufk7fklpg' |
| 93 | 93 | assert((await r.base.intents()).length === 2, 'the intents are still there, under the reserved name') |
| 94 | 94 | assert((await r.signedLog()).length === 2, 'and both were signed') |
| 95 | 95 | } |
| 96 | // ⛔ A SIGNED LABEL WITHOUT `ver` IS NOT EMITTED. The label spec requires ver: 1 on every label that moves |
| 97 | // between services, and signs over it. Before atproto-identity 0.0.5 buildLabel omitted it, and loser-club's two |
| 98 | // member labels sit in the shared log in that shape — bsky's AppView never showed them. The tick must treat such |
| 99 | // an entry as not yet signed and re-sign it, under the same content key, so the log converges on valid labels. |
| 100 | { |
| 101 | const { signLabel, encodeLabel } = await import('atproto-identity/lib/labels.js') |
| 102 | const cts = '2026-10-14T15:09:59.328Z' |
| 103 | const sb = mockSb() |
| 104 | const r = new LabelRoom(sb, { ...KP, holds: () => true }) |
| 105 | await r.label(WJ, 'loser-club-member', { cts }) |
| 106 | const legacy = signLabel({ src: SRC, uri: WJ, val: 'loser-club-member', cts }, labeler.privateKey) // no ver |
| 107 | const key = '__label__\x00' + cts + '\x00' + WJ + '\x00loser-club-member\x000' |
| 108 | await sb.set(key, Buffer.from(encodeLabel(legacy)).toString('hex')) |
| 109 | assert(await r.tick() === 1, 'a log entry without ver is re-signed') |
| 110 | const log = await r.signedLog() |
| 111 | assert(log.length === 1, 'under the SAME content key — the log holds one label, not two') |
| 112 | assert(log[0].ver === 1 && verifyLabel(log[0], labeler.didKey), 'and it now carries ver: 1 and verifies') |
| 113 | assert(await r.tick() === 0, 'a second tick re-signs nothing') |
| 114 | } |
| 96 | 115 | console.log('\nLABEL-ROOM PRESENCE OK') |