Skip to content

Feat/add gh waitlist#81

Merged
ripgrim merged 3 commits into
mainfrom
feat/add-gh-waitlist
Jul 15, 2026
Merged

Feat/add gh waitlist#81
ripgrim merged 3 commits into
mainfrom
feat/add-gh-waitlist

Conversation

@ripgrim

@ripgrim ripgrim commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Checklist

Notes for reviewers

dansholds and others added 3 commits July 14, 2026 21:46
Replace the email-only waitlist with an admin-reviewed access queue:

- accessStatus/accessReviewedAt/accessReviewedBy/waitlistedAt on user
  (drizzle schema + better-auth additionalFields, server-only input)
- new signups land pending; signups-paused block removed; prior email
  waitlist entries flagged with their original join date
- approvedProcedure tRPC gate (also on org/admin procedures) behind
  ACCESS_GATE_ENABLED, with DB re-check for stale sessions
- accessRequests admin router: list/approve/reject/bulkApprove + lazy
  GitHub metadata; Access Requests table in _admin
- /queue status page for pending users, distinct rejected copy;
  useAccessGate client redirect in the app shell
- packages/email: @opencoredev/email-sdk client (Resend, retries) and
  approval template; access/approved Inngest job with two-layer
  idempotency so bulk-approve retries never double-send
- backfill + waitlist migration-email scripts; landing/login CTA copy
  swapped to request-access framing
The marketing landing page lives in the tripwire-landing repo now. The
app root just routes by session: signed-in users to /home, everyone
else to /login. Removes components/layout/landing (header, waitlist
form, faulty-terminal shader, space-invaders easter egg).

The waitlist tRPC router and table are intentionally untouched — they
stay live through the email-migration claim window.
@comp-ai-code-review

comp-ai-code-review Bot commented Jul 15, 2026

Copy link
Copy Markdown

Comp AI code review failed. Comment /review to retry.

A sandbox with the name 'cs-review-cmrmbrini00a904jma46s0i4e' already exists for this project. Use GET /sandboxes/:name to resume it or delete it first.

Posted by Comp AI Code Reviews.

@ripgrim
ripgrim merged commit f544e81 into main Jul 15, 2026
4 of 8 checks passed
@github-actions

Copy link
Copy Markdown

React Doctor found 11 new issues in 5 files · 5 errors & 6 warnings · score 40 / 100 (Critical) · 1 fixed · vs main

Errors

6 warnings

src/integrations/trpc/routers/access-requests.ts

  • ⚠️ L48 Sequential independent awaits server-sequential-independent-await

src/routes/_admin/admin/access-requests.tsx

  • ⚠️ L350 Locale/timezone formatting during render no-locale-format-in-render

src/routes/oauth/popup-callback.tsx

  • ⚠️ L176 Multiple components in one file no-multi-comp
  • ⚠️ L185 Multiple components in one file no-multi-comp
  • ⚠️ L191 Multiple components in one file no-multi-comp
  • ⚠️ L199 Multiple components in one file no-multi-comp

Reviewed by React Doctor for commit dd28364. See inline comments for fixes.

.from(userTable)
.where(where)

const rows = await db

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/server-sequential-independent-await (warning)

This await doesn't use the previous result, so your users wait twice as long for nothing.

Fix → These two awaits don't depend on each other. Wrap them in Promise.all([...]) so they run at the same time.

Docs

),
})

const accountAge = useMemo(() => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-hooks-js/preserve-manual-memoization (error)

This component misses React Compiler's automatic memoization & re-renders more than it should: Compilation Skipped: Existing memoization could not be preserved. Rewrite the flagged code so the compiler can optimize it.

Fix → React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was meta.data.accountCreatedAt, but the source dependencies were [meta.data?.accountCreatedAt]. Inferred different dependency than source.

Docs

</div>
{row.waitlistedAt ? (
<span
title={`On the email waitlist since ${new Date(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-locale-format-in-render (warning)

This can cause a hydration mismatch because toLocaleDateString() formats with the server's locale and timezone during server rendering but the user's in the browser. Format it in a post-mount useEffect, or pass an explicit locale and timeZone.

Fix → Format locale/timezone-dependent values in a post-mount useEffect + state, or pass an explicit locale and timeZone so the server and the browser render the same text. Only runs on SSR-capable projects.

Docs

* redirect, or COOP severed window.opener — it falls back to navigating in
* place (there's no popup to close in that case).
*/
export const Route = createFileRoute("/oauth/popup-callback")({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/tanstack-start-route-property-order (error)

Ordering route property "validateSearch" after "headers" breaks type inference.

Fix → Follow the route property order because TanStack Router's type inference depends on earlier properties feeding later ones.

Docs

if (error) {
done.current = true
if (postToOpener({ type: MESSAGE_TYPE, status: "error" }, targetOrigin)) {
setView({ kind: "error" })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-hooks-js/set-state-in-effect (error)

This component misses React Compiler's automatic memoization & re-renders more than it should: Calling setState synchronously within an effect can trigger cascading renders. Rewrite the flagged code so the compiler can optimize it.

Fix → Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:

  • Update external systems with the latest state from React.
  • Subscribe for updates from some external system, calling setState in a callback function when external state changes.

Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).

Docs

)
}

function Heading({ children }: { children: React.ReactNode }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-multi-comp (warning)

This file declares several components, so each component is harder to find, test, and change.

Fix → Move secondary components into their own files so each component stays easier to find, test, and change.

Docs

)
}

function Body({ children }: { children: React.ReactNode }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-multi-comp (warning)

This file declares several components, so each component is harder to find, test, and change.

Fix → Move secondary components into their own files so each component stays easier to find, test, and change.

Docs

)
}

function CloseButton() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-multi-comp (warning)

This file declares several components, so each component is harder to find, test, and change.

Fix → Move secondary components into their own files so each component stays easier to find, test, and change.

Docs

* threading through the opener origin so the closer knows exactly which window
* (and origin) to notify. This is standard OAuth machinery, hence /oauth/*.
*/
export const Route = createFileRoute("/oauth/waitlist")({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/tanstack-start-route-property-order (error)

Ordering route property "validateSearch" after "headers" breaks type inference.

Fix → Follow the route property order because TanStack Router's type inference depends on earlier properties feeding later ones.

Docs

import { useTRPC } from "#/integrations/trpc/react"
import { buildSeo, formatPageTitle, PRIVATE_ROUTE_HEADERS } from "#/lib/seo"

export const Route = createFileRoute("/queue")({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/tanstack-start-route-property-order (error)

Ordering route property "head" after "headers" breaks type inference.

Fix → Follow the route property order because TanStack Router's type inference depends on earlier properties feeding later ones.

Docs

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