# Allapp Project Context This file is a compact project memory for future Codex chats. Read it first when working in `D:\workspace\code\app`. ## Workspace - Root: `D:\workspace\code\app` - Git repository root: `D:\workspace` - Backend: `app-go` - Frontend: `app-rn` - Local database memo: `db.local.yml` - Treat config files as sensitive. Some local config files may contain real credentials. ## Product Mental Model Allapp is shaped more like a mini-program platform than a single linear mobile app. There is a main shell for the family/personal space, and feature modules behave like small apps inside it. The frontend owns most product flow and business behavior. The backend is deliberately thin and generic, acting mostly as auth, file storage, ID generation, and database access. High-level model: ```text Allapp main shell ├── Home / Chat / Tools / My ├── Auth and family/space management └── Sub-apps ├── Finance │ ├── Home │ ├── Add record │ └── Analysis └── Clothes matching └── Planned/listed, route not implemented yet ``` Important naming note: - The product often uses "family" and "space" as the same concept. - Database tables use `b_family` and `b_family_member`. - Main tab config currently includes `/space`, but there is no matching page yet. ## Backend: app-go Tech stack: - Go - Fiber v3 - pgx PostgreSQL client - JWT - Viper config - Zap logging - S3/RustFS file storage - QQ/WeChat login and binding - Snowflake-style unique ID generator Important files: - Entry: `app-go/cmd/app/main.go` - Bootstrap: `app-go/internal/bootstrap/app.go` - Server: `app-go/internal/bootstrap/server.go` - Routes: `app-go/internal/router/router.go` - Config type: `app-go/internal/config/config.go` - Request binding/validation: `app-go/internal/httpx/request.go` - Response shape: `app-go/internal/httpx/response.go` - Auth middleware: `app-go/internal/middleware/auth.go` - Generic DB access: `app-go/pkg/db/*` Bootstrap flow: ```text config -> logger -> S3 client -> Postgres pool -> db.Init -> unique ID -> JWT -> WeChat client -> Fiber server ``` API base path comes from config and is currently: ```text /app ``` Important endpoints: ```text POST /app/auth/login/qq POST /app/auth/login/wechat POST /app/bind/qq POST /app/bind/wechat POST /app/data/loadData POST /app/data/loadDataBySql POST /app/data/saveData POST /app/data/getUniqueId POST /app/s3/upload POST /app/s3/delete ``` Backend architecture notes: - `loadData` accepts a table/view name, selected columns, condition string, order string, and args. - `loadDataBySql` accepts raw SQL and args. - `saveData` accepts batches of inserts, updates, and deletes by table name/key field. - Insert/update helpers add audit fields for most tables via `applyMetaFields`. - `Token` header is parsed by `middleware.Auth()` and stores `user_id` in context. - There are no explicit database foreign keys in the inspected schema; relationships are enforced by code and naming conventions. Security/architecture caution: - The generic data API is very flexible but risky. - Table names, columns, conditions, ordering, and raw SQL can come from the frontend. - If this moves toward production, prioritize server-side table/field whitelists, ownership checks, and removing or restricting raw SQL. Validation notes: - `BindAndValidate` validates structs with `go-playground/validator`. - It skips validation for slices. - `GetUniqueIdReq.Count` currently uses a `binding` tag, not a `validate` tag, so its min/max rules may not run. ## Frontend: app-rn Tech stack: - Expo 55 - React Native 0.83 - React 19 - Expo Router - Zustand - Alova with Axios adapter - HeroUI Native - Uniwind / Tailwind-style classes - Lucide React Native icons - QQ/WeChat native login plugins Important files: - Package: `app-rn/package.json` - App config: `app-rn/app.json` - Root layout: `app-rn/src/app/_layout.tsx` - Startup redirect page: `app-rn/src/app/index.tsx` - Request wrapper: `app-rn/src/request/index.ts` - API methods: `app-rn/src/request/api.ts` - User store: `app-rn/src/store/user.ts` - Family store: `app-rn/src/store/family.ts` - Finance store: `app-rn/src/store/finance.ts` - Main shell layout: `app-rn/src/layouts/AppLayout.tsx` - Module shell layout: `app-rn/src/layouts/ModuleLayout.tsx` - Shared tabbar: `app-rn/src/components/layout/tabbar.tsx` - App/module list config: `app-rn/src/configs/pages.ts` Frontend/backend contract: - Frontend reads `EXPO_PUBLIC_API_URL`. - Requests use Alova with Axios adapter. - Auth token is sent in a custom `Token` header. - Login APIs are whitelisted in the request wrapper. - Backend response shape: ```ts { code: number; message: string; data: unknown; track_id?: string; } ``` Response codes: ```text 1000 success 1001 unauthorized/token expired 2000 business error 3000 system error ``` State: - `user-storage`: persisted user token/id/nickname/avatar. - `family-storage`: persisted current family id. - Finance categories are in memory only and loaded by the finance module layout. Startup flow: ```text / index ├── no local token -> /auth/login ├── token exists but user check fails -> /auth/login ├── token exists but no family -> /family/entry └── token exists and family exists -> /(tabs)/home ``` ## Frontend Route Structure Expo Router tree: ```text src/app ├── _layout.tsx ├── index.tsx ├── +not-found.tsx ├── auth │ └── login.tsx ├── (tabs) │ ├── _layout.tsx │ ├── home/index.tsx │ ├── chat/index.tsx │ ├── my/index.tsx │ └── star/index.tsx ├── tools │ └── index.tsx ├── family │ ├── entry.tsx │ ├── settings.tsx │ ├── user.tsx │ └── member/[id].tsx └── finance ├── (tabs) │ ├── _layout.tsx │ ├── home/index.tsx │ └── analysis/index.tsx ├── add/index.tsx └── sub/index.tsx ``` Effective routes: ```text / startup redirect /auth/login login /home main home /chat chat/image picker demo /my profile tab /star placeholder page, not currently in tab config /tools app/module list /family/entry create or join family /family/settings family settings /family/user user profile settings /family/member/:id family member detail /finance/home finance module home /finance/add add finance record /finance/analysis finance analysis /finance/sub test page ``` Main tab config in `src/app/(tabs)/_layout.tsx`: ```text /home 首页 /space 空间, but route currently missing /tools center app-list button /chat 聊天 /my 我的 ``` Finance module tab config in `src/app/finance/(tabs)/_layout.tsx`: ```text /finance/home 记账 /finance/add center add button /finance/analysis 分析 ``` Layout behavior: - Root `_layout.tsx` renders a global Stack with no headers. - `(tabs)/_layout.tsx` uses `AppLayout`, which renders `Slot`, top `Navbar`, and bottom `Tabbar`. - `finance/(tabs)/_layout.tsx` uses `ModuleLayout`, a module-level shell with its own top bar and tabbar. - `ModuleLayout` close action returns to `/(tabs)/home`. Current route mismatches: - Main tab points to `/space`, but no `/space` file exists. - `src/app/(tabs)/star/index.tsx` exists but is not in the tab config. - `/tools` is outside `(tabs)`, so it is not wrapped by `AppLayout`; decide whether this is intentional. - `/finance/add` is outside `finance/(tabs)`, but the finance tabbar points to it. This can be intentional for a modal/subpage style add screen. ## Feature Status Implemented or mostly implemented: - QQ login - WeChat login - Auth persistence - Auth-expired redirect - Family creation - Family joining by invite code - Family settings - User profile - Avatar upload to S3/RustFS - QQ/WeChat account binding - App/module list page Partially implemented: - Finance module shell - Finance category loading - Finance add-record form UI - Finance analysis placeholder/demo page Not yet complete: - Saving a finance record from `/finance/add` - Finance record list on `/finance/home` - Finance analysis real data - Clothes matching app route - `/space` main-tab page ## Database: allapp Observed database: - PostgreSQL version observed previously: 18.1 - Database: `allapp` - Schema: `public` - Explicit foreign keys: none observed Tables: ```text b_user b_user_oauth b_family b_family_member b_finance b_finance_category b_finance_category_default ``` Views: ```text v_family_member ``` Main entities: - `b_user`: user profile, nickname, avatar, last login time, name, phone, birth date. - `b_user_oauth`: third-party login bindings; includes `user_id`, `type`, `openid`. - `b_family`: family/space; includes `name`, `invite_code`, `owner_id`. - `b_family_member`: family membership; includes `family_id`, `user_id`, `role`, `nickname`. - `b_finance`: finance records; includes `category_id`, `family_id`, `amount`, `remark`, `record_time`. - `b_finance_category_default`: default finance category template. - `b_finance_category`: actual finance categories for a family. - `v_family_member`: joins `b_family_member` with `b_user`. Finance conventions: ```text type = 0 expense type = 1 income ``` Category icon names match frontend iconfont names, for example: ```text finance_jiaotong finance_canyin finance_shicai finance_gouwu finance_gongzi finance_jianzhi finance_shouru ``` ## Local Environment Notes The Codex shell runs inside WSL2 Ubuntu. WSL has `fnm` installed at: ```text /home/oneao/.local/share/fnm/fnm ``` Known WSL Node setup: ```text fnm 1.39.0 v22.22.3 v24.16.0 default ``` In non-interactive Codex commands, `~/.bashrc` may not initialize fnm automatically. If `node` is not found, temporarily enable it with: ```bash export PATH="$HOME/.local/share/fnm:$PATH" eval "$(fnm env --shell bash)" ``` After fnm init, expected tools: ```text node v24.16.0 pnpm 11.5.2 ``` Windows-side `nvm` paths may appear in PATH: ```text /mnt/d/devtool/nvm /mnt/d/devtool/nodejs ``` Those are not the right runtime for WSL. Prefer WSL `fnm`. ## Known Type/Build Issues Frontend: - `pnpm exec tsc --noEmit` currently fails. - `tsconfig.json` includes `**/*.ts` and `**/*.tsx`, pulling in `example`. - `tsconfig.json` has a suspicious extra include entry: `src/app/auth/login_2`. - Generated iconfont components have `react-native-svg` prop type incompatibilities. - `src/app/finance/(tabs)/analysis/index.tsx` has `Surface variant="2"` type mismatch. Backend: - `go` was not available in the earlier command environment, so `go test ./...` could not be rerun there. - Prior context noted a possible unique ID package compile issue around `fmt.Println(message)` vs `fmt.Println(message...)`. ## Important Current Risks - Generic backend data APIs need server-side permissions before production use. - Finance category loading currently queries all `b_finance_category` rows without filtering by current `family_id`. - Frontend business logic often trusts local/user-provided family and user IDs. - Main tab route `/space` is missing. - Some pages are placeholders or demos.