SOURCE WRITE-BACK

原站回寫:保留原站正式資料的接法

本頁只供維護既有「原站確認正式答案」的特殊接駁。新流程使用三種 UI 接入方式;外站保留評審或其他業務資料時,用流程資料同步取得副本,不需要改用 intake。兩邊都能填表或看資料,本身不要求回寫。

OpenDashboard 可以為這類連接應用提供選用的免登入入口。這個功能需要管理員配置通知目的地及原站接收程式;建立表單或匯入資料不會自動開放入口,也不會自動建立雙向同步。

參賽者會看到甚麼?

公開入口只建立新隊伍。開始後,參賽者保存一條私人連結,用來填寫隊伍報名及作品。作品一、作品二可放在同一張作品表,不必拆成兩張表。

連結持有人可查看及修改該隊資料,不必登入。私人連結必須妥善保存;不可放入公開報告、分析工具或日誌。匯入的舊隊伍不會被公開入口按電郵、姓名或原站編號認領。

資料如何到達原站?

1. 參賽者保存草稿或正式提交。OpenDashboard 檢查欄位、附件權限和版本,保存草稿及待處理指令。 2. OpenDashboard 以簽名通知喚醒原站工作程序。通知只有應用、模式和版本號,不含參賽者答案。 3. 原站讀取待處理指令,在交易內檢查報名時段、作品要求及隊伍所有權,保存到原站資料庫。 4. 原站回覆接受或拒絕。OpenDashboard 才顯示「原站已保存」或修正提示。 5. 原站原有的變更通知再同步正式資料到 OpenDashboard 的表單及儀表板。

選用原站回寫的網站需要自己的欄位對應及回寫程式;中央保存模式不需要這套回寫程序。請勿將連接金鑰放在瀏覽器;原站評分、管理員欄位及系統編號不應出現在參賽者輸入定義中。

與中央保存模式的界線

目前 /apply/{slug} intake 固定走待處理指令及原站確認,沒有 direct 模式開關。它不會自動轉換成 OpenDashboard 中央保存的公共新報名入口。中央保存的新流程使用 /start/{slug} 及私人 /w/<token> 頁,或流程填表 API;在流程的「網站接入」配置入口。

原站同步來的舊隊伍不會自動取得 intake 連結。若要跨兩個 UI 修改同一隊伍,需先完成安全身份對應及版本核對;現有新隊伍入口不提供以姓名或電郵認領。

建立入口

以下為合成範例。使用伺服器端連接應用金鑰,POST /api/apps/v1/intakes。應用必須啟用已識別資料模式;每個 form_id 必須屬於相同應用及測試/正式模式。入口建立時保持停用。

json
{
  "id": "ink_demo_intake",
  "slug": "demo-team-entry",
  "definition": {
    "title": "示範比賽報名",
    "description": "開始後請保存本隊私人連結。",
    "forms": [{
      "key": "registration",
      "form_id": "evt_demo_registration",
      "title": "隊伍報名",
      "questions": [{"key":"team_name","type":"short_text","title":"隊伍名稱","personal":false}],
      "actions": [{"key":"save","label":"保存草稿","submit":false}]
    }]
  }
}

定義沿用一般欄位類型及重複群組,但與匯入表單的內部欄位分開。每個表單 key、action key 唯一;動作的 submit 標記只影響呈現,原站仍必須自行執行正式提交驗證。

GET /api/apps/v1/intakes/{id} 讀取配置。配置不可原地換綁表單或改題目;必要時建立新版本入口,保留舊隊伍的定義。管理員先私密配置 HTTPS 通知目的地及簽名密鑰,再 PATCH 同一路徑 {"enabled":true}。開放入口為 /apply/{slug};停用使用 {"enabled":false}。

原站接收與確認

GET /api/apps/v1/intake-commands 每次最多讀取 25 筆本應用、本模式的待處理指令。每筆包含 id、entry_id、intake_id、revoked 及 payload。payload 包含 form、action、answers、expected_revision、source_ref、source_version。

原站只可用自己的私密對應表查找此前由該 entry_id 建立的隊伍,不能用參賽者輸入的電郵連回既有帳戶。首次 source_ref 為空;成功後固定綁定同一隊伍。revoked 為 true 時不得繼續修改來源資料。

將指令 id、payload 雜湊及結果保存在與資料更新相同的交易中。遇上逾時或重播,回覆同一結果,不能另建隊伍。原站與 OpenDashboard 的版本衝突都應保留草稿並要求核對,不可盲目覆寫。

POST /api/apps/v1/intake-commands/{id}/ack:

json
{"status":"accepted","source_ref":"demo_team_001","source_version":"revision_1"}

或拒絕:

json
{"status":"rejected","code":"invalid_answers","fields":{"team_name":"請填寫隊伍名稱。"}}

拒絕代碼包括 invalid_answers、window_closed、version_conflict、entry_closed。拒絕不可帶 source_ref 或 source_version。相同確認可以重播;不同結果回覆衝突。

通知、重試與附件

通知 JSON 為 type=intake.commands.pending、app_id、test、generation。HTTP 標頭 X-OpenDashboard-Intake-Timestamp 及 X-OpenDashboard-Intake-Signature 分別為 Unix 秒和 HMAC-SHA256 十六進位值。簽名輸入是時間字串、句點及原始 body bytes;接收端需固定時間比較、檢查時間差及 app/mode,耐久保存待處理標記後才回覆成功。

共用重試工作只讀有待辦的索引,每次最多三個目的地,並限制逾時和退避;不會每五分鐘逐個應用掃描整份資料。原站程序也需設定單一工作鎖、批次上限、記憶體及時間限制。另可每日查一次待辦指令補漏。

附件透過現有私密上傳 API 取得,external_id 必須以 intake:{entry_id}: 開頭。原站應再次檢查檔案所屬隊伍、完成狀態、大小、SHA-256、實際檔案類型及可信儲存來源;不能下載參賽者提供的任意 URL。本入口接受 JPG、PNG 和 PDF,單檔最多 20 MB;原站可設定更小的整批限制。

與表單管理、儀表板的關係

表單管理仍顯示原站同步來的正式回覆。啟用入口後,可從表單的選單開啟新報名/作品入口。匯入的正式回覆保持由原站管理,避免 OpenDashboard 與原站各自改寫同一筆資料。

儀表板使用同步完成後的正式資料;待原站確認的草稿不應算成報名完成。報告範本只決定如何展示資料,不能代替填表入口或授予隊伍修改權。

自己的填表介面 · API 參考 · 常見問題

在管理介面找到回寫入口

完成 intake 設定後,到「流程管理」選擇已連接的原站報名項目。頁面直接讀取既有 intake,列出關聯表單及報名網址,不會新增重複表單。表單列表及回覆頁也會連回所屬流程。

新報名狀態只包含經該 intake 建立的申請;早前從原站匯入的隊伍仍在關聯表單中。待原站確認、已接受、已拒絕和草稿分開顯示。只有原站確認接受,才代表回寫完成;正式回覆的變更同步仍按原接駁流程處理。

需要完全由 OpenDashboard 保存的新活動,使用中央公開入口。不能直接把原站 intake 當作中央 workflow,或停掉來源同步後假設舊資料已完成轉換。