backend-coding
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBackend Coding (Supabase)
后端开发(Supabase)
Khi nào cần skill này (không phải mọi task)
何时需要使用此技能(并非所有任务都需要)
Chỉ trigger khi task thực sự cần logic phía server, KHÔNG trigger cho task chỉ là CRUD đơn giản (Supabase client SDK trong Flutter tự query/insert/update trực tiếp là đủ, không cần viết gì thêm ở đây):
- Phân quyền dữ liệu phức tạp hơn "user chỉ xem của mình" đơn giản → viết RLS policy.
- Tính toán không thể tin client (giá, tổng tiền, áp dụng voucher, số dư ví) → Edge Function hoặc Postgres function, không tính ở Flutter rồi gửi kết quả lên.
- Webhook từ bên thứ 3 (Momo callback, xác nhận thanh toán) → Edge Function nhận request, xác thực chữ ký, cập nhật DB.
- Job chạy định kỳ (nhắc lịch hẹn, dọn dữ liệu cũ) → Supabase Cron + Edge Function.
- Validate business rule mà RLS đơn thuần không diễn đạt được (ví dụ: không cho đặt lịch trùng giờ) → Postgres function/trigger hoặc Edge Function.
仅在任务确实需要服务端逻辑时启用,不要在仅需简单CRUD的任务中启用(Flutter中的Supabase客户端SDK可直接完成查询/插入/更新操作,无需在此处额外编写代码):
- 比“用户仅查看自己的数据”更复杂的数据权限控制 → 编写RLS策略。
- 不可信任客户端的计算操作(价格、总金额、优惠券应用、钱包余额)→ 使用Edge Function或Postgres函数,不要在Flutter中计算后再将结果发送到服务端。
- 第三方Webhook(如Momo回调、支付确认)→ 使用Edge Function接收请求、验证签名并更新数据库。
- 定时任务(如日程提醒、清理旧数据)→ 使用Supabase Cron + Edge Function。
- 验证单纯RLS无法表达的业务规则(例如:不允许重复预约时间)→ 使用Postgres函数/触发器或Edge Function。
Thiết kế Schema (Postgres)
Postgres Schema设计
- Đọc delta spec () để lấy Data Model - đây là nguồn field/bảng, không tự bịa thêm cột ngoài spec.
openspec/changes/<change-name>/specs/ - Map 1-1 sang bảng Postgres, dùng đúng kiểu dữ liệu (,
textcho tiền - KHÔNG dùngnumericcho tiền,floatcho thời gian,timestamptzcho khóa chính mặc định).uuid - Khai báo foreign key rõ ràng cho quan hệ 1-nhiều/nhiều-nhiều thay vì nhúng mảng JSON tùy tiện - tận dụng đúng thế mạnh quan hệ của Postgres so với NoSQL.
- Nếu delta spec đánh dấu "BREAKING" (đổi field bảng đã có dữ liệu) → chuyển qua trước, viết migration SQL (
schema-migration/SKILL.md) thay vì DROP+CREATE lại.ALTER TABLE
- 阅读delta规范()获取数据模型——这是字段/表的来源,不得自行添加规范外的列。
openspec/changes/<change-name>/specs/ - 一对一映射到Postgres表,使用正确的数据类型(、金额使用
text——不要使用numeric存储金额,时间使用float,默认主键使用timestamptz)。uuid - 为一对多/多对多关系明确声明外键,而非随意嵌入JSON数组——充分利用Postgres相较于NoSQL的关系型数据库优势。
- 如果delta标记为“BREAKING”(修改已有数据的表字段)→ 先查看,编写迁移SQL(
schema-migration/SKILL.md)而非删除后重建表。ALTER TABLE
Row Level Security (RLS)
行级安全(RLS)
- Mặc định BẬT RLS cho mọi bảng chứa dữ liệu người dùng (không bao giờ để bảng public không có policy).
- Viết policy tối thiểu cần thiết cho từng thao tác (,
select,insert,update) riêng biệt, không gộp 1 policy "cho phép hết" rồi lọc ở client.delete - Ví dụ pattern phổ biến:
sql
create policy "user xem don hang cua minh" on orders for select using (auth.uid() = user_id); create policy "chi admin sua trang thai don hang" on orders for update using (exists (select 1 from staff where staff.user_id = auth.uid() and staff.role = 'admin')); - Test policy qua MCP/Supabase local trước khi coi task là xong - không chỉ tin code đọc đúng, phải chạy thử với user thật khác quyền.
- 默认对所有包含用户数据的表启用RLS(绝不要让public表没有策略)。
- 为每个操作(、
select、insert、update)编写必要的最小权限策略,不要编写一个“全允许”的策略后在客户端过滤。delete - 常见示例模式:
sql
create policy "user xem don hang cua minh" on orders for select using (auth.uid() = user_id); create policy "chi admin sua trang thai don hang" on orders for update using (exists (select 1 from staff where staff.user_id = auth.uid() and staff.role = 'admin')); - 在标记任务完成前,通过MCP/Supabase本地环境测试策略——不要仅依赖代码审查,必须使用不同权限的真实用户进行测试。
Edge Function (khi cần logic server thật)
Edge Function(当需要真正的服务端逻辑时)
- Viết bằng Deno/TypeScript, đặt trong .
supabase/functions/<ten-function>/index.ts - Với mọi tính toán tiền/số lượng: tính toán 100% ở Edge Function/Postgres function, Flutter chỉ hiển thị kết quả trả về, KHÔNG tự tính rồi gửi lên để server "xác nhận lại" - phải là server tính từ đầu.
- Webhook (Momo, v.v.): luôn xác thực chữ ký/signature từ bên thứ 3 trước khi xử lý, không tin request chỉ vì đúng URL.
- Trả lỗi rõ ràng (HTTP status + message) để phía client xử lý đúng, không trả lỗi chung chung.
flutter-coding
- 使用Deno/TypeScript编写,放置在路径下。
supabase/functions/<ten-function>/index.ts - 所有金额/数量计算:100%在Edge Function/Postgres函数中完成,Flutter仅显示返回结果,不要自行计算后发送到服务端“确认”——必须由服务端从头计算。
- Webhook(如Momo等):在处理前始终验证第三方的签名,不要仅因URL正确就信任请求。
- 返回清晰的错误信息(HTTP状态码 + 消息),以便客户端正确处理,不要返回模糊的通用错误。
flutter-coding
Sau khi viết xong backend
后端编写完成后
- Chuyển sang để viết phần client gọi đúng RPC/Edge Function/table vừa tạo (dùng
flutter-coding/SKILL.mdpackage).supabase_flutter - Chạy để test toàn bộ luồng end-to-end (client gọi thật, không chỉ test riêng backend).
mcp-loop/SKILL.md
- 切换到编写客户端部分,正确调用刚创建的RPC/Edge Function/表(使用
flutter-coding/SKILL.md包)。supabase_flutter - 运行进行端到端全流程测试(客户端真实调用,不要仅单独测试后端)。
mcp-loop/SKILL.md
Package Supabase phía Flutter (thêm vào danh sách đã duyệt trong architecture/SKILL.md
nếu chưa có)
architecture/SKILL.mdFlutter端Supabase包(若未在architecture/SKILL.md
的已批准列表中则添加)
architecture/SKILL.md- - client chính thức, dùng cho Auth + Realtime + Postgrest query trực tiếp cho CRUD đơn giản.
supabase_flutter - Không tự thêm package Supabase cộng đồng khác ngoài package chính thức trừ khi user xác nhận.
- - 官方客户端,用于Auth + Realtime + 直接进行简单CRUD的Postgrest查询。
supabase_flutter - 除非用户确认,否则不要添加官方包之外的其他Supabase社区包。