Skip to content

In-file cleanup: posts, registration, organizations (backend campaign 9) - #98

Closed
theobong wants to merge 4 commits into
chore/backend-campaign-08-inplace-b04-b06from
chore/backend-campaign-09-inplace-b07-b09
Closed

theobong wants to merge 4 commits into
chore/backend-campaign-08-inplace-b04-b06from
chore/backend-campaign-09-inplace-b07-b09

Conversation

@theobong

Copy link
Copy Markdown
Member

What changed

A behavior-neutral cleanup inside the files of three areas: posts, the feed, follows, notifications and legal documents; host registration, tickets, questions, waitlist and check-in; organizations, event teams and event pages. The 2,854-line registration repository and the 1,979-line organization repository are split by concern into files in the same folder, behind the same factories. Large functions are split into named helpers, repeated code is shared, magic values are named, and dead code and needless exports are removed. Nothing a user sees should change.

Before you start

Verify

Nothing new to verify: every step below is a regression check.

Regression

Posting, liking, reposting and following — [Web] [Mobile]

  1. A: on Home, click "Share an update with your neighborhood...", type text and click "Post" — Expect: the post tops the feed
  2. B: click "Like" on it — Expect: the count goes up and stays after a reload
  3. B: click "Repost", then "Repost" in the menu — Expect: B's feed shows the repost and the menu now offers "Undo repost"
  4. B: open A's profile and click "Follow" — Expect: the button reads "Following"
  5. A: open "Notifications" — Expect: " started following you."

Registering with tickets and questions, and the waitlist — [Web] [Mobile]

  1. A (web): on the event's "Tickets" tab click "Add a ticket type" with capacity 1 and the waitlist on, save; click "Add a question", mark it required, save — Expect: "Questions saved"
  2. B: open the event, pick the ticket, leave the question empty and click "Register" — Expect: "Please answer the required questions."
  3. B: answer it, accept the terms and click "Register" — Expect: "You're registered." and "View ticket"
  4. C: open the full event and click "Join the waitlist" — Expect: "You're on the waitlist." and position 1

Check-in and the roster — [Web] [Mobile]

  1. B: click "View ticket" — Expect: a QR code with the ticket code below it
  2. A (web): open the "Check-in" tab, type B's code and click "Check in" — Expect: "Checked in"; a second try says "Already checked in"
  3. A (mobile, on event day): "Host dashboard", then "Scan a ticket", scan B's code — Expect: "Checked in"
  4. A (web): open the "Attendees" tab and filter to checked in — Expect: B is listed

Organization invite — [Web]

  1. A: open the host area, the organizations switcher, then "New organization"; fill the name and handle and click "Create organization" — Expect: "Organization created"
  2. Open Members, invite by email with B's address and click "Send invite" — Expect: "Invitation sent" and an email for B
  3. B: open the email link, sign in and click "Accept invitation" — Expect: "You joined " and B is listed under Members

Event team invite — [Web] [Mobile]

  1. A: "Host dashboard", "Team", then "Invite"; choose a handle, type B's handle, pick co-host and click "Send the invite" — Expect: "Invite sent" and a pending row
  2. B: open your profile and accept the invitation — Expect: B's event page shows "You're co-hosting"

Editing the event signup page — [Web]

  1. A: open the event's "Signup page" tab and type a page address — Expect: "That address is free."
  2. Add a block and click "Save" — Expect: "Page saved"
  3. Click "Publish" and open civfix.dev/e/ — Expect: "Page published" and the public page shows the block

Findings addressed

Campaign PRs 7 to 10: the LOCAL DUP, READ and DEAD ledger findings for chunks B07 to B09, plus local magic values, large-function splits and un-exports.

  • B07: BE-DEAD-032; BE-DUP-034, 036, 040, 041 (partly); BE-READ-030 (partly), 031, 032, 035.
  • B08: BE-DEAD-034, 035, 038; BE-DUP-042, 043, 044, 048; BE-READ-036, 037, 038, 039, 040, 044, 045.
  • B09: BE-DEAD-042; BE-DUP-054, 057, 058; BE-READ-047, 048, 049, 050, 051 (local part), 053.

Largest splits: the registration repository into load, ticket types, questions, register, roster, waitlist, check-in and pages files, with registerIn in steps on the same transaction and statement order; the organization repository into rows, profile, members, verification, admin and invites files, with invite acceptance in steps under the same lock order; post creation and feed hydration; the five post-activity notifiers into one table with the same keys and dedupe choices.

Decisions for the reviewer

  • SQL moved between files inside each repository folder. The brief for these PRs keeps SQL where it is (moving it into repositories is PR 11), but the chunk targets asked for these two repository splits. Every statement keeps its text, parameters, order and transaction scope; three statements rebuilt from shared fragments send different whitespace only. The transcripts, which compare whitespace-normalized text, are identical.
  • An adversarial review compared all 44 registration repository methods and every organization repository method before and after; it found no behavior, lock-order or query change.
  • assertSlugAllowed takes an optional message so the page address keeps its own "that address is reserved" text.
  • Kept although only tests use them: the registration waitlist type probe, the ticket token verifier, the organization roleOf and pending-invite count, the team standing factory (now also used by its route), and several notification helpers.
  • The in-memory registration repository ignores the roster sort, and its checked-in and no-show filters skip a status check the database version applies. Unchanged here; logged as a test-double follow-up.
  • Types that appear in an exported function or type stay exported (DECISIONS-PENDING D-151).

User-visible copy changes

None. The invite emails and notification still say "expires in 14 days", now driven by the same constant as the expiry.

Tests changed

None. No test file was edited.

Verification

  • Every commit typechecks on its own (api and media worker).
  • At this branch: pnpm lint, prettier check, check:sql clean; api unit suite by explicit path 428 files, 7116 passed, 3 skipped; media-worker unit 300 passed, 2 failed (the known arm64 ffprobe helper issue fixed in Backend test safety net: SQL transcripts, CSRF pairing, authz and characterization tests #92).
  • The offline SQL transcripts of all repository cases are identical to the parent branch.
  • CI runs only on PRs based on main, so it starts here when the PRs below merge and GitHub retargets this one to main.

Staging checks

  • https://api.civfix.dev/readyz answers ready after the deploy (no migration in this PR).
  • The registration, waitlist and check-in steps above (they run the split repository).

Not covered

  • Scanning a ticket on mobile only works on event day; the web code entry covers the same check-in path.
  • Organization verification (document upload and operator review) is not in the steps.

🤖 Generated with Claude Code

@byteful
byteful added this pull request to stack #122 September 24, 2026 17:53
@byteful byteful closed this Sep 24, 2026
@byteful
byteful deleted the chore/backend-campaign-09-inplace-b07-b09 branch September 24, 2026 20:13
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.

2 participants