# Published Page Deletion Workflow

**Date**: 2025-01-18
**Platform**: Modyo Channels
**Status**: ✅ Verified and Working

---

## Overview

This document describes the correct workflow for deleting a **published page** in Modyo. Published pages require a three-step process: unpublish, archive workflow, then delete.

## Three-Step Workflow

### Step 1: Unpublish the Page

**Endpoint**: `POST /sites/{site_id}/layout_pages/{id}/unpublish`

**MCP Tool**: `page-unpublish`

**Request Body**:
```json
{
  "layout_page": {
    "unpublish_at": ""
  }
}
```

**Empty string** (`""`) means "unpublish immediately". For scheduled unpublish, use ISO 8601 datetime:
```json
{
  "layout_page": {
    "unpublish_at": "2025-12-31T23:59:59Z"
  }
}
```

**Example Usage**:
```typescript
page-unpublish({
  platformSlug: "fed-team",
  siteId: 4606,
  pageId: 175396
})
```

**What Happens**:
- Page is removed from live site
- Page status changes from "published" to "unpublished"
- Page remains in Modyo admin but not visible to public
- Workflow remains active

---

### Step 2: Archive the Workflow

**Endpoint**: `POST /workflows/{workflow_id}/archive`

**MCP Tool**: `page-archive`

**Request Body**:
```json
{
  "app_type": "site",
  "app_id": 4606
}
```

**Example Usage**:
```typescript
page-archive({
  platformSlug: "fed-team",
  siteId: 4606,
  pageId: 175396
})
```

**What Happens**:
- Tool automatically gets `workflow_id` from page
- Archives the workflow associated with the page
- Page can now be safely deleted
- Workflow history is preserved

**Important**: The `page-archive` tool handles getting the workflow_id automatically. You don't need to find it manually.

---

### Step 3: Delete the Page

**Endpoint**: `DELETE /sites/{site_id}/layout_pages/{id}`

**MCP Tool**: `page-delete`

**Request Body**: Empty (no body required)

**Example Usage**:
```typescript
page-delete({
  platformSlug: "fed-team",
  siteId: 4606,
  pageId: 175396
})
```

**What Happens**:
- Page is permanently deleted from Modyo
- Page record removed from database
- This operation cannot be undone

---

## Complete Workflow Example

```typescript
// Full workflow to delete a published page
const platformSlug = "fed-team";
const siteId = 4606;
const pageId = 175396;

// Step 1: Unpublish
await page-unpublish({
  platformSlug,
  siteId,
  pageId
  // layout_page is optional - omit for immediate unpublish
});

// Step 2: Archive workflow
await page-archive({
  platformSlug,
  siteId,
  pageId
});

// Step 3: Delete page
await page-delete({
  platformSlug,
  siteId,
  pageId
});
```

---

## Authentication: Bearer Token vs CSRF Token

### Browser Authentication (Session-Based)

Browser requests include `authenticity_token` in the request body:

```bash
curl 'https://fed-team.modyo.cloud/api/admin/sites/4606/layout_pages/175396/unpublish' \
  -H 'content-type: application/json' \
  -b 'cloud-prod_session=...' \
  --data-raw '{"layout_page":{"unpublish_at":""},"authenticity_token":"pGgiNhe..."}'
```

**Why**: Browsers use session cookies for authentication, requiring CSRF protection via `authenticity_token`.

### API Authentication (Bearer Token)

MCP tools use Bearer token in Authorization header:

```bash
curl 'https://fed-team.modyo.cloud/api/admin/sites/4606/layout_pages/175396/unpublish' \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer YOUR_API_TOKEN' \
  --data-raw '{"layout_page":{"unpublish_at":""}}'
```

**Why**: Bearer tokens provide authentication without cookies, eliminating need for CSRF tokens.

**IMPORTANT**: ✅ **CSRF tokens are NOT required for API calls with Bearer tokens**

Our MCP implementations correctly:
- ✅ Use Bearer token authentication (handled by `FetchRepositoryBase`)
- ✅ Do NOT include `authenticity_token` in request bodies
- ✅ Send proper request body structure matching API expectations

---

## Home Page Restriction

**⚠️ CRITICAL**: Home pages (path `/` or empty `""`) **CANNOT** be unpublished or deleted via API.

This is a **Modyo platform protection** to prevent accidentally breaking the site.

**Home Page Detection**:
- Path is `/` (root)
- Path is `""` (empty string)
- Page type is `home` or `homelayoutpage`

**What Happens**:
Both `page-unpublish` and `page-delete` tools will throw an error:
```
Cannot unpublish home page (ID: 175381, path: "/").
Home pages are protected by Modyo platform and cannot be unpublished or deleted via API.
If you need to change the home page:
1. Create a new page to be the home page,
2. Update site settings to set the new home page,
3. Then you can unpublish the old home page.
```

**Workaround**:
1. Create a new page to serve as the home page
2. In Modyo Admin UI → Channels → Sites → Settings
3. Change the home page to the new page
4. Now the old page can be unpublished/deleted

---

## Page States and Allowed Operations

| Page State | Can Unpublish | Can Archive | Can Delete | Notes |
|------------|---------------|-------------|------------|-------|
| Draft | ⚠️ No-op | ✅ Yes | ✅ Yes | Already unpublished |
| Review | ⚠️ No-op | ✅ Yes | ✅ Yes | Already unpublished |
| Scheduled | ✅ Yes | ✅ Yes | ⚠️ Unpublish first | Cancel scheduled publish |
| Published | ✅ Yes | ✅ Yes | ⚠️ Unpublish first | Requires 3-step workflow |
| Home Page | ❌ No | ❌ No | ❌ No | Protected by platform |

**Legend**:
- ✅ Yes: Operation allowed and works
- ⚠️ Unpublish first: Requires unpublish before deletion
- ⚠️ No-op: Operation succeeds but has no effect
- ❌ No: Operation blocked by platform

---

## Error Handling

### "Cannot unpublish home page"
**Cause**: Attempting to unpublish a page with path `/` or ``
**Solution**: Change site home page in admin UI settings first

### "Page does not have an associated workflow"
**Cause**: Attempting to archive a page without a workflow
**Solution**: This is rare. Contact platform admin or skip archive step

### "Fetch error (400): Bad Request"
**Cause**: Invalid request body structure
**Solution**: Verify request body matches documented format (our tools handle this correctly)

### "Fetch error (404): Not Found"
**Cause**: Page ID doesn't exist or already deleted
**Solution**: Verify page ID is correct using `page-list` or `page-get`

### "Fetch error (403): Forbidden"
**Cause**: Insufficient permissions
**Solution**: Verify API token has appropriate permissions for page operations

---

## Implementation Details

### Repository Methods

**PagesRepository** (`src/repositories/channels/pages/PagesRepository.ts`):
```typescript
async unpublishPage(
  siteId: number,
  pageId: number,
  data?: Record<string, unknown>,
): Promise<void> {
  return this.fetchClient.post(
    `/sites/${siteId}/layout_pages/${pageId}/unpublish`,
    { layout_page: data ?? {} }  // Wraps in layout_page key
  );
}

async deletePage(siteId: number, pageId: number): Promise<void> {
  return this.fetchClient.delete(
    `/sites/${siteId}/layout_pages/${pageId}`
    // No body required
  );
}
```

**WorkflowsRepository** (`src/repositories/channels/workflows/WorkflowsRepository.ts`):
```typescript
async archiveWorkflow(
  workflowId: number,
  params: ArchiveWorkflowParams,
): Promise<void> {
  return this.fetchClient.post(
    `/workflows/${workflowId}/archive`,
    params  // { app_type: "site", app_id: siteId }
  );
}
```

### Tool Implementations

All three tools extend `ToolBase` and use the repository pattern:

1. **Unpublish Tool** (`src/tools/channels/pages/Unpublish.ts`)
   - Validates home page protection
   - Calls `repo.unpublishPage(siteId, pageId, layout_page)`
   - Repository wraps data in `layout_page` key

2. **Archive Tool** (`src/tools/channels/pages/Archive.ts`)
   - Gets page to retrieve `workflow_id`
   - Validates workflow exists
   - Calls `workflowRepo.archiveWorkflow(workflow_id, {app_type, app_id})`

3. **Delete Tool** (`src/tools/channels/pages/Delete.ts`)
   - Validates home page protection
   - Calls `repo.deletePage(siteId, pageId)`
   - No request body required

---

## Testing

All three tools have comprehensive unit tests:

- `tests/unit/tools/channels/pages/Unpublish.test.ts` - 11 tests
- `tests/unit/tools/channels/pages/Archive.test.ts` - 7 tests
- `tests/unit/tools/channels/pages/Delete.test.ts` - Tests include home page validation

**Test Coverage**:
- ✅ Successful operations
- ✅ Home page protection
- ✅ Error handling
- ✅ Different page states
- ✅ Parameter validation

Run tests:
```bash
npm test -- test/tools/channels/pages
```

---

## Related Documentation

- [PAGE_UNPUBLISH_ISSUE.md](../issues/PAGE_UNPUBLISH_ISSUE.md) - Investigation notes
- [TESTING_UNPUBLISH.md](../issues/TESTING_UNPUBLISH.md) - Testing guide
- [MODYO_PAGE_TYPES.md](../MODYO_PAGE_TYPES.md) - Page types reference
- [Modyo API Documentation](https://docs.modyo.com/en/platform/channels/pages.html)

---

## Summary

**Key Takeaways**:

1. ✅ Published pages require 3 steps: unpublish → archive → delete
2. ✅ Bearer token authentication is sufficient (no CSRF tokens needed)
3. ✅ Home pages are protected and cannot be unpublished/deleted via API
4. ✅ All MCP tools implement correct request body structure
5. ✅ Workflows must be archived before page deletion

**MCP Tools**:
- `page-unpublish` - Step 1: Remove from live site
- `page-archive` - Step 2: Archive workflow
- `page-delete` - Step 3: Permanently delete

**Validation**: All tools validate home page protection and provide helpful error messages.

---

**Last Updated**: 2025-01-18
**Verified Against**: Modyo Platform (fed-team.modyo.cloud, site ID: 4606)
**Status**: ✅ Production Ready
