Commit Graph

11 Commits

Author SHA1 Message Date
egutierrez f8b2bf8e9e Merge branch 'issue/ui-rooms' 2026-06-14 13:49:23 +02:00
egutierrez e8850d8965 feat(uniweb): crear rooms y chatear desde la UI
Añade un control "Nueva room" en el header del sidebar (botón "+") y CTAs
en los estados vacíos del sidebar y del panel. Abren un modal que pide el
asunto, crea la room con bus.createRoom contra el bus real, la inserta en
la lista (dedup por id, sin recargar) y la activa.

- NewRoomModal: modal de Mantine con loading, manejo de SessionError/Error
  en español, crear con Enter o botón, formulario limpio en cada apertura.
- ChatShell: estado del modal con useDisclosure, handleRoomCreated centraliza
  inserción + selección, empty state del panel rediseñado con botón crear.
- Sidebar: prop onNewRoom, botón "+" con tooltip, empty state distingue
  "sin resultados" de "sin rooms" (con CTA crear primera room).

No toca la capa de datos (busService.ts ni web/src/bus/): usa los métodos de
bus tal como están. Verificado end-to-end contra el cluster real: crear room
desde la UI, enviar mensaje y verlo aparecer por la suscripción.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 12:35:33 +02:00
agent 3f52167b04 feat: browser-native client — wire SPA to the SDK, delete the Go gateway
Phase 2 of issue 0001. uniweb becomes a pure frontend (web/ only), like
unibus_android: the SPA talks directly to the bus and the Go gateway is gone.

- busService.ts: the new data layer over the bus SDK, replacing the old api module.
  It holds the user's wallet identity and a connected BusClient IN THE BROWSER and
  opens the session locally — the private key is never sent anywhere (closes the
  gateway-era hole where the browser POSTed its private key to /api/session).
- Wire account/App/ChatShell/ChatPanel/WalletLogin/Recover/Join to busService;
  subscribeRoom replaces the SSE streamRoom; ApiError -> SessionError.
- SDK: ControlPlane.createRoom + listMemberRooms, and fetchRoom mapped to the real
  control-plane wire shape (snake_case, no id) — all verified by the live round-trip.
- Delete cmd/webgw, go.mod, go.sum, src/api.ts and the orphan operator Login. uniweb
  now has zero Go and no dependency on unibus as a module.
- vite: drop the /api proxy, dev server on 5173 to match the bus CORS allowlist; add
  vite-env typings. app.md: lang ts, no uses_functions, e2e_checks are now web-only.
  Bump 0.3.0.

Onboarding by token is now admin-side (the bus has no self-register endpoint; the
gateway only mocked it). tsc + pnpm build + 19/19 unit green.
2026-06-14 11:39:06 +02:00
egutierrez bf0884527e chore: auto-commit (2 archivos)
- dev/
- registry.db

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 11:27:04 +02:00
agent 2960b0984a feat(bus): createRoom + control-plane shape fixes, verified by live E2E round-trip
Validating the SDK against the real cluster surfaced the control-plane wire shapes:
the room/policy JSON is snake_case (sign_msgs) and GET /rooms/{id} omits the id.
Fix ControlPlane.fetchRoom to map the wire shape to the SDK Room type, and add
ControlPlane.createRoom (mint a room key, seal it to the owner via sealed box, POST
/rooms) so a browser peer can own an encrypted room.

The live smoke now does a full end-to-end round-trip against the 3-node cluster:
create an encrypted+signed room, connect over nats.ws, publish, and receive the
SDK's own message decrypted with the signature verified. Verified 2026-06-14:
room 01KV2Q…, plaintext round-tripped intact. The whole seal/sign/open happens in
the client; the private key never leaves it.

Exclude *.test.ts from the app tsconfig so the Node-API integration test does not
break the production build (vitest transpiles tests independently). Issue 0001,
Phase 3.
2026-06-14 11:26:13 +02:00
agent b44aa02326 test(bus): prove a registered identity is accepted on the live cluster
Extend the live smoke: when a registered identity is present (its sign_pub added
to the bus allowlist), assert the SAME SDK that a fresh identity gets rejected with
is now ACCEPTED — control plane no longer 401s and the nats.ws data-plane
connection succeeds. Verified 2026-06-14 against the 3-node cluster: random
identity -> 401 / 'authorization violation'; registered identity -> 403 'not a
member of this room' / connected=true. The allowlist is the only gate; the SDK
speaks both planes correctly end-to-end. Issue 0001, Phase 3.
2026-06-14 11:21:38 +02:00
agent 024af306fe test(bus): live integration smoke against the real unibus cluster
A network smoke (self-skips unless BUS_HTTP/BUS_WS are set) that points the SDK
at the live 3-node cluster. With a fresh, unregistered identity it asserts BOTH
planes reject with an AUTHORIZATION error (not a signature/protocol error),
proving the SDK speaks the control plane (signed canonical request) and the data
plane (nats.ws + nkey) correctly end-to-end. Verified 2026-06-14 against datardos:
control-plane 401 'identity not authorized', data-plane 'authorization violation'.
Issue 0001, Phase 3.
2026-06-14 11:18:43 +02:00
agent b72976e06c feat(bus): complete TypeScript SDK — auth, room envelope, client, transport
Second half of the browser-native bus SDK (issue 0001, Phase 1), making uniweb a
peer of the bus in its own right (like unibus_android) without the Go gateway:

- busauth.ts: NATS user nkey from the Ed25519 key (base32 + crc16, no nkeys dep)
  and control-plane request signing (CanonicalRequest + X-Unibus-* headers).
- room.ts: Policy / Room types (ModeNATS, ModeMatrix).
- client.ts: the pure room ENVELOPE (sealRoomMessage/openRoomMessage — AEAD with
  the subject as AAD, Ed25519 sign, drop on verify/decrypt failure), a transport-
  agnostic BusClient, and a signed ControlPlane HTTP client (fetch room/key/members,
  open the sealed room key locally).
- wstransport.ts: concrete nats.ws WebSocket transport (validated E2E in Phase 3).
- index.ts: public SDK surface.

Parity pinned by vectors from unibus cmd/busvectors (extended with nkey + signed
control-request vectors): 19/19 green. The user's private key signs everything in
the browser and is never sent to any server. Bumps uniweb to 0.2.0.

Remaining for Phase 1 completion: the live nats.ws connection + control-plane,
which need a running unibus with the WebSocket listener — exercised in Phase 3.
2026-06-13 22:54:54 +02:00
agent 3d9b4ce392 feat(bus): TypeScript SDK crypto + frame, parity-verified against Go
First half of the browser-native bus SDK (issue 0001, Phase 1):

- crypto.ts: Ed25519 sign/verify (@noble), ChaCha20-Poly1305 AEAD (@noble),
  endpoint id (sha256+base64url), and the anonymous sealed box for room-key
  distribution. The sealed-box nonce is BLAKE2b-192 over ephPub||recipientPub,
  matching Go's nacl/box.SealAnonymous (NOT SHA-512) so a Go-sealed key opens here.
- frame.ts: the Frame wire format, reproducing Go encoding/json byte-for-byte —
  struct field order, omitempty rules, base64-std byte fields, and the default
  HTML escaping (<, >, &, U+2028/U+2029) — plus sign/verify over canonical bytes.

vectors.test.ts checks all of it against the golden vectors generated by unibus
cmd/busvectors. 11/11 green: endpoint id, Ed25519 (incl. frame signature),
AEAD seal+open, sealed box open + round-trip, and frame signing-bytes + wire
marshal. This pins cross-language interop with Go/Kotlin peers.

Adds @noble/ciphers, tweetnacl (runtime) and vitest (dev).
2026-06-13 22:30:38 +02:00
agent cb6b51156a test(bus): add cross-language crypto/protocol vectors from unibus
Golden vectors generated by unibus cmd/busvectors: the contract the TypeScript
bus SDK must match byte-for-byte (Ed25519 sign, ChaCha20-Poly1305 AEAD, sealed
box, Frame wire format). Issue 0001, Phase 0.
2026-06-13 22:22:32 +02:00
agent e8e37d77fe feat: initial scaffold of uniweb — unibus web frontend (SPA + gateway)
Extracted from unibus v0.13.0: the chat SPA (web/, React+Mantine, per-user
BIP39 wallet) and the web gateway (cmd/webgw, REST+SSE) that acts as a bus
peer for the browser. Consumes unibus as a Go module via replace => ../unibus,
keeping its own replace fn-registry for the cybersecurity primitives.

go build/vet/test and pnpm build green in the new location.
2026-06-13 21:23:10 +02:00