From ff4590767debe22dc74a0dbd8a944b675e3046f9 Mon Sep 17 00:00:00 2001 From: Guoguo Date: Tue, 5 May 2026 02:35:36 -0700 Subject: [PATCH] docs: update AGENTS.md with current architecture and security measures --- AGENTS.md | 174 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 60 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 1de6c03..e20735f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,74 +1,128 @@ # Repository Reality -- This repository now contains the WeChat Mini Program, the uniapp/Vue 3 admin console, a Tencent Cloud SCF HTTP backend, deployment docs, and design/planning references. -- Current backend implementation lives in `server/` and targets Tencent Cloud HTTP Function + TencentDB MySQL + COS. -- The previous WeChat Cloud Development function directories have been removed from the active architecture. -- Do not treat older planning/review documents as current implementation truth unless they explicitly say they are current. +- WeChat Mini Program (`miniprogram/`) + Tencent Cloud SCF HTTP backend (`server/`) + Vue 3 H5 admin console (`admin-console/`). +- Backend: Express.js with DAO layer, deployed as Tencent Cloud HTTP Function. +- Database: TencentDB MySQL, schema in `server/sql/schema.sql`. +- Storage: Tencent COS for firmware and admin H5 artifacts. -# Verified System Scope +# Architecture -- Mini Program: native WeChat `WXML` / `WXSS` / `JS` under `miniprogram/`. -- Device communication: BLE 5.0 GATT via `miniprogram/services/ble.js`. -- Mini Program cloud API: HTTPS requests through `miniprogram/utils/request.js` to the configured API base in `miniprogram/config/env.js`. -- Backend: Tencent Cloud HTTP Function, package root uses executable `server/scf_bootstrap` to start `node scripts/local-server.js` on port `9000`. -- Database: TencentDB MySQL schema in `server/sql/schema.sql`. -- Storage: Tencent COS for firmware/admin H5 artifacts. -- Admin console: uniapp + Vue 3 under `admin-console/`, H5 build can be uploaded to COS. +## Server (`server/src/`) -# Current Deployment Facts - -- Test API base is configured as `https://1426323813-ilxkhlxf4p.ap-guangzhou.tencentscf.com` in both Mini Program and admin console test configs. -- SCF function name used during deployment: `jw-beauty-api`. -- SCF is an HTTP function, not an event function. Use `scf_bootstrap`, not `index.main_handler`, for this function type. -- SCF must be attached to the TencentDB VPC/subnet when using the database private endpoint. -- Real secrets must remain in local `.env` or SCF environment variables. Never commit `server/.env`. - -# Integration Facts Worth Preserving - -- BLE frame format implemented in code: header `0xAA 0x55`, length, type, payload, XOR checksum over header/length/type/payload. -- BLE services in the document/code: `FFE0` device info, `FFE1` data communication, `FFE2` OTA. -- Device binding is two-phase: backend bind request creates pending token, Mini Program sends BLE bind, device returns bind success, Mini Program confirms backend binding. -- Device commands are queued in MySQL `device_commands`; Mini Program pulls pending commands and executes BLE commands. -- Current main cloud path is HTTPS API through the Mini Program, not MQTT/IoT direct device-cloud communication. - -# User Profile / Login Reality - -- `wx.login()` only provides a code for backend `openid/session_key` exchange. -- The current login page uses `wx.getUserProfile()` to request WeChat's official profile authorization popup and then stores returned nickname/avatar if WeChat provides them. -- WeChat may still return masked values such as `微信用户` and default avatar. This is platform policy, not a backend bug. -- If reliable nickname/avatar capture becomes required, use the newer `chooseAvatar` + `input type="nickname"` flow, but that is not the current requested UX. -- Phone number authorization is scaffolded through `open-type="getPhoneNumber"` and backend `/api/v1/user/phone`, currently hidden in the login UI. - -# Build And Deploy Commands - -Backend local: - -```bash -cd server -npm install -npm run db:init -npm start +``` +app.js — Express app, middleware, route mounting, rate limiting +index.js — SCF entry point (lib/serverless.js adapter) +config.js — Environment config with production guards +lib/ + db.js — MySQL2 pool, query/one/transaction helpers, namedPlaceholders + auth.js — JWT sign/verify, bcrypt compare, randomHex + response.js — ok()/fail() response wrappers + settings-cache.js — Cached settings with 60s TTL + invalidateCache() + serverless.js — SCF event → Express req/res adapter + utils.js — toMysqlDate (UTC+8 aware) +middleware/ + auth.js — requireUser/requireAdmin Express middleware +dao/ — 11 DAO files: admin, binding, command, device, device-event, + firmware, log, settings, subscription, treatment, user +routes/ — 7 route files: admin, auth, device, firmware, subscription, treatment, user +scripts/ + local-server.js — Local dev server (app.listen) + init-db.js — Database schema initialization ``` -Admin H5: +**Route mounting:** +- `/api/v1` — auth, user, device, subscription, treatment, firmware +- `/api/v1/admin` — admin routes +- Rate limiting: user login 10/15min, admin login 5/15min -```bash -cd admin-console -npm install -npm run build:h5 -npm run deploy:cos +**Auth:** +- User: JWT_SECRET, payload.type === 'user', 7d expiry, 1d refresh grace +- Admin: ADMIN_JWT_SECRET, payload.type === 'admin' +- bcrypt for passwords, SHA-256 legacy auto-migration + +## Mini Program (`miniprogram/`) + +``` +pages/ — 15+ pages (index, profile, subscribe-*, treating, etc.) +services/ + ble.js — Proxy: module.exports = require('./ble/index') + ble/ + protocol.js — Constants, frame encode/decode, uint32ToBytes, hexToBytes + connection.js — Scan, connect, disconnect, reconnect, event emitter + commands.js — writeCommand, startTreatment, stopTreatment, bindDevice + index.js — Barrel export (39 exports including REGION_NAMES) +utils/ + api.js — Named API functions matching server routes + request.js — wx.request wrapper with token refresh + page.js — getStatusBarHeight, navigateBack, isDevMode +config/ + env.js — API base URL per environment ``` -Mini Program BLE frame test: +**BLE frame format:** `0xAA 0x55 | length | type | payload | XOR checksum` -```bash -cd miniprogram -node scripts/test-ble-frame.js +**Device binding:** Two-step (bind request → BLE handshake → confirm) or mock-bind (dev only). + +## Admin Console (`admin-console/`) + +``` +pages/ + login/index.vue — Standalone login page + admin/index.vue — SPA shell: AdminLayout + keep-alive + dynamic +views/ — 9 views: Dashboard, DeviceList, DeviceDetail, UserList, + UserDetail, Subscription, Record, Log, Settings +components/ + AdminLayout.vue — Sidebar nav, emits 'navigate' with view names + DataTable.vue — Reusable table + pagination + ConfirmModal.vue — Reusable modal +utils/ + useList.js — listMixin for paginated list views +styles/ + common.css — Shared styles including form classes ``` -# Working Rules For Future Sessions +**SPA routing:** Component-based (no URL routing). keep-alive caches views by `name` property. -- Use current executable config and code as the source of truth before relying on older planning docs. -- Do not reintroduce `wx.cloud`, WeChat Cloud Development functions, or MQTT unless the architecture is explicitly changed again. -- Do not commit `.env`, cloud credentials, database passwords, signed COS URLs, or generated build artifacts. -- Before committing, check `git status --short` and scan staged files for secret-looking values. +# Key Design Decisions + +1. **Subscription extends, never overwrites** — purchase() adds days to existing expire_time via DATE_ADD +2. **Settings cache** — 60s TTL in-memory, invalidated on admin save +3. **Feature toggles** — maintenance_mode, enable_binding enforced server-side via settings-cache +4. **Timezone** — SCF runs UTC, MySQL connection timezone +08:00, toMysqlDate forces UTC+8 +5. **Mock endpoints** — mock-bind, mock-purchase restricted to non-production (config.nodeEnv !== 'production') +6. **BLE module resolution** — `services/ble.js` proxy file exists because WeChat `require('./ble')` doesn't resolve `ble/index.js` + +# Security Measures + +- Rate limiting on auth endpoints (express-rate-limit) +- Production guards: throw if JWT secrets or admin credentials use defaults +- Parameterized queries (namedPlaceholders) everywhere except one Number()-coerced IN clause +- JWT type field prevents cross-contamination between user/admin tokens +- CORS currently `*` (development phase, to be restricted for production) + +# Deployment + +**Backend local dev:** +```bash +cd server && npm install && npm start +``` + +**SCF deploy:** +- HTTP function, uses `scf_bootstrap` (not event handler) +- Must be in TencentDB VPC/subnet +- Function name: `jw-beauty-api` + +**Admin H5:** +```bash +cd admin-console && npm install && npm run build:h5 && npm run deploy:cos +``` + +**Test API base:** `https://1426323813-ilxkhlxf4p.ap-guangzhou.tencentscf.com` + +# Working Rules + +- Use current code as source of truth, not older planning docs +- Never commit `.env`, credentials, or signed URLs +- WeChat miniprogram `require()` does not auto-resolve directories — always use explicit proxy files +- `wx.getUserProfile()` is deprecated; if reliable profile needed, use `chooseAvatar` + nickname input +- Mock/dev endpoints are gated by `config.nodeEnv !== 'production'`