QBear.
The engineering companion · Design v1.0

把小熊的想法,
變成清晰的工程藍圖。

Technical design / 技術設計工作台

從開發前置條件到資料模型、畫面流程與服務合約,讓產品、工程及營運使用同一份設計。

填寫開發前置設定 ↓
DESIGN ONLYiOS + Android先準備,再開發。

本頁是設計文件與設定筆記。App 畫面按鈕只示範流程。QBear schema 及設定表已建立;開發前置設定登入後儲存到 Supabase。

QBear資料庫 schema 名稱
7畫面線框
3,600首次啟動贈送秒數
01 / SYSTEM ARCHITECTURE

一隻公仔,一個獨立的時間錢包。

延續項目手冊架構:Flutter 手機 App、Supabase 身份與資料庫、受控 Voice Gateway。公仔是角色與 QR 載體;手機收音及播放是 MVP 假設,硬件語音另行設計。

Flutter App

iOS / Android家長登入 · QR · 語音介面 · IAP

業務 API + Voice Gateway

身份與所有權 · 限速 · 冪等媒體控制 · 安全攔截 · 可信計時

Supabase / Provider

Auth + PostgreSQL「QBear」核准語音供應商 · 商店驗證

App 的責任

畫面、登入狀態、相機/咪高峰權限、商店購買及顯示伺服器餘額。UI 不自行加減秒數,也不直接更新 ownership 或 ledger。

後端的責任

從已驗證 JWT 取家長身份;每次檢查公仔所有權、同意及限時。交易統一鎖序;Gateway 只可在有效租約內傳送及生成音訊。

設計基線:廣東話優先、每隻公仔獨立額度、家長付款。年齡範圍、推出地區、供應商資格與兒童資料處理條件需先確認。Supabase 資料推送與供應商的即時語音服務是不同服務。
02 / BEFORE YOU BUILD

開發前置條件與設定筆記

填入非機密設定與負責人,登入授權帳戶後儲存到 Supabase。每個環境獨立版本,可從其他瀏覽器登入載入。

0 / 8 項自行確認
設定儲存在 QBear.project_configuration;不是 App 已部署或資格已驗證。不要輸入 API secret、service_role key、資料庫密碼或付款憑據;只記錄 secret manager 項目名稱。勾選為使用者自行確認,並非本頁已驗證連線、DNS 或資格。所有欄位、確認清單及決策筆記一併保存;匯出 JSON 可作備份。

Supabase 設定編輯帳戶

使用此專案的 Supabase Auth 電郵/密碼登入。只有 QBear.configuration_editors 內的帳戶可讀寫;此登入只用於設計設定。

尚未登入。密碼不會儲存在配置內。

A. 項目與網域

B. 資料庫、身份與平台

C. 語音與營運

開發開始前的確認清單

請登入已授權的設定編輯帳戶,以載入及儲存 QBear 雲端設定。

03 / DATABASE BLUEPRINT

專案資料庫 namespace:QBear

在指定 Supabase 專案的 PostgreSQL 建立 schema,並非另建 database。保留精確名稱 QBear:所有 SQL 引用用 "QBear".table_name;未加引號會轉為小寫。

狀態:QBear schema 與設定資料表已建立。已部署 configuration_editors 及 project_configuration,並初始化 planning、development、staging、production 四個環境。下方 App 業務表仍為後續設計,未建立。

Schema 建立紀錄(已執行,節錄)

BEGIN;
CREATE SCHEMA IF NOT EXISTS "QBear";
COMMENT ON SCHEMA "QBear" IS
  'QBear project: parents, dolls, wallets and voice-session accounting';
REVOKE ALL ON SCHEMA "QBear" FROM PUBLIC, anon;
-- Configuration access is restricted by editor-membership RLS.
GRANT USAGE ON SCHEMA "QBear" TO authenticated, service_role;
COMMIT;

-- Verify after execution; expected result: QBear
SELECT nspname FROM pg_namespace WHERE nspname = 'QBear';

MVP 建議保持 QBear 不暴露於 Data API,App 經業務 API 存取。service_role 只放後端且須驗證所有權。未來直讀需要 exposed schema、逐表 SELECT grant 與 ownership RLS;App 不直接寫餘額。Supabase custom schemas 官方文件。

已建立:BEFORE YOU BUILD 設定儲存

資料表保存內容存取
QBear.configuration_editorsuser_id → auth.users、created_at管理員配置授權名單;登入者只讀自己的資格,不可自行授權。
QBear.project_configurationenvironment 主鍵、settings JSONB(全部 30 欄)、revision、updated_at、updated_by僅指定編輯者可讀寫;server timestamp/revision;版本衝突拒絕覆蓋。

透過 public.qbear_load_configuration / qbear_save_configuration 讀寫,兩者均 SECURITY INVOKER,保留 RLS。QBear 無需加入 exposed schemas;匿名使用者不能呼叫或存取設定。Secrets 只記錄參照名稱。

App 業務資料表與約束(設計,未建立)

QBear 資料表欄位與關係約束及存取
parents / consentsparents.id → auth.users.id;status;consents.parent_id、version、accepted_at、revoked_at只設家長身份;版本化同意;停用/撤回立即阻止新 session。
dollsid UUID PK、serial、owner_id → parents、character_id、stateserial UNIQUE;只讀自己公仔;綁定經 redeem。
walletsdoll_id → dolls(PK)、balance_seconds bigint、reserved_seconds bigint、revisionCHECK balance ≥ reserved ≥ 0;available = balance − reserved。
sessionsid、doll_id → dolls、parent_id、state、fence_epoch、started_at、closed_atpartial UNIQUE(doll_id) WHERE state IN ('connecting','active','paused');timestamptz 時間戳。
leasesid、session_id → sessions、granted_seconds、settled_seconds、expires_at、state每 session 一個 open lease;0 ≤ settled ≤ granted ≤ 15;到期硬停止。
ledgerid、doll_id → dolls、session_id、delta_seconds、kind、dedupe_key、created_atdedupe_key UNIQUE;追加式,不覆寫;補償用新分錄。
purchasesid、parent_id、doll_id、store、environment、transaction_key、product_id、stateUNIQUE(store, environment, transaction_key);驗證完成才加額。
qr_codesid、doll_id、token_hash、pepper_version、redeemed_at、revoked_attoken_hash UNIQUE;HMAC 雜湊;App 不讀;原碼不進 log。
outbox / auditid、event_key、actor、resource、狀態、重試/審計時間event_key UNIQUE;outbox 隨交易提交;不存原始語音或 QR secret。

索引與不變量

owner_id、parent_id 等外鍵查詢欄位建索引;ledger(doll_id, created_at)、leases(state, expires_at)。UUID 作 ID、bigint 作整數秒。餘額以帳本核對,不得負可用額度。

隔離與保留

每表啟用 RLS 作額外防線;使用者可讀資料與秘密/付款原文分開。如增加直讀,以 auth.uid() 與 owner 限制行;UPDATE 同時有 USING + WITH CHECK。保留期限由前置設定決策落實。

依據:Supabase RLS 官方文件。完整 migration、policy 及刪除方案留待後續開發,需將原手冊 SQL 基線的物件與關聯一致遷移到 "QBear",不能混用 public 版本。

04 / SCREENS & INTERACTIONS

畫面線框與使用流程

點選畫面或線框內的按鈕查看流向。示範資料固定,沒有登入、相機、語音或付款功能。

首頁另有「增值」及「家長設定」分支。額度不足 → 家長增值 → 商店驗證 → 返回首頁。撤回同意 → 停止語音 → 重新同意。

9:41 · DESIGN PREVIEW

你好,我是 QBear。

由家長登入,陪好奇心一起長大。

家長電郵 · 模擬輸入欄
家長同意/私隱摘要
AI 身份 · 咪高峰用途 · 可隨時停止

01 / 身份與家長同意

家長是帳戶持有人;兒童無獨立登入。已有登入及有效同意可直接到首頁。

  • ① 驗證碼:真正 App 驗證電郵、限速及 resend cooldown;OTP 驗證成功才完成登入。
  • ② 繼續:需完成登入及明確同意,再送 consent version 及 server timestamp;進掃碼或首頁。

UI states / 例外

格式錯誤、OTP 過期、網絡失敗及未同意:停留原畫面並提供修正/重試,不建立 session。

Auth → POST /v1/consents → GET /v1/dolls

目前:01 登入/同意。點選可看流程,不執行 App 功能。

05 / SERVICE CONTRACTS

如何實作:API、交易與失敗處理

API 前綴為設定的 API URL + /v1。HTTPS、驗證家長 JWT、從 token 取身份;body 的 parent_id 不作授權。寫操作有 request_id、Idempotency-Key 與 body hash;同鍵不同 body 回 409。

方法與路徑輸入 → 輸出規則
GET /dolls
GET /dolls/{id}/wallet
GET /dolls/{id}/ledger
JWT/公仔 → 公仔、balance/reserved/available/revision、分頁帳本每次檢查 ownership;跨家庭不可見。
POST /activations/redeemqr_token、consent_version → doll_id、granted_seconds、revision一次綁定並送 3,600 秒。
POST /sessionsdoll_id、device_nonce → session_id、Gateway token、protocol、expires_atconnecting 不扣額;30 秒未 ready 清理;每公仔一個 session。
POST /sessions/{id}/pause
POST /sessions/{id}/resume
POST /sessions/{id}/close
冪等鍵 → state、settled_seconds、wallet revisionpause/close 停媒體、結算、釋放;resume 重查限制並發新 token/lease。
POST /purchase-intents
POST /purchases/verify
doll_id、store、product_id → intent;intent_id+receipt → pending/credited交易身份去重;正式/sandbox 分開。
GET /parent-settings
PATCH /parent-settings
上限、家庭時區、version → 新設定/version家長驗證;版本衝突 409;後端 enforcement。
POST /consents
POST /safety-reports
DELETE /account
同意/撤回、event ID/類別、重新驗證 → 狀態或 202 job停用優先於媒體;安全回報最小資料。
POST /internal/leases/*
POST /webhooks/apple
POST /webhooks/google
可信累積用量/平台通知 → 結算/接受事件Gateway mTLS/服務簽章;webhook 驗簽去重;不給 App。

核心原子交易

1. 啟動

驗同意 → HMAC → 鎖 QR → wallet → 綁 owner → +3,600 → 唯一 ledger → redeemed → outbox → commit。鎖序由 QR(如有)→ wallet → session → lease,所有交易一致。同家長同碼返回原結果。

2. 扣秒

Gateway ready 預留最多 15 秒,每 5 秒提交可信累積毫秒;檢查 fence、期限及 event 去重。消耗同時減 balance 與 reserved,釋放只減 reserved;每 session 一個 open lease。

3. 付款

intent → 商店 → server verify → 鎖 wallet → 去重 purchase → 加額 → ledger → outbox → commit。取消、pending、驗證失敗不加額。

計時與故障

累積毫秒中途 floor、最終一次 ceil;跨租約留餘數。到期/DB 故障/gate 不可用即停媒體。只扣持久化可信證據,未知尾段由營運承擔。

錯誤語意

401 登入;403 / 404 不可存取;402 秒數不足;409 綁定、version 或冪等衝突;422 修正輸入;429 按 retry-after;503 暫停後重試。逾時不代表交易失敗,用相同冪等鍵或查狀態;只對可重試錯誤採有抖動的退避。

Flutter 實作邊界(後續開發)

Feature 分為 auth / activation / dolls / voice / wallet / purchases / parent,各有 screen、狀態控制器、repository 與 typed DTO。共用 HTTP client 處理 JWT refresh、request ID 與錯誤映射;repository 為資料入口。voice 狀態機驅動 UI,與音訊 transport 分離;開發時確認並鎖定 Flutter/SDK 版本。

06 / IMPLEMENTATION HANDOFF

後續開發順序與驗收

目前已交付設計 HTML、QBear schema 及雲端設定儲存;Flutter App、語音、付款與業務資料表尚未開發。

01 · 資格與準備市場、供應商、兒童資料、商店 QR 審批及前置設定。證據:資格確認及決策紀錄。
02 · 資料與交易開發環境建立 QBear、表、權限及原子交易。證據:並發、去重及家庭隔離測試。
03 · App 閉環依線框完成 Flutter、Gateway、安全及 IAP sandbox。證據:啟動→語音→結算→付款。
04 · 試點與營運還原、告警、客服、刪除與安全評審後家庭試點。證據:驗收與回滾演練。

驗收必須涵蓋

返回手冊的工程交付與責任分工 →