@startuml title Indexer — Peer A publishing, Peer B publishing (handleNodePublish → DHT) participant "Node A" as NodeA participant "Node B" as NodeB participant "IndexerService (shared)" as Indexer participant "DHT Kademlia" as DHT note over NodeA: Start after claimInfo or refresh TTL par Peer A publish its PeerRecord NodeA -> Indexer: TempStream /opencloud/record/publish/1.0 NodeA -> Indexer: stream.Encode(PeerRecord A {DID_A, PeerID_A, PubKey_A, Expiry, Sig_A}) Indexer -> Indexer: Verify sig_A (reconstruit rec minimal, pubKey_A.Verify) Indexer -> Indexer: Check StreamRecords[Heartbeat][PeerID_A] existe alt A active Heartbeat Indexer -> Indexer: StreamRecord A → DID_A, Record=PeerRecord A, LastSeen=now Indexer -> DHT: PutValue("/node/"+DID_A, PeerRecord A JSON) Indexer -> DHT: PutValue("/name/"+name_A, DID_A) Indexer -> DHT: PutValue("/peer/"+peer_id_A, DID_A) DHT --> Indexer: ok else Pas de heartbeat Indexer -> NodeA: (erreur "no heartbeat", stream close) end else Peer B publish its PeerRecord NodeB -> Indexer: TempStream /opencloud/record/publish/1.0 NodeB -> Indexer: stream.Encode(PeerRecord B {DID_B, PeerID_B, PubKey_B, Expiry, Sig_B}) Indexer -> Indexer: Verify sig_B Indexer -> Indexer: Check StreamRecords[Heartbeat][PeerID_B] existe alt B Active Heartbeat Indexer -> Indexer: StreamRecord B → DID_B, Record=PeerRecord B, LastSeen=now Indexer -> DHT: PutValue("/node/"+DID_B, PeerRecord B JSON) Indexer -> DHT: PutValue("/name/"+name_B, DID_B) Indexer -> DHT: PutValue("/peer/"+peer_id_B, DID_B) DHT --> Indexer: ok else Pas de heartbeat Indexer -> NodeB: (erreur "no heartbeat", stream close) end end par note over DHT: DHT got \n"/node/DID_A" et "/node/DID_B" @enduml