Ships the user-visible friction fixes and the foundation for the v2
invite protocol. API wiring + CLI client + email UI ship in wave 2.
Meshes — shipped
- Drop global UNIQUE on mesh.slug; mesh.id is canonical everywhere
- Server derives slug from name; create form has no slug field
- Two users can freely name their mesh "platform"; no collision errors
- Migration 0017
Invites v1 — shipped (URL shortener, backward compatible)
- New invite.code column (base62, 8 chars, nullable unique index)
- createMyInvite mints both token + short code; returns shortUrl
- GET /api/public/invite-code/:code resolves short code to token
- New route /i/[code] server-redirects to /join/[token]
- Invite generator UI shows short URL; QR encodes short URL
- Advanced fields (role/maxUses/expiresInDays) collapsed under disclosure
- Migration 0018
Invites v2 — foundation (broker + DB only; API+CLI+Web wiring in wave 2)
- Broker: canonicalInviteV2, verifyInviteV2, sealRootKeyToRecipient
- Broker: POST /invites/:code/claim endpoint (atomic single-use accounting)
- Broker tests: invite-v2.test.ts (signature, expiry, revocation, exhaustion)
- DB: mesh.invite gains version/capabilityV2/claimedByPubkey columns
- DB: new mesh.pending_invite table for email invites
- Migration 0019
- Contract locked in docs/protocol.md §v2 + SPEC.md §14b
Consent landing — shipped
- /join/[token] redesigned: explicit role, inviter, mesh stats, consent
- New server components: invite-card, role-badge, inviter-line, consent-summary
- "Join [mesh] as [Role]" primary action (not just "Join")
Error surfacing — shipped
- handle() now parses {error} responses from hono route catch blocks
- onError fallback includes timestamp so handle() can match apiErrorSchema
- Real error messages reach the UI instead of "Something went wrong"
Docs
- SPEC.md §14b: v2 invite protocol
- docs/protocol.md: v2 claim wire format
- docs/roadmap.md: status
- .artifacts/specs/2026-04-10-anthropic-vision-meshes-invites.md
Deferred to wave 2/3
- API claim route wiring (packages/api)
- createMyInvite v2 capability generation
- Email invite mutation + Postmark delivery
- CLI v2 join flow (x25519 keypair + unseal)
- Web invite-generator email field + v2 display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
30 lines
994 B
TypeScript
30 lines
994 B
TypeScript
interface InviterLineProps {
|
|
inviterName: string | null;
|
|
}
|
|
|
|
export function InviterLine({ inviterName }: InviterLineProps) {
|
|
const initial = (inviterName ?? "?").trim().charAt(0).toUpperCase() || "?";
|
|
return (
|
|
<div
|
|
className="flex items-center gap-3"
|
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
|
>
|
|
<div
|
|
aria-hidden="true"
|
|
className="flex h-9 w-9 items-center justify-center rounded-full border border-[var(--cm-border)] bg-[var(--cm-bg-elevated)] text-[13px] font-medium text-[var(--cm-fg-secondary)]"
|
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
|
>
|
|
{initial}
|
|
</div>
|
|
<div className="flex flex-col leading-tight">
|
|
<span className="text-[11px] uppercase tracking-[0.16em] text-[var(--cm-fg-tertiary)]">
|
|
Invited by
|
|
</span>
|
|
<span className="text-[14.5px] font-medium text-[var(--cm-fg)]">
|
|
{inviterName ?? "the mesh owner"}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|