Skip to content

feat: add profile message action and read-only status - #219

Merged
kalvinnchau merged 2 commits into
mainfrom
peon/profile-human-dm
Sep 24, 2026
Merged

kalvinnchau merged 2 commits into
mainfrom
peon/profile-human-dm

Conversation

@kalvinnchau

Copy link
Copy Markdown
Contributor

Summary

Human profile v2, built on the DM capabilities from #156.

  • Message: foreign profiles get a Message button when the session supports DMs. The button calls session.directMessages.open([pubkey], signal), then navigates to the relay-confirmed channel as a conversation target, using the viewer/community scope captured at click time.
    • The attempt is aborted on unmount. The profile view is keyed by target, viewer and community, so a stale result is ignored.
    • While opening, the button shows a busy state. A failure shows an inline alert, and the user can retry.
  • Hidden DM restore: directMessages.subscribeOpened fires only after open() confirms the roster. useHiddenDms listens to it and clears that DM's local hide.
    • The unhide is deliberately tied to open() success, not to navigation, so back/forward and selection restore don't unhide DMs the user deliberately hid.
    • Side effect: New message also unhides a hidden DM as soon as open() succeeds, before the first send completes.
  • NIP-05: Profile.nip05 is parsed and shown as "NIP-05 (unverified)". It is not DNS-verified.
  • Status (read-only): one read of [{kinds:[30315], authors:[pubkey], "#d":["general"], limit:1}] when the profile opens. The profile shows the newest self-signed event's emoji tag plus its text. Blank, foreign-author and failed reads show nothing, and a late result after switching profile is ignored.
    • This is a snapshot: no live updates and no NIP-40 expiry (desktop doesn't handle expiry either). :shortcode: emoji render as plain text.
    • Setting your own status is out of scope.
  • docs/profiles.md is updated for all of the above.

Tests

Unit (vitest):

  • ProfilePanel.message.test.tsx (6): availability gating, busy state, navigation target and scope, failure and retry, stale abort.
  • ProfilePanel.status.test.tsx (5): newest status with emoji, cleared status, another author's status, failed read, late result after switching profiles.
  • useHiddenDms.test.tsx: an opened DM is unhidden and other hidden DMs stay hidden. direct-messages.test.ts: the notification fires only after a valid roster. profile-details.test.ts: NIP-05 parsing.
  • Guard removal checks: I removed the message guards, the status author filter and the blank-content check one at a time. Each time, the matching test failed.

Browser (Playwright, Chromium + WebKit):

  • Added new-message.spec.mjs › "profile Message opens a fresh DM and restores a hidden one". It is browser-only because it drives the real panel → DM open → navigation → sidebar-hide flow across the app host.
  • profiles.spec.mjs: the fixture gives Mic a kind 30315 status, and the test asserts it renders in the real panel. tests/browser/fixture.mjs accepts this read, with the query shape pinned, so it doesn't trip the unexpected-query guard.
  • No browser cases were removed.

Validation

All of the following ran at df120cc, rebased on e02fe33:

  • bin/pnpm tsc --noEmit -p .: clean.
  • bin/pnpm biome check on the changed files: clean. git diff --check against the base: clean.
  • bin/pnpm vitest run: 2797 pass, 2 fail (read-state.test.ts, unread-startup.test.ts). This branch doesn't touch either file, and both passed 3/3 when rerun on their own.
  • playwright test --config tests/browser/playwright.config.mjs for profiles, profiles-appearance, profile-channel-focus and new-message: 14/14 pass (7 × Chromium and WebKit).

Deferred: full browser suite and hosted CI.

@kalvinnchau
kalvinnchau requested review from a team, comp615 and wesbillman as code owners September 24, 2026 15:50
@kalvinnchau
kalvinnchau force-pushed the peon/profile-human-dm branch 2 times, most recently from 4be3392 to 3a0c930 Compare September 24, 2026 18:09
Open or reopen the one-to-one DM from the human profile through
session.directMessages.open, navigate to the relay-confirmed channel in the
captured viewer/community scope, and clear that DM's local sidebar hide.
Show the self-declared NIP-05 identifier (unverified) and a one-time NIP-38
general status snapshot.

Co-authored-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: peon <9ac6794b000690b7e814eb1805ad32405d0bec7d52838de3a86cf967565dacc0@buzz.block.builderlab.xyz>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Changes requested: one P2 recipient-policy bypass, detailed inline. Preserve the existing managed-agent restriction for this new entry point and add its eligibility/lifecycle regressions. No other material blocker found in the scoped Message, hidden-DM restore, status or NIP-05 review.

Reviewed head 1dcc1b015fe32c7854bb66dc9f2740720e1cdd54 against base/merge-base 8842b3ac05862e069ab0adf2f30e11a3af084042, with independent UI and status/trust lanes. A temporary mounted React probe used the real relay session, synthetic transport and signed profile/DM roster: the human control passed; the unowned-agent policy assertion failed after open and navigation succeeded. Production files were unchanged. Existing hosted required CI, Chromium/WebKit and DCO checks passed. No broad local rerun, live-relay write or native acceptance was performed.

Comment thread src/bundled/profiles/ProfilePanel.tsx Outdated
Known agents get the profile Message action only while this community's
ready native control manages them, matching New message. Availability
and activation both check session.agentChoices; humans are unchanged.

Co-authored-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: peon <9ac6794b000690b7e814eb1805ad32405d0bec7d52838de3a86cf967565dacc0@buzz.block.builderlab.xyz>
@kalvinnchau
kalvinnchau merged commit da41e24 into main Sep 24, 2026
19 of 21 checks passed
@kalvinnchau
kalvinnchau deleted the peon/profile-human-dm branch September 24, 2026 20:23
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.

2 participants