Skip to content

test(e2e) + fix(marketing): the social Messages surface e2e — and the two DM bugs it caught - #707

Merged
jacoby149 merged 1 commit into
devfrom
test/social-e2e-messages
Aug 28, 2026
Merged

test(e2e) + fix(marketing): the social Messages surface e2e — and the two DM bugs it caught#707
jacoby149 merged 1 commit into
devfrom
test/social-e2e-messages

Conversation

@jacoby149

Copy link
Copy Markdown
Owner

What

The social-e2e lane's Messages bite: e2e/tests/social-messages.spec.ts — API floor (DM group contract + CRUD, deterministic DM group ID, I3 anti-test) + browser gauntlet (two-user DM round-trip through the real app: A composes to B → B receives → B replies → A's reload sees the reply, [social-dms] log sequence on both sides).

The two bugs it caught (fixed in-lane)

  1. The DM surface was broken end to end. dms.ts derived the DM group as web10.app/groups/{first}/dm-{second} (the KB's well-known shape) and added members with provider-qualified keys (web10.app/users/{username}). Neither can exist: POST /v3/groups/create derives the group_id from the caller's token ({provider}/groups/users/{creator}/{name} — the well-known shape is only creatable by direct DB insert, like the boot-time discover group), and the node's user key is the bare username — so the provider-qualified member keys never matched the real users, the recipient was never a member, and every receive 403'd. Fix: the deterministic identifier is the group NAME dm-{sorted} (the messages-demo findDmGroup reference pattern) — both parties find the group by name suffix in their own group list; member keys are bare usernames; listConversations resolves the other party from membership (the name is ambiguous — usernames may contain dashes) with a member_count === 2 guard; readDms on a not-yet-existing conversation returns [] instead of 403.
  2. isMe never matched. sender_provider derived from a bare author_key is the literal string web10 (extractProvider's fallback), never the node's provider, so the provider-qualified isMe comparison never matched in any environment — own messages rendered as the other party's (left-aligned, no edit/delete menu). Now username-based (v3 DMs are same-node): DmsScreen bubble, MailView thread + formatFromTo, CrmView, and classifyThread/replyAllTargets.

Out of lane (notes in .context/social-e2e-messages-handoff.md)

  • groups.ts still exports the broken dmGroupId/ensureDmGroup; the same well-known-shape mismatch affects closeFriendsGroupId/ensureCommunity (the followers half was just fixed in fix(social) + test(e2e): the follows surface works + the groups e2e floor/gauntlet #703 with the provider-aware ID pattern).
  • KB drift: db/clickhouse.md's user_blacklist/group_blacklist DDL is stale (code expects updated_at+deleted; a fresh CH built from the KB DDL 500s on every group read — the read path anti-joins both). And social-contracts.md's DM Group ID column is uncreatable via the API.

Verification

  • Spec 4/4 green (API floor ×3 + gauntlet), run against an isolated e2e stack (the shared e2e compose project is contended by the sibling lanes — see the handoff note for the topology: isolated project + static nginx router + host-published port, the CI topology, because Chromium maps *.localhost → 127.0.0.1 for page navigations).
  • tsc -b && vite build clean; 200 web10-social unit tests green; spec file tsc-clean (the pre-existing exporter/gauntlet/messages-demo tsc errors are untouched).
  • Screenshots re-captured (chat/mail/crm/settings, desktop + 375px) — green run per the temporary no-PNG-read override in the harness README.

@jacoby149
jacoby149 merged commit 6c10092 into dev Aug 28, 2026
7 checks passed
jacoby149 added a commit that referenced this pull request Aug 28, 2026
jacoby149 added a commit that referenced this pull request Aug 28, 2026
…ation lives (3.25.1) (#706)

* docs(kb): ad dissemination — design-under-discussion on where the curation lives (3.25.1)

Operator reframe: the ad should be a property of the post read (opted-in
posts come back with their curated ad, curated from the author's catalog per
the author's preference), not a client-side computation — 'more clickhousey',
a platform capability any app gets for free.

The doc (ads-dissemination.md) lays out the reframe, the strong argument for
it (the read already does read-time projections — media URLs, HLS manifest
minting, power-mean ranking), the stateful-curation wall (a stateless query
can't hold per-viewer/per-session state), the three options (client-side /
data-layer / hybrid), and the open questions. Not a decision — the KB-side
starting point for the discussion. ads.md Dissemination section points to it.

* docs(kb): ad dissemination — converged design: per-doc ad_preference + catalogs + love-based curation (3.25.1)

The design converged: every document has an ad_preference (which catalog to
curate from + a mode + a target for pinned); a user has multiple ad catalogs
(the Spotify-playlist model — an ad in several); on read, ClickHouse curates
the ad from the chosen catalog per the mode and serves doc + ad together.

The 'love' idea dissolves the statefulness wall: least-loved (round_robin) /
most-loved (greedy) is a property of the data, not the viewer — a
deterministic function of current engagement, the same ref-count machinery
power-mean ranking already reads in SQL. No per-viewer state, no
write-on-read.

Added the mermaid diagram, the ClickHouse feasibility read (window-function +
join, the house pattern), the value prop, and 11 serious open questions.
curateAds (3.26.0) is largely superseded.

* chore(changelog): renumber ad-dissemination entry to 3.25.2 (3.25.1 taken by merged social-e2e follows fix)

* docs(kb): ad dissemination — signal×strategy enums, node-level ad density, authenticator Ads tab, greedy reframed (3.25.2)

Converged further:
- The mode is a signal × strategy pair (expandable: reaction round robin,
  comment round robin, you name it) + a scope enum (global / per_viewer).
- A node-level ad density setting — the % of posts that get an ad at all, the
  operator's fatigue throttle (deterministic pseudo-random roll in the query).
- The authenticator gets a new Ads tab (ads upload + catalog making), which
  makes catalogs first-class (leaning a catalog doc).
- Greedy reframed as 'show my proven best' (complementary to round_robin's
  'give everything a fair shot'); the cold-start is the distinction, not a bug.

* chore(changelog): renumber ad-dissemination entry to 3.25.3 (3.25.2 taken by merged Messages e2e #707)

* chore(changelog): renumber ad-dissemination entry to 3.26.1 (above merged feed spec 3.26.0 #702)
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