Skip to content

fix(join): read a pasted community DID as a DID, not a broken invitation - #347

Merged
stormer78 merged 1 commit into
mainfrom
worktree-join-paste-did
Sep 18, 2026
Merged

stormer78 merged 1 commit into
mainfrom
worktree-join-paste-did

Conversation

@stormer78

Copy link
Copy Markdown
Contributor

Found while running the vetting dry-run guide: pasting the community's DID on the join entry page answered "Pasted text is not valid JSON".

The bug

The two paste routes had drifted apart:

JSON {…} anything else
Bracketed paste (terminal) → invitation DID field
[Ctrl+V] (JoinPasteFromClipboard) → invitation → invitation → "not valid JSON"

The clipboard key handed its text to the invitation loader whatever it was. Its
own comment said "same validation as a bracketed paste", which had stopped
being true.

The fix

One apply_entry_paste on the component that owns the input, called by both
routes, so they cannot disagree again. A JSON object is an invitation; anything
else is the community's DID or agent name.

Ctrl+V now reads the clipboard where the input lives and applies the text
itself, so only the read failure still needs the loop —
JoinPasteFromClipboard becomes JoinClipboardFailed(String), which is all it
ever really carried. Reading the clipboard synchronously in a key handler
matches what the vetting panel already does for its copy keys.

The sniff is on the shape of the text, not on whether it parses. A DID never
opens a brace, and text that does open one and then fails to parse is a broken
invitation — which load_pasted_vic already reports as one, naming what is
wrong with it. Sniffing by "does it parse as JSON" would report a mangled VIC as
a malformed DID, which is the less useful of the two errors.

The page now leads with the community

The DID prompt and its input come first; the invitation block moves below the
input, still ahead of the examples.

This reverses part of issue #29, so the reasoning matters. The invitation led
the page while this was the only screen that mentioned invitations at all, and
one pasted here was easy to miss. What #29 actually caught was an affordance
that was dim, unnamed and last — and the named [Ctrl+V] row that fixed
that stays exactly where it can be seen. Since #342 the join lists the ways in
on the following step, where an invitation is offered counted and matched
against the community
, with a paste row of its own. Leading with it here buys
nothing now and pushes the DID prompt down the page.

The copy changed to match what it actually does: "Don't have the DID? … it names
the community, so it fills the DID in for you."

A regression the suite caught

Putting the invitation between the prompt and the input broke
the_input_keeps_its_row_across_states_and_widths — the prompt has to be the
last line above the input. That is why the block sits below the input rather
than merely after the prompt.

Testing

  • cargo fmt --all, cargo clippy --all-targets --all-features — clean
  • cargo test --all-features — all green
  • RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features — clean

The replaced ctrl_v_asks_for_the_clipboard_rather_than_typing asserted the old
action. It is now two tests:

  • ctrl_v_never_types_a_v — whatever the clipboard holds, the key itself never
    lands in the field. It deliberately asserts nothing about what was pasted:
    that depends on the machine's clipboard, and a test reading it would pass or
    fail on what the developer last copied.
  • a_pasted_did_goes_in_the_field_and_an_invitation_is_loaded — drives
    apply_entry_paste with text of its own: a DID and an agent name land in the
    field with no action sent, a JSON object is loaded as an invitation and does
    not overwrite what is being typed.

Not yet run against the live community — the guide run that found this is the
next thing to re-try it on.

`[Ctrl+V]` on the join entry page read the clipboard and handed whatever
it found to the invitation loader. Pasting the community's DID — the
commonest thing anyone pastes on that page — came back "Pasted text is
not valid JSON", while the identical text delivered as a bracketed paste
went into the field correctly, because that path sniffed for a leading
brace and the clipboard path did not. The two had drifted, and the
comment on the clipboard key still claimed they did the same thing.

Both now go through one `apply_entry_paste`, on the component that owns
the input: a JSON object is an invitation, anything else is the DID or
agent name. `Ctrl+V` reads the clipboard there and applies it, so only
the read *failure* still needs the loop — `JoinPasteFromClipboard`
becomes `JoinClipboardFailed(String)`, which is all it ever really was.

The sniff is on the shape of the text, not on whether it parses. A DID
never opens a brace, and text that does and then fails to parse is a
broken invitation — which `load_pasted_vic` reports as one. Sniffing by
"does it parse as JSON" would report a mangled VIC as a malformed DID.

The page also now leads with the community. The invitation block moves
below the input, ahead of the examples. It led the page (issue #29) while
this was the only screen that mentioned invitations and one pasted here
was easy to miss; what #29 actually caught was an affordance that was
dim, unnamed and last, and the named `[Ctrl+V]` row that fixed it stays.
Since the join learned to list the ways in, an invitation is offered
again on the following step — counted, matched against the community, and
with a paste row of its own — so leading with it here only pushed the DID
prompt down the page. Pasting one still fills in a DID you may not have,
which is what its copy now says.

The prompt stays the last line above the input: the invitation went
between them at first, and `the_input_keeps_its_row_across_states_and_widths`
caught it.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 requested a review from a team as a code owner September 18, 2026 20:25
@stormer78
stormer78 merged commit 8a6bc49 into main Sep 18, 2026
15 checks passed
@stormer78
stormer78 deleted the worktree-join-paste-did branch September 18, 2026 20:44
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.

1 participant