feat(mobile): reconstruir+ampliar binding gomobile para paridad con la web
El wrapper mobile/unibus.go se habia perdido del repo (solo quedaba compilado
en el .aar del 5 jun). Se reconstruye y amplia con:
- Wallet BIP39 determinista: NewMnemonic, ValidateMnemonic, DeriveAndSaveIdentity.
Deriva la MISMA identidad que uniweb (web/src/wallet/derive.ts): PBKDF2-BIP39 ->
HKDF-SHA256(info unibus-sign-v1 / unibus-kex-v1) -> Ed25519 + X25519. Test de
paridad contra el vector de oro (mnemonica abandon...about -> sign_pub
34302746...b3c8) garantiza misma cuenta web<->movil byte a byte.
- Selector de salas: Session.ListMyRooms() -> JSON [{id,subject,mode,role}].
- Nombres legibles: Session.Directory() + Client.Directory()/EndpointID() nuevos
en pkg/client (GET /directory firmado).
- HasIdentity/SignPubAt para el onboarding.
Aditivo; build/vet/test del modulo verdes (incluido TestDeriveParityWithWeb).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user