fix: BUG-1 CSRF, TASK-8 H2/H3/H4, BUG-20/37/40/41 — 7 bugs fixed
BUG-1 (P0): CSRF tokens now HMAC-derived from session token instead of
random — survives backend restarts, eliminates cookie/header race conditions.
Frontend retries 403s as belt-and-suspenders.
TASK-8 H2: federation.peer-joined verifies ed25519 signature on join messages.
TASK-8 H3: federation.peer-address-changed requires signed proof from known peer.
TASK-8 H4: Rust backend default bind 0.0.0.0 → 127.0.0.1 (nginx proxies all).
BUG-20: ElectrumX index estimate string fixed from ~55GB to ~130GB.
BUG-37: App card Start/Stop buttons split into loading vs interactive states
to prevent WebSocket state flicker during container scans.
BUG-40: Uninstall modal uses Teleport to body with z-[3000] for full overlay.
BUG-41: Uninstalling overlay on card + optimistic store removal.
Updated MASTER_PLAN.md and BETA-PROGRESS.md to reflect all completed work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
00bfd62393
commit
41ff1021ad
@@ -298,6 +298,7 @@ pub async fn accept_invite(
|
||||
local_did: &str,
|
||||
local_onion: &str,
|
||||
local_pubkey: &str,
|
||||
sign_fn: impl FnOnce(&[u8]) -> String,
|
||||
) -> Result<FederatedNode> {
|
||||
let (did, onion, pubkey, _token) = parse_invite(code)?;
|
||||
|
||||
@@ -333,17 +334,19 @@ pub async fn accept_invite(
|
||||
save_invites(data_dir, &invites).await?;
|
||||
|
||||
// Notify remote node (best-effort over Tor)
|
||||
let _ = notify_join(&node.onion, local_did, local_onion, local_pubkey).await;
|
||||
let _ = notify_join(&node.onion, local_did, local_onion, local_pubkey, sign_fn).await;
|
||||
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
/// Best-effort notification to the remote node that we joined their federation.
|
||||
/// Signs the message with our ed25519 key so the remote peer can verify authenticity.
|
||||
async fn notify_join(
|
||||
remote_onion: &str,
|
||||
local_did: &str,
|
||||
local_onion: &str,
|
||||
local_pubkey: &str,
|
||||
sign_fn: impl FnOnce(&[u8]) -> String,
|
||||
) -> Result<()> {
|
||||
let host = if remote_onion.ends_with(".onion") {
|
||||
remote_onion.to_string()
|
||||
@@ -351,12 +354,18 @@ async fn notify_join(
|
||||
format!("{}.onion", remote_onion)
|
||||
};
|
||||
let url = format!("http://{}/rpc/v1", host);
|
||||
|
||||
// Sign the canonical message: "peer-joined:{did}:{onion}:{pubkey}"
|
||||
let sign_data = format!("peer-joined:{}:{}:{}", local_did, local_onion, local_pubkey);
|
||||
let signature = sign_fn(sign_data.as_bytes());
|
||||
|
||||
let body = serde_json::json!({
|
||||
"method": "federation.peer-joined",
|
||||
"params": {
|
||||
"did": local_did,
|
||||
"onion": local_onion,
|
||||
"pubkey": local_pubkey,
|
||||
"signature": signature,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user