feat: persistent session (no re-unlock on reload) + reconnect ACL after createRoom
Session persistence (web/src/session.ts): the unlocked wallet identity is kept across reloads so an F5 no longer forces a password re-unlock. By default it lives in sessionStorage (survives F5, cleared with the tab); with 'keep me signed in' it lives in localStorage (survives closing the browser) bounded by a 30-day absolute TTL and a 12-hour inactivity auto-lock. logout clears it; activity (send/createRoom) refreshes the idle timer. No cookie is ever used — the private key never travels to any server. WalletLogin gains the 'keep me signed in' checkbox; Recover/Join keep the session by default (recovering/creating on a device implies it is yours). App.tsx restores the session on mount before falling back to the unlock screen. ACL reconnect: a room created while connected was not in the NATS per-subject ACL grant (subjects are frozen at connect time), so its first messages silently did not deliver until a re-login. WsNatsTransport gains reconnect(); BusClient.refresh() calls it; busService.createRoom reconnects after creating so the new room is usable immediately. Bumps uniweb to 0.4.0.
This commit is contained in:
@@ -138,6 +138,10 @@ export type MessageHandler = (subject: string, data: Uint8Array) => void;
|
||||
export interface NatsTransport {
|
||||
publish(subject: string, data: Uint8Array): void | Promise<void>;
|
||||
subscribe(subject: string, handler: MessageHandler): Promise<Subscription>;
|
||||
// reconnect rebuilds the connection so the server's per-subject ACL re-evaluates
|
||||
// this peer's room membership (a room created after connecting is otherwise not in
|
||||
// the grant). Active subscriptions are dropped; re-subscribe after calling it.
|
||||
reconnect(): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -367,4 +371,13 @@ export class BusClient {
|
||||
private async loadSigners(roomID: string): Promise<void> {
|
||||
this.signCache.set(roomID, await this.control.signerKeys(roomID));
|
||||
}
|
||||
|
||||
// refresh reconnects the data plane so the server's per-subject ACL re-evaluates
|
||||
// this peer's room membership. Call it after creating or joining a room while
|
||||
// connected: NATS freezes a connection's publishable/subscribable subjects at
|
||||
// connect time, so the new room's subject only becomes usable on a fresh
|
||||
// connection. Active subscriptions are dropped — re-subscribe afterwards.
|
||||
async refresh(): Promise<void> {
|
||||
await this.transport.reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user