# @novelpad/outreach-review Human review queue for (org, grant) matches produced by the scoring pipeline in `packages/outreach-core`. A reviewer sees each pending match — organization, hero grant, total score, easy-win flag — and approves or rejects it. Approved matches are picked up downstream and synced into Apollo sequences. ## Auth **There is no authentication in this app, by design.** It is a tiny internal tool intended to run behind: - Google IAP (Identity-Aware Proxy) in any hosted environment, or - `localhost` only, for local development Do **not** add `better-auth` (or any other auth library) to this workspace. If this app ever needs to leave an IAP-fronted network, that's a deliberate follow-up decision, not something to bolt on ad hoc here. ## Development ``` yarn dev # react-router dev yarn build # react-router build yarn start # serve the production build yarn typecheck # react-router typegen && tsc --noEmit ``` Requires `DATABASE_URL` pointing at the outreach Postgres instance (see `packages/outreach-core`). Optional: `PG_POOL_MAX`, `PG_CONNECTION_TIMEOUT_MS`. ## Data contract This app is a thin consumer of `@novelpad/outreach-core`. It assumes the following exports (server-side query/action functions live under the `./server` subpath, matching the `packages/core` convention in novelpad-desktop): ```ts // @novelpad/outreach-core export const schema: /* drizzle schema */; export type NpOutreachDatabase = /* PgDatabase<..., typeof schema> */; export interface PendingReviewMatch { id: string; orgName: string; heroGrantTitle: string; totalScore: number; isEasyWin: boolean; } export type MatchReviewDecision = 'approved' | 'rejected'; // @novelpad/outreach-core/server export function serverListPendingReviewMatches( db: NpOutreachDatabase, ): Promise; export function serverSetMatchReview( db: NpOutreachDatabase, matchId: string, decision: MatchReviewDecision, ): Promise; ``` If `packages/outreach-core`'s matches domain (`src/matches/queries`, `src/matches/actions`) lands with different names or a different `PendingReviewMatch` shape, update `app/db.server.ts` and `app/routes/_index.tsx` to match rather than reshaping data client-side.