package client // This file exposes two read helpers the mobile binding needs but that the core // client did not surface yet: the peer's own endpoint id, and the cluster member // directory (endpoint id -> human handle). Both are additive and read-only. // EndpointID returns this peer's stable endpoint id, base64url(sha256(signPub)), // the value the bus stamps as the sender of every frame this peer publishes. func (c *Client) EndpointID() string { return c.endpoint } // DirectoryEntry maps a member's stable endpoint id to a human handle, as served // by the control plane's GET /directory. A client uses it to render readable names // instead of raw endpoint ids on incoming frames. type DirectoryEntry struct { SignPub string // 64-hex Ed25519 public key Endpoint string // base64url-nopad, == EndpointID(signPub) Handle string Role string } type directoryMemberWire struct { SignPub string `json:"sign_pub"` Endpoint string `json:"endpoint"` Handle string `json:"handle"` Role string `json:"role"` } type directoryResp struct { Members []directoryMemberWire `json:"members"` } // Directory fetches the cluster-wide member directory (endpoint id -> handle). Any // active user may read it; the request is signed like every other control-plane // call. Returns the active members only (the server filters to status=active). func (c *Client) Directory() ([]DirectoryEntry, error) { var resp directoryResp if err := c.doJSON("GET", "/directory", nil, &resp); err != nil { return nil, err } out := make([]DirectoryEntry, 0, len(resp.Members)) for _, m := range resp.Members { out = append(out, DirectoryEntry{ SignPub: m.SignPub, Endpoint: m.Endpoint, Handle: m.Handle, Role: m.Role, }) } return out, nil }