mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-28 16:32:28 +00:00
diag(nip46): add temporary lifecycle diagnostics for #33
Code-level audit of the NIP-46/Amber login+profile+persistence bug points at a single shared SignerManager.nip46Client + per-profile restore/switch not being multi-account-aware. Added TEMP [nip46-diag] userLogger traces (visible on unstable; devLogger is gated off there) at: - scheduleStoredRemoteSignerRestore (restore-on-load → "unknown user") - disconnectRemoteSigner (the shared-client teardown → "logs out everyone") - SignerManager.logout (scope) - authService.switchProfile (does the switch resolve the expected pubkey) These let a single Amber reproduction pinpoint the exact failure before the fix. Findings + plan recorded under TODO #33. Remove diagnostics with the fix. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
adf0488df8
commit
088a5c797d
3 files changed
+76
-1
No files matched your search
@@ -883,6 +883,13 @@ export class SignerManager {
|
||||
|
||||
async scheduleStoredRemoteSignerRestore() {
|
||||
const stored = readStoredNip46Session();
|
||||
// [nip46-diag] TEMP (todo #33): trace whether a NIP-46 session is restored on
|
||||
// load — the "unknown user after refresh" symptom. Remove with the fix.
|
||||
userLogger.info("[nip46-diag] restore: scheduleStoredRemoteSignerRestore", {
|
||||
hasStored: !!stored,
|
||||
storedPubkey: stored?.pubkey || stored?.userPubkey || null,
|
||||
storedKeys: stored ? Object.keys(stored) : [],
|
||||
});
|
||||
if (!stored) {
|
||||
return;
|
||||
}
|
||||
@@ -896,8 +903,15 @@ export class SignerManager {
|
||||
silent: true,
|
||||
validator: this.buildAccessControlValidator(),
|
||||
});
|
||||
userLogger.info("[nip46-diag] restore: succeeded", {
|
||||
resolvedPubkey: this.pubkey || null,
|
||||
});
|
||||
} catch (err) {
|
||||
devLogger.warn("Failed to restore remote signer", err);
|
||||
// Surfaced via userLogger so it's visible on unstable (devLogger is gated).
|
||||
userLogger.warn("[nip46-diag] restore: FAILED", {
|
||||
message: err?.message || String(err),
|
||||
code: err?.code || null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -905,6 +919,14 @@ export class SignerManager {
|
||||
}
|
||||
|
||||
async disconnectRemoteSigner({ keepStored = false } = {}) {
|
||||
// [nip46-diag] TEMP (todo #33): the single shared nip46Client is torn down here;
|
||||
// logout/switch calling this is the suspected "logs out everyone" cause.
|
||||
userLogger.info("[nip46-diag] disconnectRemoteSigner", {
|
||||
keepStored,
|
||||
hadClient: !!this.nip46Client,
|
||||
pubkey: this.pubkey || null,
|
||||
stack: new Error().stack?.split("\n").slice(2, 5).join(" <- "),
|
||||
});
|
||||
// Abort an in-flight nostrconnect:// handshake wait, if any.
|
||||
if (typeof this.pendingHandshakeCancel === "function") {
|
||||
try {
|
||||
@@ -1016,6 +1038,13 @@ export class SignerManager {
|
||||
|
||||
logout() {
|
||||
const previousPubkey = this.pubkey;
|
||||
// [nip46-diag] TEMP (todo #33): trace logout scope — which pubkey + whether a
|
||||
// shared remote-signer client is being torn down (affects other NIP-46 profiles).
|
||||
userLogger.info("[nip46-diag] logout", {
|
||||
previousPubkey: previousPubkey || null,
|
||||
hadRemoteClient: !!this.nip46Client,
|
||||
sessionActorSource: this.sessionActor?.source || null,
|
||||
});
|
||||
this.pubkey = null;
|
||||
logoutSignerFromRegistry(previousPubkey);
|
||||
const previousSessionActor = this.sessionActor;
|
||||
|
||||
@@ -977,6 +977,12 @@ export default class AuthService {
|
||||
const providerId = normalizeProviderId(normalizedOptions.providerId);
|
||||
|
||||
const normalizedActive = this.normalizeHexPubkey(getActiveProfilePubkey());
|
||||
// [nip46-diag] TEMP (todo #33): trace profile switching — from/to + provider.
|
||||
userLogger.info("[nip46-diag] switchProfile: begin", {
|
||||
from: normalizedActive || null,
|
||||
to: normalizedTarget,
|
||||
providerId: providerId || null,
|
||||
});
|
||||
if (normalizedActive && normalizedActive === normalizedTarget) {
|
||||
return { switched: false, reason: "already-active" };
|
||||
}
|
||||
@@ -993,6 +999,10 @@ export default class AuthService {
|
||||
try {
|
||||
requestResult = await this.requestLogin(requestOptions);
|
||||
} catch (error) {
|
||||
userLogger.warn("[nip46-diag] switchProfile: requestLogin FAILED", {
|
||||
to: normalizedTarget,
|
||||
message: error?.message || String(error),
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -1001,6 +1011,13 @@ export default class AuthService {
|
||||
(typeof requestResult?.pubkey === "string"
|
||||
? requestResult.pubkey.trim()
|
||||
: "");
|
||||
// [nip46-diag] TEMP (todo #33): did the switch resolve the EXPECTED pubkey?
|
||||
userLogger.info("[nip46-diag] switchProfile: requestLogin returned", {
|
||||
to: normalizedTarget,
|
||||
requestedPubkey: requestedPubkey || null,
|
||||
matchesTarget: requestedPubkey === normalizedTarget,
|
||||
hasDetail: !!requestResult?.detail,
|
||||
});
|
||||
|
||||
let detail = requestResult?.detail || null;
|
||||
|
||||
|
||||
@@ -48,6 +48,35 @@ Likely a shared root cause in session/identity persistence + multi-account handl
|
||||
connection are stored/restored, how multiple accounts are tracked, and how
|
||||
logout scopes to one account. Produce a plan (likely `docs/`), then fix.
|
||||
|
||||
- [x] **AUDIT done 2026-06-25 (code-level).** Architecture:
|
||||
`js/state/cache.js` persists a list of **saved profiles** (`bitvid:savedProfiles:v1`)
|
||||
+ a single **active profile pubkey**. There is ONE active session at a time.
|
||||
`SignerManager` (`js/nostr/managers/SignerManager.js`) holds a SINGLE shared
|
||||
`this.nip46Client` (one remote-signer connection). Likely root cause for ALL three
|
||||
symptoms: the single-shared `nip46Client` + per-profile restore/switch not being
|
||||
multi-account-aware. Specifics:
|
||||
- **Logout-logs-out-everyone:** `authService.logout()` IS registry-scoped
|
||||
(`logoutSignerFromRegistry(previousPubkey)`), but `SignerManager.logout()`
|
||||
calls `disconnectRemoteSigner()` which destroys the SHARED `nip46Client` — so
|
||||
for NIP-46 every profile that depends on it loses its signer.
|
||||
- **Switch-doesn't-work:** `authService.switchProfile` re-runs `requestLogin`
|
||||
with `expectPubkey`; for NIP-46 the shared client must be re-established for the
|
||||
target profile — if it doesn't reconnect, the new profile has no working signer.
|
||||
- **Unknown-user-after-refresh:** `scheduleStoredRemoteSignerRestore` →
|
||||
`useStoredRemoteSigner` silently fails (the catch logged via the gated
|
||||
`devLogger`), leaving `this.pubkey` unresolved → UI shows "unknown user".
|
||||
- [x] **Diagnostics SHIPPED (2026-06-25, TEMP).** Added `[nip46-diag]` `userLogger`
|
||||
traces (visible on unstable, where `devLogger` is gated off) at:
|
||||
`scheduleStoredRemoteSignerRestore` (hasStored/storedPubkey + succeeded/FAILED),
|
||||
`disconnectRemoteSigner` (keepStored/hadClient + caller stack),
|
||||
`SignerManager.logout` (previousPubkey/hadRemoteClient), and
|
||||
`authService.switchProfile` (from/to + whether requestLogin resolved the expected
|
||||
pubkey). **Remove these once the fix lands.**
|
||||
- [ ] **NEXT: reproduce on the phone with Amber on unstable, paste the `[nip46-diag]`
|
||||
console output**, then ship the targeted fix (likely: per-profile NIP-46 session
|
||||
keyed by pubkey, don't tear the shared client on a scoped logout, and reconnect on
|
||||
switch/restore).
|
||||
|
||||
### 1. Delete is not fully working — tombstoned videos still show in the UI
|
||||
- [x] **Root cause found + fixed** (`afb6200b`): deletes published only to the CAPPED
|
||||
read set (<=8) while videos publish to the full write set, so relays outside
|
||||
|
||||
Reference in new issue
Block a user