審議前的報名、背景調查與問題蒐集表單。一張表最多 12 題、六種題型(短答、長答、單選、複選、1–5 量表、同意勾選),沒有帳號、沒有追蹤,整個系統是一個 Cloudflare Worker:一張表單一個 SQLite Durable Object。它在 delib 審議拼圖 裡扮演 HeyForm 的角色,但出口直接是下一輪要吃的格式:
tttc.csv(id,interview,comment)→ Pocket TTTC 或 delib 資料工作台- Pocket Polis 起始陳述(去重後的文字答案,每句 ≤ 280 字)
responses.csv寬表與responses.json
- 在首頁建表:名稱、說明(要寫清楚收什麼、為什麼、保存多久)、題目。建立時要勾「我已決定…」。
- 拿到兩個連結:填寫連結(
/f/<id>)給參與者;主辦者連結(/h/<id>#admin=…)只顯示一次,伺服器只存雜湊。 - 主辦者頁看每題統計(單選/複選長條、量表平均、同意人數),可關閉收件、重新開放、匯出、整份刪除。
填寫者每台裝置一份回應(瀏覽器產生的 v4 UUID,伺服器只存雜湊),再送出會覆蓋;可留暱稱或身分,會成為 tttc.csv 的 interview 欄。
POST /api/forms {title, description?, language?, askAlias?, aliasLabel?, maxResponses?, questions:[...], confirmed:true}
→ 201 {formId, adminToken, urls:{participate, host, api}}
GET /api/forms/:id 公開的題目與狀態
POST /api/forms/:id/responses {responderId (v4 uuid), alias?, answers:{q1:…}} → {ok, updated, responses}
POST /api/forms/:id/me {responderId} → 這台裝置之前的回答
GET /api/forms/:id/host X-Form-Admin: <token> 每題統計
POST /api/forms/:id/status X-Form-Admin {status:"open"|"closed"}
GET /api/forms/:id/export/tttc.csv X-Form-Admin 或 ?token=
GET /api/forms/:id/export/responses.csv
GET /api/forms/:id/export/responses.json
GET /api/forms/:id/export/seeds.json {seedStatements:[…]} 最多 15 句
DELETE /api/forms/:id X-Form-Admin
GET /api/health
題目格式:{type:"short"|"long"|"choice"|"multi"|"scale"|"consent", label, help?, required?, options?:[...], exportText?}。consent 一律必填;short/long 預設 exportText: true。
- 全站建立限制每小時 10、每日 50 張;每張表預設最多 2,000 份回應(
MAX_RESPONSES)。 - 不存 IP、不存原始裝置代碼;主辦者權杖只存 SHA-256。
- 匯出需要主辦者權杖;下載連結帶
?token=,請勿公開。 - 沒有 email 通知、沒有檔案上傳、沒有邏輯跳題:這是給審議流程用的收件表,不是 HeyForm 的替代品。
- 按鈕:部署到自己的 workers.dev。
- 正式站 CI:push 到
main會跑.github/workflows/deploy.yml(check → deploy--env production→ smoke)。需要 repository secretsCLOUDFLARE_API_TOKEN與CLOUDFLARE_ACCOUNT_ID;缺少時 deploy 步驟略過。自訂網域放在wrangler.jsonc的env.production.routes,Worker 名稱不可改。
npm install
npm run dev
npm test # vitest(@cloudflare/vitest-pool-workers)
npm run check # typecheck + test + deploy --dry-run(兩個環境)MIT 授權。