Files
searcher/.codex/skills/wallora-searcher/references/architecture.md
T
2026-06-06 00:49:07 +08:00

97 lines
5.7 KiB
Markdown

# Wallora Searcher Architecture Reference
## Surfaces And Roles
The project has three user-facing surfaces:
- Public API: available to external users. Use JWT login/authorization for protected API access. Keep contracts documented in `swagger.yaml`.
- Admin: available only after account/password login. Use NextAuth-backed sessions to persist admin login state and gate admin features.
- Public website: available to anyone on the public internet. Optimize pages for SEO, metadata, crawlability, and public performance.
Keep these surfaces separate in routing, middleware, authorization helpers, and mental model.
## Route Boundaries
Prefer clear route groups as the app grows:
- Public website: `app/(site)/...`
- Admin UI: `app/(admin)/admin/...`
- Protected admin UI: `app/(admin)/admin/(protected)/...`
- Public API: `app/api/...`
- Auth endpoints: `app/api/auth/...` for NextAuth
If the existing tree does not yet use route groups, introduce them only when it makes the current change clearer.
## Authentication And Authorization
- Public API authorization: validate JWTs explicitly for protected API routes. Define who issues the token before implementing token verification.
- Current app-user JWTs are issued by `/api/v1/auth/login` and `/api/v1/auth/register`, signed with `APP_JWT_SECRET` or `AUTH_SECRET`, and validated by server-only helpers before accessing `/api/v1/users/me/...`.
- Disabled app users should not be able to log in or use existing Bearer tokens because token validation reloads current `wg_app_users.status`.
- Admin authorization: use NextAuth account/password login and session checks. Do not rely on public API JWT logic as the admin session source.
- Only `/admin/login` is public under the admin surface. All other `/admin` pages need middleware/proxy protection and server-side `auth()` checks, preferably via a protected route-group layout.
- Server code must keep secrets server-only. Never expose service-role Supabase keys, Aliyun OSS secrets, NextAuth secrets, or JWT signing secrets in `NEXT_PUBLIC_*`.
- Keep authorization decisions close to the server boundary: route handlers, server actions, middleware, or server-only helpers.
## Data Storage
Use Supabase for application data.
- Prefix project-owned tables, indexes, triggers, and helper functions with `wg_` when practical.
- Enable and design RLS for tables exposed through Supabase APIs.
- Do not use user-editable metadata claims for authorization decisions.
- Model admin roles and API consumer permissions in trusted tables or trusted auth metadata.
- Verify Supabase behavior against current documentation before implementing schema, RLS, or auth-sensitive behavior.
- Use service role credentials only in server-only code, one-shot scripts, cron workers, or protected internal route handlers.
- Treat raw gallery rows as admin data. Public photo APIs should return picked rows only.
- App-facing gallery list/detail endpoints may accept an optional Bearer app-user JWT to add user-specific fields such as `isFavorited`; anonymous responses must still work.
- Keep picked state and OSS mirror metadata on `wg_gallery_photos`; use collections tables to group picked photos into public sets.
- Admin collection writes should validate that every collection item references a picked photo.
- Public collection APIs should filter on `is_published = true` and keep collection photo pagination compatible with infinite scroll.
- App user favorites should accept picked photos only, and preferences/download preferences should be stored as JSON in `wg_user_settings`.
- Keep phone and WeChat identity support as additive fields on `wg_app_users`; do not split them into separate user tables unless provider-specific complexity requires it later.
## Image Storage
Use Aliyun OSS for image files.
- Store files in OSS buckets; store metadata such as object key, URL, owner, MIME type, size, visibility, and related entity in Supabase.
- Prefer server-side signed upload or server-mediated upload for private/admin flows.
- Avoid placing OSS access keys in browser-exposed code.
- Existing OSS env support accepts `OSS_REGION`, `OSS_ACCESS_KEY_ID`, `OSS_ACCESS_KEY_SECRET`, `OSS_BUCKET`, and either `OSS_PUBLIC_URL` or `OSS_PUBLIC_BASE_URL`.
- Decide whether each image class is public, signed, or private before generating URLs.
## UI System
Use shadcn/ui as the base UI layer.
- Initialize and inspect shadcn project config before adding components.
- Use the project package runner: `pnpm dlx shadcn@latest ...`.
- Prefer existing shadcn components before writing custom controls.
- Use semantic tokens and component variants instead of raw color overrides.
- Compose forms, tables, dialogs, sheets, empty states, loading states, and feedback with shadcn primitives where available.
## SEO Website Pages
For public website pages:
- Use server-rendered pages by default.
- Keep page-level metadata accurate with Next.js metadata APIs.
- Use semantic HTML, crawlable content, canonical URLs where needed, and fast-loading assets.
- Avoid hiding important public content behind client-only rendering.
## API Documentation
Maintain `swagger.yaml` for public API contracts.
- Update it whenever API endpoints, auth requirements, request schemas, response schemas, status codes, or error formats change.
- Keep operation IDs stable and descriptive.
- Document JWT requirements per route instead of assuming all routes share the same auth behavior.
- Treat generated examples as contract examples, not placeholders.
## Scheduled Jobs
- Do not assume Vercel Cron. This project is not planned for Vercel.
- Prefer a one-shot script that can be called by crontab, PM2, Docker, or another scheduler.
- Keep scheduled routes protected with a secret when an HTTP trigger is useful.
- Never rely on `setInterval` inside a Next.js request/serverless process for durable jobs.