Pull-mode httpClient + drainer + parallel RPCs against the same peer deteriorated after ~10s with `DecryptionError`. Two bugs combined: - `OutboundQueue.enqueue` woke `drain` waiters with a `since=0` snapshot, replaying already-processed events into `Shade.acceptTransferEnvelope` → `manager.decrypt` twice. The duplicate consumed an already-used skipped key and corrupted the Double Ratchet receive chain. - `ratchetDecrypt` then propagated the corruption: a same-DH message behind the chain with no cached skipped key fell through to `kdfChainKey` on the ahead state and rewound `chain.counter`, permanently desyncing the chain. Fix `OutboundQueue` to honor each waiter's `since`, and harden `ratchetDecrypt` so any future duplicate fails cleanly without mutating state. Adds regression coverage at all three layers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
21 lines
445 B
JSON
21 lines
445 B
JSON
{
|
|
"name": "@shade/dashboard",
|
|
"version": "4.2.1",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "vite build && bun run scripts/copy-to-observer.ts"
|
|
},
|
|
"dependencies": {
|
|
"@shade/widgets": "workspace:*",
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/react": "^19.0.0",
|
|
"@types/react-dom": "^19.0.0",
|
|
"@vitejs/plugin-react": "^4.3.0",
|
|
"vite": "^6.0.0"
|
|
}
|
|
}
|