eleven / ocho Public

web: a dead invite link redirects signed-in members to the chat (#598)

An existing member clicking a stale invite (an old link in a chat message,
email, or the one-time setup link they already used) got "This invite has
been used or is no longer valid. Ask for a new one." — an error about an
invite they don't need. Check for a live session first and go to the chat;
liveSession's definitive-403 rule keeps the honest error for tokens from a
reset instance, and the native add-chat embed keeps the join flow.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 203ce1ccd055ab3e6ee1b4cd46446e55baba5709 parent 8334e4a
2 files changed, +12 −0
  • changelog/2026-07-10-expired-link-goes-home.md +4 −0
  • web/static/join.js +8 −0
diff --git a/changelog/2026-07-10-expired-link-goes-home.md b/changelog/2026-07-10-expired-link-goes-home.md
new file mode 100644
index 0000000..60f53be
--- /dev/null
+++ b/changelog/2026-07-10-expired-link-goes-home.md
@@ -0,0 +1,4 @@
+🤖 Clicking an old invite link when you're already signed in on this device
+now takes you straight to your chats. Before, it showed "this invite has been
+used" — an error you couldn't do anything with, about an invite you didn't
+need.
diff --git a/web/static/join.js b/web/static/join.js
index 70e147b..21ad2bb 100644
--- a/web/static/join.js
+++ b/web/static/join.js
@@ -77,6 +77,14 @@ async function start() {
return showError("Couldn't reach the server. Try again.");
}
if (!info.ok) {
+ // A dead link in an existing member's hands is just a stale bookmark —
+ // they're already in, so go to the chat instead of an error card telling
+ // them to ask for an invite they don't need. liveSession (not a raw
+ // localStorage read) so a token from a reset instance still falls through
+ // to the honest error. Embed keeps the error: the native add-chat webview
+ // owns navigation, and its shell expects a join, not a redirect.
+ const existing = window.__lchatEmbed ? null : await liveSession();
+ if (existing) return location.replace("/");
return showError("This invite has been used or is no longer valid. Ask for a new one.");
}