Skip to content

feat(identity): consolidate key and account controls - #3069

Open
tellaho wants to merge 14 commits into
mainfrom
tho/identity-page
Open

tellaho wants to merge 14 commits into
mainfrom
tho/identity-page

Conversation

@tellaho

@tellaho tellaho commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Category: improvement
User Impact: Users can manage their key, backup recovery and community sign-ins from one Identity page.

Problem: Key controls and backup feedback are scattered across the page, with duplicate account summaries and unclear recovery actions.

Solution: Put private-key controls, consent, backup recovery and guarded removal on the Identity card. Keep provider accounts below it and retain native consent, account-binding and stale-result protection. Shared controls add masked fields and an opt-in Button.loadingAppearance="disabled"; other loading buttons keep their default appearance.

Validation: Pre-push types, related unit tests, design guards and Clippy pass. Both Chromium and WebKit layout/focus checks pass. Tests are trimmed to failure, safety, focus and layout contracts. Live native upload and human acceptance remain pending.

Try it: Open Settings → Buzz → Identity. Flip the card to access the key, enable optional backup through consent, recover a failed backup, or open the guarded removal confirmation.

Screenshots — b97c65db3

Wide native desktop captures; email and public-key text redacted.

Framed Identity card Community sign-ins (scrolled) More options
Framed Identity card Full-width community sign-ins below the card More options

Account lookup recovery

The lookup failure was induced by temporarily rejecting the account-status read in the native dev window. Recovery follows restoring the original read and clicking Retry; the card returned to Backed up.

Lookup failure / Retry backup Recovered after Retry
Account lookup failure and Retry backup Recovered account lookup after Retry

tellaho and others added 3 commits November 8, 2026 23:11
Add opt-in disabled loading colors and masked field controls with their
shared documentation and viewer specimens.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Expose public key-management metadata without changing native consent or
account-binding enforcement. Retire stale key/account evidence.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Put key access, consent, backup recovery and guarded removal on the ID card.
Keep provider accounts below it and expose the Builderlab connection row.
Retain focused failure, stale-result, consent, focus and layout coverage.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho

tellaho commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Fixed the Settings layout test blocker in 08a07c2. The Identity card now exposes Copy Buzz ID, a Full Buzz ID fallback after clipboard failure, and More options as the next keyboard action. The existing test follows those controls and verifies the full fixture npub is selectable; all geometry assertions remain unchanged. No product code or test cases were added or removed.

Validation: reproduced the original failure in Chromium and WebKit at 8aeb23d, then passed all 58 cases across the seven Settings browser spec files and the Identity badge spec in both engines (zero retries). Pre-commit and pre-push hooks passed, including types/related tests, design checks and Clippy. Hosted CI for the new head remains pending.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho

tellaho commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Updated the Identity layout in b97c65db3: the key card now sits in a shared panel, with More options / Back in its top-left corner and provider rows aligned below. Normal widths use less top space; smaller widths and enlarged text retain clearance around the corner control.

Validation: all 8 cases in identity-badge.spec.mjs and settings-layout.spec.mjs passed across Chromium and WebKit at this head, with no test cases added or removed. Pre-commit and pre-push checks passed. Native screenshots and acceptance of the rebuilt app remain pending.

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 One visual rendering defect found.

Comment thread src/app/IdentityBadge.module.css Resolved
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
matt2e added a commit that referenced this pull request Nov 9, 2026
…s the next step (#3082)

## Why

Identity sync names Builderlab in two of its sentences: when this key
isn't linked to the account (waiting `not_linked`) and when the account
already holds a different key (failed `other_key_linked`). The next step
for both, **Connect Buzz identity** or **Switch to this device's
identity**, is on Settings → Plugins → Builderlab, but the row had
nothing to click. People had to find that page themselves.

## What

In those two sentences the first "Builderlab" becomes a
`SettingsSectionLink` to `block.builderlab/login`, the shared inline
link from #2122. Settings passes the opener only while the Builderlab
card is registered and reuses `openSection`, so focus moves into the
opened section as it does from Decisions API. Without an opener, or in
any other state, the sentence stays plain text. The status text itself
is unchanged; only the name becomes a link.

Deliberately unlinked:

- `no_session`: Builderlab signs in with the build's NIP-FI session, and
that Organization sign-in is on this same Identity page.
- `no_consent`: its next step is the row's own **Sync with Builderlab**
button; Builderlab's page has nothing for it.
- Retryable failures and `signed_out` clear on a new sign-in. The
remaining failures have no fix on Builderlab's page.

The linked states arise only after the user opted into automatic backup:
`nsec_backup.rs` admits consent (`NoConsent`) before it reads the
account's key (`NotLinked`, `OtherKeyLinked`). The link only navigates.
Connecting on Builderlab's page starts a backup the user already agreed
to.

## How

`BackupRow` takes an optional `openBuilderlab` and splits the existing
feedback sentence around the first "Builderlab" for the two states.
`Settings` derives the opener from `openSection` and the contributed
card list. Two files of production change, about 40 lines, plus tests
and the help guide and identity doc.

## Risk

Low. No native, protocol, or persistence changes. The shared link style
makes the Identity sync row about 2 px taller in the linked states.
Known gap, shared with the existing Sync button: a status change while
the link has focus drops focus to the page.

## Testing

- `pnpm typecheck` and biome pass on `01c105cd5`.
- `IdentitySettings.test.tsx` and `Settings.test.tsx`: 124 tests pass.
With main's `IdentitySettings.tsx` and `Settings.tsx` swapped in, three
fail: the two "links Builderlab from the … sentence to its Settings
page" cases and "opens Builderlab from Identity sync only while its card
is registered". The negative cases (`no_session`, `no_consent`, idle,
running, complete, every other failure kind, and no opener) pass on
both, as intended.
- The Settings test removes the Builderlab card while Identity is open
and asserts the link goes in place with no section switch, as well as
the mount-time gate. A `BackupRow` that reads its opener once (`useRef`)
passes the old test and fails this assertion.
- The before/after recording below exercises the real `Settings`
component in headless Chromium.

Not verified: a native FI build, both themes, narrow widths, enlarged
text, and keyboard navigation in the real app.

## Before and after

The same pointer script runs on origin/main (left) and this branch
(right): click "Builderlab" in the Identity sync sentence, go back to
Identity, switch the backup status from waiting `not_linked` to failed
`other_key_linked`, click "Builderlab" again.


https://github.com/user-attachments/assets/04a67ba8-6374-4226-ae24-d8222287f861

![BEFORE, just after the first click: the cursor is on the plain-text
"Builderlab", and Identity is still highlighted and
shown.](https://github.com/user-attachments/assets/24895d72-57e3-430c-a7d1-b065dc1567f2)

![AFTER, the same moment: Plugins → Builderlab is highlighted in the
side menu and its section shows Connect Buzz
identity.](https://github.com/user-attachments/assets/7dd687f0-b496-467f-90d0-56b8ea16b4b9)

**Real:** the `Settings` component, the side menu, the link, the section
switch and the focus move. **Faked:** the backup status, and a fixture
Builderlab card that renders the real `Login` and `HostedCommunities` on
fake sign-in and account data, since the plugin registers its card only
with a native session or the live development server. Recorded in
headless Chromium with Playwright, not a native build.

## Bigger picture

Overlaps with #3069, which deletes `BackupRow` and moves backup state
into a key-card notice, and rewrites the same paragraphs in
`docs/buzz-help.md` and `docs/identity.md`. Whichever lands second
reconciles. If this lands first, #3069 can either carry `openBuilderlab`
and the card gate into the notice, splitting the period-less
`not_linked` and `other_key_linked` strings, or drop the prop and its
tests on the grounds that its plugin-contributed `BuilderlabIdentityRow`
already links Builderlab from Identity. If #3069 lands first, this
becomes a re-implementation in the notice, and the "only button in the
row is the link" assertion has to allow for **Retry backup**.

#2458 links the other direction: Builderlab's Hosted communities card
opens Settings → Identity when the account's backed-up key differs from
this device's. It is complementary.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: mtoohey <mtoohey@squareup.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Preserve the Builderlab next-step link in the Identity card notice.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kyle reviewed the PR and the Nexus review-tracker notes and approved, with one non-blocking keyboard-focus comment.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

Comment thread src/features/identity/PrivateKey.tsx Resolved
tellaho and others added 6 commits November 9, 2026 14:46
Use the shared backed-up linked-key check in the existing Identity card.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Preserve required-sign-in community filtering inside the existing account cards.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Preserve background account-key checks and align the new consent regression with approved backup copy.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants