feat(broker): record daemon idempotency fields on message_queue
Additive plumbing for v0.9.0 daemon spec §4.2/§4.4. Adds two nullable
columns to mesh.message_queue — client_message_id (caller-supplied) and
request_fingerprint (canonical sha256 of the send shape) — and threads
them through the broker:
- handleSend reads them off the wire envelope when present
- queueMessage persists them on the row
- drainForMember projects them onto the push so receiving daemons
can dedupe their local inbox by client_message_id
Columns stay nullable so legacy traffic (launch CLI, dashboard chat)
continues to flow uninterrupted. Sprint 7 (broker hardening) will add
the partial unique index and the client_message_dedupe atomic-accept
table once we're ready to enforce dedupe broker-side.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -564,6 +564,8 @@ async function maybePushQueuedMessages(
|
||||
nonce: m.nonce,
|
||||
ciphertext: m.ciphertext,
|
||||
createdAt: m.createdAt.toISOString(),
|
||||
...(m.clientMessageId ? { client_message_id: m.clientMessageId } : {}),
|
||||
...(m.requestFingerprint ? { request_fingerprint: m.requestFingerprint } : {}),
|
||||
};
|
||||
sendToPeer(presenceId, push);
|
||||
metrics.messagesRoutedTotal.inc({ priority: m.priority });
|
||||
@@ -1968,6 +1970,12 @@ async function handleSend(
|
||||
}
|
||||
}
|
||||
|
||||
// v0.9.0 daemon clients attach a stable idempotency id and the canonical
|
||||
// request fingerprint per spec §4.2/§4.4. Forward both verbatim; legacy
|
||||
// callers omit them and the columns are nullable.
|
||||
const clientMessageId = (msg as { client_message_id?: string }).client_message_id;
|
||||
const requestFingerprint = (msg as { request_fingerprint?: string }).request_fingerprint;
|
||||
|
||||
const messageId = await queueMessage({
|
||||
meshId: conn.meshId,
|
||||
senderMemberId: conn.memberId,
|
||||
@@ -1976,6 +1984,8 @@ async function handleSend(
|
||||
priority: msg.priority,
|
||||
nonce: msg.nonce,
|
||||
ciphertext: msg.ciphertext,
|
||||
clientMessageId: clientMessageId && clientMessageId.length > 0 ? clientMessageId : undefined,
|
||||
requestFingerprint: requestFingerprint && requestFingerprint.length > 0 ? requestFingerprint : undefined,
|
||||
});
|
||||
|
||||
// Topic-tagged messages (targetSpec starts with `#<topicId>`) get
|
||||
|
||||
Reference in New Issue
Block a user