CONNECT WORKFLOW DATA

流程資料接駁與變更通知

在 OpenDashboard 建立流程,網站使用連結、iframe 或自訂 UI 填表。OpenDashboard 保存答案及推進流程;外站需要副本時,使用本頁的表單對應、申請讀取及資料變更通知。這不是雙向同步,也不會接入既有外站資料。

在哪裡設定

進入「流程管理 → 選擇流程 → 網站接入 → 資料通知 → 開發者設定」。已發佈流程可查看表單對應,設定 HTTPS 接收網址、啟用通知、取得一次顯示的驗證密鑰及查看傳送紀錄。設定需要查看個人資料及編輯權限;查看紀錄需要查看個人資料權限。

通知預設關閉。不指定接收網站就不會向外傳送。接收網址須為公開 DNS 名稱、HTTPS 443,不能包含帳密、查詢參數或片段;不跟隨轉址,目前需有公開 IPv4。每次傳送重新核對 DNS 並固定連線地址,拒絕私人網絡及保留地址。

表單關聯和版本

名稱代表什麼
workflow_id一套流程,跨發佈版本不變
version一宗申請固定使用的發佈版本
step_id流程中的填表步驟
form_id該發佈版本儲存答案的表單
source.kind = workflow_owned題目在流程內建立
source.kind = question_reference引用既有題目;source.form_id 和 revision 指向來源及題目版本
application_id同一宗申請的固定 OpenDashboard 編號,等於 workflow run id
external_id外站建立申請時指定的識別值;OpenDashboard 公開入口會自動產生
revision申請每次成功變更後遞增,用於衝突檢查及避免舊資料覆蓋新資料

引用問題不等於連接既有答案。發佈後的 form_id 是流程自己的版本表單;原表單、原答案、電郵及 QR 設定保持原狀。新版本不會搬移舊申請。改題目後須重新發佈,新入口選用新版本,舊申請仍使用原版本。

舊資料接入是另行核對的遷移工作,目前不提供把任意外站答案自動變成流程申請的操作。全新活動可直接在流程建立表單,無須使用舊資料。

讀取對應和完整申請

以下是網站後端使用的應用管理 API,使用連接應用的伺服器金鑰。它不是參加者填表金鑰,絕不可放到瀏覽器、iframe 或公開代碼中。參加者仍用流程接入 API及私人憑證,只能操作自己的申請。

javascript
const base = 'https://registration.konnec.ai/api/apps/v1';
const headers = { Authorization: `Bearer ${process.env.OPENDASHBOARD_APP_KEY}` };
// version 選填;省略時取最新發佈版本。同步申請時應使用該申請的固定版本。
async function read(path) {
  const response = await fetch(base + path, { headers, redirect: 'error', signal: AbortSignal.timeout(15000) });
  const data = await response.json();
  if (!response.ok) throw Object.assign(new Error(data.message || 'Read refused'), { code: data.error });
  return data;
}
const bindings = await read('/workflows/wfl_example/bindings?version=1');
const snapshot = await read('/workflow-runs/wru_example/export');

申請回傳 application_id、workflow_id、version、revision、external_id、status、current、updated_at 及 forms。每份表單有 step_id、form_id、source 和 items;items 保留答案、提交狀態、附件 ID 及回覆編號。未填寫的步驟 items 為空;draft 不能當作已提交。附件取得方式見下節,通知不傳相片或公開下載網址。

所有讀取限制在金鑰所屬應用及正式/測試環境。跨應用、跨環境或不存在的申請回傳 404。私人填表連結和流程填表金鑰不提供這個完整匯出端點。

同步附件與初次補齊

export 不包含參與人的 actor。若使用 /workflow-runs/:id/files/:uploadId?actor=:ref,ref 必須是建立申請時由可信後端分配、且有權查看該附件的參與人;缺少 actor 會回 invalid_actor。流程填表 API 開始的申請由平台建立參與人,不能猜 actor 或拿 application_id 代替。

已有管理金鑰的接收程序可用 GET /api/apps/v1/uploads/:uploadId 讀取同應用/模式的已完成私人附件,回傳 url、sha256、size、content_type。只下載本次受信任 export 答案實際引用的 upload id,核對 bytes 與摘要、大小及格式,再寫入本地副本。此廣泛應用附件端點不是限一宗申請的接口,也不被 publication.data_sync 自動撤銷;不可把它代理成任意訪客可輸入 upload id 的下載接口。

如果需要使用限申請的 files 端點,先採用有明確參與人對應的管理 API 建立方式,見流程管理 API。填表者自己下載則使用流程金鑰+私人憑證的 ?action=file,不需要 actor。兩種下載不可混用。

初次同步用 GET /workflows/:id/runs?offset=0&limit=25,讀取回傳 runs 的 id,逐宗取得 export;帶 next_offset 讀下一頁,直到 null。名單不是整批一致快照:同時開啟持久通知收件,再用 revision 去重並於完成後對帳。不能只處理第一次 25 筆,亦不可把 offset 當成永久增量游標。

同一宗申請不重複建立

外站用應用 API 建立申請時,對同一流程重用相同 external_id、respondent、participants 和 version。建議首次明確指定 version 並保存原請求;省略時首次採用最新發佈版本,已存在的 external_id 重試則沿用原版本。相同請求重試會返回同一個 OpenDashboard 編號;相同 external_id 卻不同內容會拒絕。external_id 的唯一範圍是該流程,不能拿 email 當跨網站認領憑證。

用公開入口或自訂 UI 填表 API 時,開始後保存回傳的申請編號和私人憑證,之後沿用它們。每次重新產生憑證並開始報名會建立新申請。跨裝置續填須使用既有私人連結;系統不會只憑姓名或電郵合併隊伍。

答案更新沿用既有 operation_id 和 revision 規則:網絡失敗時重試完全相同的操作,不另產生新 operation_id。版本衝突先讀取最新申請,再由使用者確認要提交的內容。

通知內容

每次建立申請或成功保存、提交、補件、審核和推進步驟,都會在同一個資料庫交易中建立通知。通知不是畫布的「站內通知」節點,也不是電郵。操作重試不會建立第二筆相同版本通知。

json
{
  "id": "wfe_wru_example_2",
  "type": "workflow.application.changed",
  "app_id": "example_app",
  "test": true,
  "workflow_id": "wfl_example",
  "application_id": "wru_example",
  "version": 1,
  "revision": 2,
  "occurred_at": "2026-10-11T13:00:00+00:00"
}

沒有答案、隊員資料、私人憑證或附件內容。接收者按 application_id 讀取最新申請。這是最新狀態同步:若收到 revision 2 通知時已更新至 4,讀取可返回 4,不保證取回每次變更當下的完整答案快照。

驗證簽章

標頭包括 X-OpenDashboard-Event-Id、X-OpenDashboard-Timestamp 及 X-OpenDashboard-Signature。簽章是 HMAC-SHA256(secret, timestamp + '.' + 原始請求 body) 的十六進位值。驗證前不要重新 JSON.stringify body。

javascript
import crypto from 'node:crypto';
function verify(rawBody, timestamp, signature, secret) {
  if (!Buffer.isBuffer(rawBody) || !/^\d+$/.test(timestamp || '') ||
      Math.abs(Date.now() / 1000 - Number(timestamp)) > 300 ||
      !/^[a-f0-9]{64}$/.test(signature || '')) return false;
  const expected = crypto.createHmac('sha256', secret)
    .update(timestamp).update('.').update(rawBody).digest();
  return crypto.timingSafeEqual(expected, Buffer.from(signature, 'hex'));
}

可直接使用後端範例中的 verifyWorkflowNotice,輸入原始 Buffer、三個標頭、私密簽章密鑰及預期 app_id/workflow_id/test。簽章密鑰不是流程或應用 API 金鑰。

接收網站還須核對 type、app_id、test、workflow_id,以及標頭 event id 與 body.id 一致。將通知寫入有唯一 event id 的持久佇列後才回傳 2xx;不要只放入程序記憶體便確認成功。後台讀取申請、按 application_id 更新副本,只有較新的 revision 才覆蓋舊版本。處理副本寫入失敗,也要由接收網站自己的佇列重試。

重試和停用

通知會在 API 保存後嘗試傳送;每分鐘的背景工作只處理已產生的待送通知,不重新查詢外站或掃描全部答案。單次最多處理 5 筆,HTTP 最多等待 8 秒;非 2xx、轉址和網絡錯誤按退避間隔重試。最多 8 次後標示失敗,可在流程設定按「重試」。傳送採至少一次,不能假設每筆只到達一次或順序固定。

重試保持相同 event id 和原始 body,時間戳與簽章更新。若外站已保存但回應遺失,必須以 event id 去重。不要用 body 的 occurred_at 代替簽章時間戳。

更改網址、啟停或重新產生密鑰,會取消尚未送達的舊設定通知,不會把舊通知轉送到新網址。正在傳送中的請求仍可能到達。新設定只接收之後的變更;不自動補發歷史資料。需要初始副本時,可用流程 runs 分頁 API 列出申請,再逐宗讀取 export。

如果要更換接收網站,先準備新網站並完成資料核對,再更改設定。正式及測試流程分開設定;通知 test 欄位也必須驗證。

接駁驗收與開放報名

先完成 OpenDashboard 自己的填表路徑,再驗證外站副本:

1. 在同一流程建立報名、作品等表單步驟,發佈版本並保留入口為未開放。 2. 在獨立驗收流程使用合成資料測試草稿、必填、群組、附件、私人連結、重試和兩個步驟的固定申請編號。 3. 接收網站驗證簽章及流程範圍,先把通知可靠保存,再回應成功;背景工作讀取最新申請,只更新這宗申請對應的副本。 4. 核對重複通知不會多建資料,舊 revision 不會覆蓋新資料,附件屬於同一申請,外站自身管理的評分等欄位保持不變。 5. 確認兩邊成功後才設定正式日期及開放入口。新增外站活動不應自動切換正在使用的活動或改動既有報名。

「通知已送達」代表接收網址已回應 2xx。若外站使用背景工作,它不代表外站資料庫已更新;接收網站仍須保留待處理、完成、失敗及重試紀錄。OpenDashboard 的通知重試與接收網站的處理重試是兩項分開的責任。網站只把已提交項目交給後續業務使用,不能把草稿當成正式提交。

外站處理完成的回報

管理員在「流程 → 網站接入 → 資料通知」查看兩個不同結果:通知已送達代表通知端點接受;網站處理完成代表外站已保存需要的資料及附件。外站尚未回報時顯示等待確認,不能把送達當成資料已落地。

外站驗證通知、讀取最新 export,並完成其本地交易及附件保存後,使用同一應用的伺服器管理金鑰回報:

http
POST /api/apps/v1/workflow-runs/<application-id>/processing-receipts
Authorization: Bearer <app-key>
Content-Type: application/json

{"delivery_id":"<notification-id>","revision":12,"status":"processed"}

失敗時回報 status: "failed" 並帶 error,僅接受 attachments_invalid、source_unavailable 或 processing_failed。不得上傳原始例外、檔名、答案或個人資料。revision 是實際處理的 export 版本,必須不早於通知版本且不晚於現有申請版本。回報只能針對同一應用、測試模式及申請的通知;參加者/流程填表金鑰不能回報。

重複回報安全;較舊或已處理成功的結果不能被失敗降級。回報失敗時外站應重試同一回報,不重建隊伍。管理員可在傳送紀錄對「需要處理」按重試,會重新傳送原通知;接收端仍須按通知 id 去重,並讓已失敗的工作可恢復,不能僅因曾收到便永久忽略。

網站保存資料副本

發佈前勾選「通知我的網站,讓兩邊都有資料」。這允許新版本的變更通知及同步讀取,不會直接啟用接收端。 在流程的「網站接入 → 資料通知」設定 HTTPS 接收網址、啟用通知並安全保存簽章密鑰。 外站後端按照本頁的簽章驗證 → 持久化通知 → 讀取 export 與 files → 以 application_id/revision 更新副本 → processing-receipts 回報結果接駁。

填表使用的流程金鑰沒有同步匯出權限。讀取副本沿用連接應用的伺服器端金鑰,其權限範圍是該應用;不要交給瀏覽器或不可信的第三方。 發佈選項不會把應用金鑰變成只讀或限單一流程的金鑰,也不會撤銷它其他既有管理權限。 若不願提供該應用的後端權限,先不要啟用副本接駁,改用 OpenDashboard 管理介面查看資料。

三種常見組合:OpenDashboard 頁面填表+外站保存副本;自己的網站填表+OpenDashboard 管理;兩邊填表+外站保存副本。 所有組合都由 OpenDashboard 確認正式答案及流程進度;外站修改答案也必須經 OpenDashboard 提交,不可直接修改副本再當作已同步。 通知已送達和資料已保存是不同狀態。接駁驗收須檢查「處理完成」、附件可讀、失敗重試,以及相同通知不產生重複資料。