EmDash 將條目的已發佈版本與未發佈的變更分開保存。管理面板、 REST API、命令列介面(CLI)以及 Model Context Protocol(MCP)工具使用相同的生命週期 規則。
條目可以是 draft、scheduled 或 published。已發佈的條目也可以有草稿和未來的
排程:在排程的草稿發佈之前,訪客會繼續收到線上修訂。
回收筒與狀態是分開的。已移入回收筒的條目保留其生命週期中繼資料,但會
從普通內容讀取中排除。
狀態轉換
下表是內容狀態、修訂指標與發佈時間戳記的規範契約。 「無變更」表示操作會保留已儲存的值。
| 操作 | 起始狀態 | 結果 | 修訂效果 | publishedAt | scheduledAt | 重複呼叫 |
|---|---|---|---|---|---|---|
| 儲存變更 | 任意活動條目 | 狀態不變 | 在支援修訂的集合上,取代草稿修訂,同時線上修訂保持公開 | 無變更 | 無變更 | 提供的 _rev 會拒絕過期儲存;省略則使 REST 寫入無條件 |
| 發佈 | 草稿、已排程或已發佈 | 已發佈 | 將草稿修訂提升為線上並清除草稿指標 | 首次發佈時設定;後續發佈保留,除非經授權的呼叫方覆寫 | 清除 | 保留線上內容與發佈時間,但回傳新的 _rev |
| 到期時發佈 | 已排程,或已發佈且有排程草稿 | 已發佈 | 與發佈相同 | 首次發佈使用排程時間;在線上內容上發佈新草稿時保留現有值 | 清除 | 後續排程器回合會跳過排程已清除的條目 |
| 取消發佈 | 任意活動條目 | 草稿 | 清除線上指標;保留現有草稿或從線上修訂建立草稿 | 保留 | 清除 | 已是普通草稿的條目不變 |
| 排程 | 草稿、已排程或已發佈 | 草稿變為已排程;已發佈條目保持已發佈 | 無變更 | 無變更 | 設為請求的未來時間 | 取代現有排程並回傳新的 _rev |
| 取消排程 | 已排程,或已發佈且有排程 | 已排程條目變為草稿;已發佈條目保持已發佈 | 無變更 | 無變更 | 清除 | 沒有排程的條目不變 |
| 捨棄草稿 | 任意活動條目 | 狀態不變 | 清除草稿指標;線上修訂保持不變 | 無變更 | 無變更 | 沒有草稿的條目不變 |
| 移入回收筒 | 任意活動條目 | 在回收筒中且不出現在普通讀取中 | 保留 | 保留 | 保留 | 對已在回收筒中的條目的請求回傳未找到 |
| 從回收筒還原 | 在回收筒中 | 草稿 | 清除線上指標;保留任何草稿指標 | 保留 | 清除 | 需要仍在回收筒中的條目 |
| 永久刪除 | 在回收筒中 | 已移除 | 移除條目及其修訂 | 已移除 | 已移除 | 無法重複或復原 |
| 還原修訂 | 任意活動條目 | 狀態不變 | 在支援修訂的集合上,用所選修訂的複本取代草稿;線上修訂保持不變 | 無變更 | 無變更 | 建立新修訂並回傳新的 _rev |
在不支援修訂的集合上,儲存與發佈使用內容列,而不是線上與草稿指標。 還原修訂會將所選欄位值直接寫入該列。
在支援修訂的集合上還原修訂不會發佈它。在審閱還原的草稿後 再發佈該條目。
權限與寫入保護
權限取決於擁有權。Author 可對其擁有的條目執行動作;Editor 可對任意條目執行相同 動作。永久刪除需要 Admin。
在發佈期間設定 publishedAt 需要 content:publish_any,即使呼叫方擁有該
條目。
REST API 在所示位置接受 _rev 作為選用的樂觀並行前置條件。MCP 工具
對相同操作要求它,因此代理必須在變更前讀取條目。過期權杖
回傳 CONFLICT。受條目鎖定保護的管理後台與 REST 寫入會回傳 ENTRY_LOCKED,除非經授權的
請求使用支援的鎖定覆寫。MCP 寫入不參與條目鎖定。
| 操作 | 權限 | REST _rev | MCP _rev | 管理後台與 REST 鎖定 | 鉤子 |
|---|---|---|---|---|---|
| 儲存變更 | content:edit_own 或 content:edit_any | 選用 | 必要 | 強制 | content:beforeSave、content:afterSave |
| 發佈 | content:publish_own 或 content:publish_any | 選用 | 必要 | 強制 | content:beforePublish、content:afterPublish |
| 取消發佈 | content:publish_own 或 content:publish_any | 選用 | 必要 | 強制 | content:beforeUnpublish、content:afterUnpublish |
| 排程 | content:publish_own 或 content:publish_any | 選用 | 必要 | 強制 | content:beforeSchedule、content:afterSchedule |
| 取消排程 | content:publish_own 或 content:publish_any | 不接受 | 不接受 | 強制 | content:afterUnschedule |
| 捨棄草稿 | content:edit_own 或 content:edit_any | 選用 | 必要 | 強制 | 無 |
| 移入回收筒 | content:delete_own 或 content:delete_any | 不接受 | 不接受 | 強制 | content:beforeDelete、content:afterDelete |
| 從回收筒還原 | content:edit_own 或 content:edit_any | 不接受 | 不接受 | 不強制 | content:afterRestore |
| 永久刪除 | content:delete_permanent | 不接受 | 不接受 | 不強制 | content:afterDelete |
| 還原修訂 | content:edit_own 或 content:edit_any | 不接受 | 不接受 | 不強制 | 無 |
content:afterDelete 事件在條目移入回收筒時將 permanent 設為 false,在永久刪除後
設為 true。成功的 after 鉤子在狀態變更後執行,並可能在回應已傳送後
執行。外掛可從相應的 before 鉤子拒絕儲存、發佈、取消發佈、排程或移入回收筒。
當排程發佈到達到期時間時,它使用發佈鉤子。如果
content:beforePublish 鉤子拒絕該排程嘗試,EmDash 會清除排程並執行
content:afterUnschedule。
衝突與重試
對下一次受保護操作使用每次讀取或寫入回傳的 _rev。EmDash 會拒絕過期權杖,
而不是取代並行變更。再次讀取條目,審閱更新的狀態,然後決定是否重試。
錯誤回應並不總是證明沒有任何狀態變更。如果連線在用戶端收到回應之前 結束,請在重試生命週期操作之前讀取條目。這也能防止 重試取代另一位編輯者已完成的工作。
修訂還原會一併確認還原的內容及其稽核修訂。若任一寫入 失敗,EmDash 會保留請求之前的內容與修訂歷程。
HTTP 請求與回應結構描述見 REST API 參考,工具輸入見 MCP 伺服器參考,事件負載見 鉤子 參考。