EmDash는 항목의 게시된 버전을 게시되지 않은 변경과 분리해 둡니다. 관리자 패널, REST API, 명령줄 인터페이스(CLI), Model Context Protocol(MCP) 도구는 동일한 수명 주기 규칙을 사용합니다.
항목은 draft, scheduled, published일 수 있습니다. 게시된 항목은 초안과 미래의
일정도 가질 수 있습니다. 방문자는 예약된 초안이 게시될 때까지 라이브 리비전을 계속 받습니다.
휴지통은 상태와 별개입니다. 휴지통에 들어간 항목은 수명 주기 메타데이터를 유지하지만 일반
콘텐츠 읽기에서는 제외됩니다.
상태 전환
다음 표는 콘텐츠 상태, 리비전 포인터, 게시 타임스탬프에 대한 표준 계약입니다. “변경 없음”은 작업이 저장된 값을 유지함을 의미합니다.
| 작업 | 시작 상태 | 결과 | 리비전 효과 | publishedAt | scheduledAt | 반복 호출 |
|---|---|---|---|---|---|---|
| 변경 저장 | 모든 활성 항목 | 상태가 바뀌지 않음 | 리비전 지원 컬렉션에서는 라이브 리비전이 공개된 채로 초안 리비전을 교체 | 변경 없음 | 변경 없음 | 제공된 _rev는 오래된 저장을 거부. 생략하면 REST 쓰기는 무조건적 |
| 게시 | 초안, 예약됨, 또는 게시됨 | 게시됨 | 초안 리비전을 라이브로 승격하고 초안 포인터를 지움 | 첫 게시 시 설정. 이후 게시에서는 인가된 호출자가 덮어쓰지 않는 한 유지 | 지움 | 라이브 콘텐츠와 게시 시각은 유지하지만 새 _rev를 반환 |
| 기한 도래 시 게시 | 예약됨, 또는 예약된 초안이 있는 게시됨 | 게시됨 | 게시와 동일 | 첫 게시에서는 예약 시각 사용. 라이브 콘텐츠 위에 새 초안을 게시할 때는 기존 값 유지 | 지움 | 이후 스케줄러 패스는 일정이 이미 지워진 항목을 건너뜀 |
| 게시 취소 | 모든 활성 항목 | 초안 | 라이브 포인터를 지움. 기존 초안을 유지하거나 라이브 리비전에서 생성 | 유지 | 지움 | 이미 단순 초안인 항목은 바뀌지 않음 |
| 예약 | 초안, 예약됨, 또는 게시됨 | 초안은 예약됨이 됨. 게시된 항목은 게시됨 유지 | 변경 없음 | 변경 없음 | 요청된 미래 시각으로 설정 | 기존 일정을 교체하고 새 _rev를 반환 |
| 예약 해제 | 예약됨, 또는 일정이 있는 게시됨 | 예약된 항목은 초안이 됨. 게시된 항목은 게시됨 유지 | 변경 없음 | 변경 없음 | 지움 | 일정이 없는 항목은 바뀌지 않음 |
| 초안 버리기 | 모든 활성 항목 | 상태가 바뀌지 않음 | 초안 포인터를 지움. 라이브 리비전은 변경되지 않음 | 변경 없음 | 변경 없음 | 초안이 없는 항목은 바뀌지 않음 |
| 휴지통으로 이동 | 모든 활성 항목 | 휴지통에 들어가고 일반 읽기에서 제외 | 유지 | 유지 | 유지 | 이미 휴지통에 있는 항목 요청은 not found 반환 |
| 휴지통에서 복원 | 휴지통 | 초안 | 라이브 포인터를 지움. 초안 포인터는 유지 | 유지 | 지움 | 아직 휴지통에 있는 항목이 필요 |
| 영구 삭제 | 휴지통 | 제거됨 | 항목과 리비전을 제거 | 제거됨 | 제거됨 | 반복하거나 취소할 수 없음 |
| 리비전 복원 | 모든 활성 항목 | 상태가 바뀌지 않음 | 리비전 지원 컬렉션에서는 선택한 리비전 복사본으로 초안을 교체. 라이브 리비전은 변경되지 않음 | 변경 없음 | 변경 없음 | 새 리비전을 만들고 새 _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 서버 참고를, 이벤트 페이로드는 훅 참고를 보세요.