Skip to content

refactor(platform): converge itest sign-ups on signUpOrgMember - #3206

Merged
larryro merged 1 commit into
mainfrom
fix/itest-harness-signup-convergence
Sep 4, 2026
Merged

refactor(platform): converge itest sign-ups on signUpOrgMember#3206
larryro merged 1 commit into
mainfrom
fix/itest-harness-signup-convergence

Conversation

@larryro

@larryro larryro commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Why

services/platform/backend/integration-check.ts carried 22 hand-rolled copies of the sign-up sequence (POST /api/auth/sign-up/email → parse the user id → capture the cookie → INSERT INTO "member") beside the signUpOrgMember helper that #3198 introduced and converted five sites to. Structure-not-behaviour refactor: every remaining copy now goes through the shared helper. Same role, same org, same session semantics, same assertions — no lane asserts anything differently. Net −263 lines in the harness.

Sites converged (22)

13 → signUpOrgMember (a member/editor of the suite's org via the raw member row, as before): tasks-isolation read-only viewer, documents doc-reviewer (editor), document-write-guards member + editor, corpus-purge member, MCP member, conversations write-gate probe, TTS stranger, members email-lookup member, agent-secrets member, erasure member, audit read-gate probe, DSAR member.

9 → signUpUser (deliberately signed up WITHOUT joining the suite's org — the existing helper could not express these, so its sign-up half is now a sibling helper):

  • 2 cross-org attackers that go on to create their own org (tasks-isolation attacker, feedback rival);
  • 4 lanes whose POST /api/app/members join is itself under test — member-lifecycle outbox hints, bell-wire recipient (joined.status is asserted), board-move assignee, audit-surface member (the join lands an audit row). A raw member INSERT there would have removed the side effects those lanes observe, so they keep their API join and only the sign-up half converges;
  • the forced-password probe (account-only, no org at all);
  • the two lane-local signUp closures: checkAccountAuthzHardening (5 call sites; org create + members API are what it exercises) now delegates to signUpUser; checkOrganizationLifecycle (2 call sites) drops its closure.

Left alone (1)

  • checkAuthAndSse's primary sign-up. It is the sign-up issues session check (asserts the raw response status, cookie and user id) and creates the suite's shared user and org — not a throwaway copy.

Helper changes

  • signUpUser(base, label) split out of signUpOrgMember: same email/password/name scheme, returns { cookie, userId, email }; signUpOrgMember builds on it.
  • signUpOrgMember now also returns memberId (INSERT … RETURNING "id") so the two gate lanes that UPDATE "member" SET "role" … WHERE "id" between passes and DELETE the row at the end address it by id exactly as before, instead of hand-rolling m-conv-gate-… / m-audit-gate-… ids.
  • README harness doctrine names both helpers.

Display names (Iso ViewerItest iso-viewer) and email shapes (itest-<label>-<Date.now()>@example.com) change at the converged sites; no assertion references any of them (each literal occurred exactly once in the file). Three sites had deterministic emails and one an ON CONFLICT ("id") DO NOTHING on a hand-rolled member id — no-ops on the fresh per-run database.

Proof — backend:integration on a fresh throwaway tale-db + MinIO per run

run checks lanes FAIL
base dac9e71f0 (origin/main when branched) 460/461 131/131 webdav re-home (protocol + tree + locks + visibility on pg) — pre-existing
branch before rebase 460/461 131/131 same single FAIL
origin/main 34ccd23b2 (after #3203 #3200 #3204 #3199) 459/461 131/131 webdav re-home + messages: concurrent appends each take their own slot (see note)
branch rebased 7b7ed58f5 460/461 131/131 same single webdav re-home FAIL

Base vs branch: the ordered 461-entry check-name sequence and the PASS/FAIL sequence are byte-identical (diff of the extracted names/statuses is empty); every run reaches the final check — no RUN TRUNCATED.

Post-rebase: the ordered check-name sequences of origin/main and the rebased branch are identical (461 entries). Between the two bases, #3203 removed sandbox user-env CRUD (masked secrets, key validation) and #3204 added share links: snapshot carries no null blocked reason or error — 461 checks before and after. The extra FAIL on the origin/main run, messages: concurrent appends each take their own slot, is a concurrency race probe in the chat lane, outside this change's blast radius: it passed on the rebased-branch run that executed concurrently on the same machine (the two runs shared the CPU) and on both earlier runs. Its detail on the main run: messages: concurrent appends each take their own slot — appends=12, failed=2 (want 0), rows=10, distinctOrders=10 (want 12, no ties), contiguous=true.

Gates

bunx tsc --noEmit (services/platform) 0 · bunx oxlint --type-aware backend/integration-check.ts 0 · bunx oxfmt --check clean · bunx knip 0 (one pre-existing, unrelated config hint: cron-parser in ignoreDependencies).

Rebase / coordination

Rebased onto origin/main after #3203 merged (it removed the sandbox user-env lane from this same file): clean, no conflicts, the lane stays removed. No migrations.

The backend integration harness carried 22 hand-rolled copies of the
"POST /api/auth/sign-up/email, parse the user id, insert a member row"
sequence next to the shared helper #3198 introduced. Every copy now goes
through the helper, behaviour-preserving: same role, same org, same
cookie/userId flow, and no lane asserts anything differently.

- `signUpUser(base, label)` is split out of `signUpOrgMember` for the nine
  sites that deliberately sign up WITHOUT joining the suite's org: the two
  cross-org attackers that go on to create their own org, the four lanes
  whose `POST /api/app/members` join is itself under test (member outbox
  hint, audit row, `joined.status`), the account-only password probe, and
  the two lane-local `signUp` closures (authz hardening, org lifecycle).
- `signUpOrgMember` returns `memberId` (`RETURNING "id"`) so the two gate
  lanes that rewrite the role between passes and delete the member at the
  end keep addressing the row by id instead of hand-rolling one.
- Left alone: the suite's primary sign-up in `checkAuthAndSse` — it IS the
  "sign-up issues session" check and asserts on the raw response.

Net -263 lines in integration-check.ts; the README doctrine names both
helpers.
@larryro
larryro marked this pull request as ready for review September 4, 2026 06:38
@larryro
larryro merged commit 9405e6e into main Sep 4, 2026
23 checks passed
@larryro
larryro deleted the fix/itest-harness-signup-convergence branch September 4, 2026 06:57
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