fix(pr-77): apply Copilot/Codex review corrections with Protocol de Blindagem

This commit addresses critical issues identified in Copilot's second review
of PR #77, applying Protocol de Blindagem methodology for high reliability.

## Critical Fixes

### 1. Session Error Detection (CRITICAL BUG FIX)
**Problem**: Auto-reconnect feature was completely non-functional
- Checked `update.error` in creds.update handler
- This property does NOT exist in `Partial<AuthenticationCreds>` type
- Entire code path was unreachable
- `isSessionError` flag was never set

**Root Cause Analysis** (Protocol de Blindagem):
- Análise de Fronteira: Assumed property exists without verifying type contract
- Verificação de Invariantes: No compile-time type checking caught this
- Session errors come from DisconnectReason.badSession/restartRequired, NOT creds

**Solution**:
- REMOVED broken creds.update handler (lines 1422-1441)
- ADDED proper detection in end() function using DisconnectReason enum
- Check statusCode for badSession (500) or restartRequired (515)
- Set isSessionError flag correctly in connection.update event
- Added observability log when session error detected

**Impact**:
- Auto-reconnect feature now FUNCTIONAL
- Consumers can detect session errors via isSessionError flag
- Proper socket recreation on session desynchronization

### 2. Metrics Queue Protection (Memory Leak Prevention)
**Problem**: structured-logger.ts had unbounded queue growth risk
- metricsQueue initialized but never populated
- No protection against import failure
- No size cap to prevent memory leak

**Solution** (mirroring event-buffer.ts pattern):
- Added metricsImportFailed flag
- Added MAX_METRICS_QUEUE_SIZE = 1000 cap
- Clear queue on import failure
- Clear queue in destroy() method

**Why Important**:
- Defensive programming prevents future issues
- When metric recording is implemented, won't cause memory leak
- Consistent pattern with event-buffer.ts

## Files Modified
- src/Socket/socket.ts: Fixed session error detection, removed broken handler
- src/Utils/structured-logger.ts: Added metrics queue protections

## Testing Approach
Per-contact session errors already handled correctly in messages-recv.ts.
Socket-level session errors (badSession, restartRequired) now properly emit
isSessionError flag for consumer to detect and recreate socket.

## Protocol de Blindagem Applied
✓ Análise de Fronteira: Verified actual type contracts, not assumptions
✓ Verificação de Invariantes: Session errors from DisconnectReason, not creds
✓ Rastreamento de Fluxo: Traced where session errors actually originate
✓ Mitigação de Arestas: Added defensive caps and cleanup
✓ Desconfiança Semântica: Didn't trust property name, verified implementation

https://claude.ai/code/session_VMxqX
This commit is contained in:
Claude
2026-02-03 23:35:57 +00:00
parent c3a44783bd
commit cbb4020425
2 changed files with 22 additions and 23 deletions
+16 -22
View File
@@ -996,12 +996,27 @@ export const makeSocket = (config: SocketConfig) => {
} catch {}
}
// Detect socket-level session errors that require recreation
const statusCode = (error as Boom)?.output?.statusCode || 0
const isSessionError = (
statusCode === DisconnectReason.badSession ||
statusCode === DisconnectReason.restartRequired
)
if (isSessionError) {
logger.warn(
{ statusCode, reason: DisconnectReason[statusCode] },
'🔴 Socket-level session error - consumer should recreate socket'
)
}
ev.emit('connection.update', {
connection: 'close',
lastDisconnect: {
error,
date: new Date()
}
},
isSessionError
})
ev.removeAllListeners('connection.update')
}
@@ -1404,27 +1419,6 @@ export const makeSocket = (config: SocketConfig) => {
// update credentials when required
ev.on('creds.update', async update => {
// CRITICAL: Handle session errors by emitting close event for consumer-level reconnect
if (update.error) {
logger.error({ error: update.error }, '🔴 Session error detected')
// Session errors indicate keys are desynchronized - socket must be recreated
// Emit close event so consumer can call makeWASocket() again
ev.emit('connection.update', {
connection: 'close',
lastDisconnect: {
error: update.error,
date: new Date()
},
// Include session error flag for consumer to detect
isSessionError: true
})
// Cleanup current socket
await end(update.error)
return
}
const name = update.me?.name
// if name has just been received
if (creds.me?.name !== name) {