@startuml
title NATS — PROPALGATION_EVENT : Peer A propalgate to Peer B lookup

participant "App Pair A" as AppA
participant "NATS A" as NATSA
participant "Node A" as NodeA
participant "StreamService A" as StreamA
participant "Node Partner B" as PeerB
participant "Node C" as PeerC

participant "NATS B" as NATSB
participant "DB Pair B (oc-lib)" as DBB

note over App: only our proper resource (db data) can be propalgate : creator_id==self

AppA -> NATSA: Publish(PROPALGATION_EVENT, {Action, DataType, Payload})
NATSA -> NodeA: ListenNATS callback → PROPALGATION_EVENT
NodeA -> NodeA: propalgate from himself ? → no, continue
NodeA -> NodeA: json.Unmarshal → PropalgationMessage{Action, DataType, Payload}

alt Action == PB_DELETE
    NodeA -> StreamA: ToPartnerPublishEvent(PB_DELETE, dt, user, payload)
    StreamA -> StreamA: searchPeer(PARTNER) → [Peer Partner B, ...]
    StreamA -> NodeB: write(PeerID_B, addr_B, dt, user, payload, ProtocolDeleteResource)
    note over NodeB: /opencloud/resource/delete/1.0

    NodeB -> NodeB: handleEventFromPartner(evt, ProtocolDeleteResource)
    NodeB -> NATSB: SetNATSPub(REMOVE_RESOURCE, {DataType, resource JSON})
    NATSB -> DBB: Suppress ressource into DB B

else Action == PB_UPDATE (per ProtocolUpdateResource)
    NodeA -> StreamA: ToPartnerPublishEvent(PB_UPDATE, dt, user, payload)
    StreamA -> StreamA: searchPeer(PARTNER) → [Peer Partner B, ...]
    StreamA -> NodeB: write → /opencloud/resource/update/1.0
    NodeB -> NATSB: SetNATSPub(CREATE_RESOURCE, {DataType, resource JSON})
    NATSB -> DBB: Upsert ressource dans DB B

else Action == PB_CREATE (per ProtocolCreateResource)
    NodeA -> StreamA: ToPartnerPublishEvent(PB_UPDATE, dt, user, payload)
    StreamA -> StreamA: searchPeer(PARTNER) → [Peer Partner B, ...]
    StreamA -> NodeB: write → /opencloud/resource/create/1.0
    NodeB -> NATSB: SetNATSPub(CREATE_RESOURCE, {DataType, resource JSON})
    NATSB -> DBB: Create ressource dans DB B

else Action == PB_CONSIDERS (is a considering a previous action, such as planning or creating resource)
    NodeA -> NodeA: Unmarshal → executionConsidersPayload{PeerIDs:[PeerID_B, ...]}
    loop For every peer_id targeted
        NodeA -> StreamA: PublishCommon(dt, user, PeerID_B, ProtocolConsidersResource, payload)
        StreamA -> NodeB: write → /opencloud/resource/considers/1.0
        NodeB -> NodeB: passConsidering(evt)
        NodeB -> NATSB: SetNATSPub(PROPALGATION_EVENT, {PB_CONSIDERS, dt, payload})
        NATSB -> DBB: (treat per emmitters app of a previous action on NATS B)
    end

else Action == PB_CLOSE_PLANNER
    NodeA -> NodeA: Unmarshal → {peer_id: PeerID_B}
    NodeA -> StreamA: Streams[ProtocolSendPlanner][PeerID_B].Stream.Close()
    NodeA -> StreamA: delete(Streams[ProtocolSendPlanner], PeerID_B)

else Action == PB_SEARCH + DataType == PEER
    NodeA -> NodeA: read → {search: "..."}
    NodeA -> NodeA: GetPeerRecord(ctx, search)
    note over NodeA: Resolved per DB A or Indexer + DHT
    NodeA -> NATSA: SetNATSPub(SEARCH_EVENT, {PEER, PeerRecord JSON})
    NATSA -> NATSA: (AppA retrieve results)

else Action == PB_SEARCH + other DataType
    NodeA -> NodeA: read → {type:"all"|"known"|"partner", search:"..."}
    NodeA -> NodeA: PubSubService.SearchPublishEvent(ctx, dt, type, user, search)
    note over NodeA: Watch after pubsub_search & stream_search diagrams
end

@enduml
