feat: Phase 3 Week 4 — mesh RPC endpoints for typed messages + session management

Backend (6 new RPC endpoints):
- mesh.send-invoice: create Lightning invoice, send bolt11 to mesh peer
- mesh.send-coordinate: send GPS coordinates (integer microdegrees)
- mesh.send-alert: send signed emergency alert (with optional GPS)
- mesh.outbox: list pending store-and-forward messages
- mesh.session-status: get Double Ratchet session info per peer
- mesh.rotate-prekeys: force X3DH prekey rotation

Mock backend: matching dev mode responses for all 6 new endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-17 02:23:30 +00:00
co-authored by Claude Opus 4.6
parent de92bb2cd4
commit df478c4a1e
4 changed files with 475 additions and 76 deletions
+89
View File
@@ -1570,6 +1570,95 @@ app.post('/rpc/v1', (req, res) => {
return res.json({ result: { configured: true } })
}
case 'mesh.send-invoice': {
console.log(`[Mesh] Send invoice: ${params?.amount_sats} sats to contact ${params?.contact_id}`)
return res.json({
result: {
sent: true,
message_id: Math.floor(Math.random() * 10000) + 200,
amount_sats: params?.amount_sats,
bolt11: `lnbc${params?.amount_sats}n1pjmesh...`,
},
})
}
case 'mesh.send-coordinate': {
console.log(`[Mesh] Send coordinate: ${params?.lat}, ${params?.lng} to contact ${params?.contact_id}`)
return res.json({
result: {
sent: true,
message_id: Math.floor(Math.random() * 10000) + 300,
lat: Math.round((params?.lat || 0) * 1000000),
lng: Math.round((params?.lng || 0) * 1000000),
},
})
}
case 'mesh.send-alert': {
console.log(`[Mesh] Send alert: ${params?.alert_type}${params?.message}`)
return res.json({
result: {
sent: true,
alert_type: params?.alert_type || 'status',
signed: true,
},
})
}
case 'mesh.outbox': {
return res.json({
result: {
messages: [
{
id: 1,
dest_did: 'did:key:z6MkrHKPxJP6tvCvXMaJKZd3rRA2Y44tyftVhR8FDCMKGFjb',
from_did: 'did:key:z6MkSelf',
created_at: new Date(Date.now() - 1800000).toISOString(),
ttl_secs: 86400,
retry_count: 3,
relay_hops: 0,
expired: false,
},
{
id: 2,
dest_did: 'did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp7NQD5EjEREWh',
from_did: 'did:key:z6MkSelf',
created_at: new Date(Date.now() - 7200000).toISOString(),
ttl_secs: 86400,
retry_count: 8,
relay_hops: 1,
expired: false,
},
],
count: 2,
},
})
}
case 'mesh.session-status': {
const hasSess = (params?.contact_id === 1 || params?.contact_id === 4)
return res.json({
result: {
has_session: hasSess,
forward_secrecy: hasSess,
message_count: hasSess ? 23 : 0,
ratchet_generation: hasSess ? 7 : 0,
peer_did: hasSess ? 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2ReMkBe4bR6XBIDNq9' : null,
},
})
}
case 'mesh.rotate-prekeys': {
console.log('[Mesh] Rotating prekeys...')
return res.json({
result: {
rotated: true,
signed_prekey_id: Math.floor(Math.random() * 1000000),
one_time_prekeys: 10,
},
})
}
// =====================================================================
// Transport Layer (unified routing: mesh > lan > tor)
// =====================================================================