Stands up packages/api so the swipe path stops trusting its caller, and puts the auth library behind an interface we own. - packages/api: tRPC v11 with a Session type WE define, not one re-exported from an auth library. Swapping providers means rewriting one SessionResolver, not touching a router. - Procedure layers: public / protected / client / pro / verifiedPro / admin. Admin routes 404 rather than 403 so they cannot be probed. - deck router replaces the untrusted server action. Ownership is checked on every operation and returns NOT_FOUND, never FORBIDDEN, so job ids cannot be enumerated. 23 tests, mostly authorization. - packages/storage: presigned direct-to-R2 uploads. The server picks the key, so a caller can only write under their own user id. 14 tests. Three defects found and fixed: - The lazy db Proxy failed drizzle's is(db, PgDatabase) because it did not trap getPrototypeOf. Auth adapters dispatch on exactly that check, so this would have failed at runtime inside third-party code. Fixed and pinned with a regression test. - The open-request cap was a read-then-write race: concurrent swipes could both read 4 and both insert. Now one transaction with the job row locked. The cap is checked before the tombstone is written, so a rejected swipe leaves no trace and the card stays on the deck. - superjson was configured in two of the three required places. Without the QueryClient dehydrate/hydrate pair, RSC-prefetched data arrives as a raw envelope with no type error to warn you. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
22 lines
721 B
TypeScript
22 lines
721 B
TypeScript
import { config as loadEnv } from 'dotenv';
|
|
import type { NextConfig } from 'next';
|
|
|
|
// The monorepo keeps one .env at the root; Next only looks in the app directory.
|
|
loadEnv({ path: '../../.env' });
|
|
|
|
const config: NextConfig = {
|
|
reactStrictMode: true,
|
|
// The workspace packages ship TypeScript source, not build output.
|
|
transpilePackages: ['@linkder/api', '@linkder/db', '@linkder/shared', '@linkder/storage'],
|
|
images: {
|
|
remotePatterns: [
|
|
{ protocol: 'https', hostname: 'picsum.photos' },
|
|
{ protocol: 'https', hostname: '**.r2.dev' },
|
|
],
|
|
},
|
|
// postgres-js opens raw sockets; it must not be bundled into the server chunk.
|
|
serverExternalPackages: ['postgres'],
|
|
};
|
|
|
|
export default config;
|