Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ export default defineConfig({
{ label: "Translating EmDash", slug: "contributing/translating" },
],
},
{
label: "Runbooks",
collapsed: true,
items: [
{ label: "Runbooks Index", slug: "runbooks" },
{
label: "Cloudflare Post-Deploy Operations",
slug: "runbooks/deployment/cloudflare-post-deploy-operations",
},
],
},

{
label: "Themes",
Expand Down
40 changes: 40 additions & 0 deletions docs/src/content/docs/deployment/cloudflare.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,46 @@ wrangler deploy

Your site is now live at `https://my-emdash-site.<your-subdomain>.workers.dev`.

## Manage a deployed site via API

Your deployed site exposes EmDash's API under:

```text
https://my-emdash-site.<your-subdomain>.workers.dev/_emdash/api
```

If you use a custom domain, replace the hostname and keep the `/_emdash/api` path.

Recommended flow for programmatic content operations:

1. In the admin UI, open **Settings > API tokens** (`/_emdash/admin/settings/api-tokens`).
2. Create a **Personal Access Token** with the scopes your integration needs.
3. Copy the token once (it's only shown at creation time).
4. Call EmDash endpoints with:

```http
Authorization: Bearer <token>
```

```bash
curl -H "Authorization: Bearer <token>" \
"https://my-emdash-site.<your-subdomain>.workers.dev/_emdash/api/content/posts"

curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"slug":"hello","data":{"title":"Hello from deploy"},"status":"draft"}' \
"https://my-emdash-site.<your-subdomain>.workers.dev/_emdash/api/content/posts"
```

For browser-based admin workflows, cookies/sessions also work when requests are made from your site, but external scripts should use tokens.

Infrastructure management is separate: deploy/redeploy, bindings, KV/D1/R2 resources, DNS, and env secrets are handled through Cloudflare tooling (Workers/Pages dashboard, `wrangler`, or Cloudflare API), not EmDash.

MCP clients can also use `/_emdash/api/mcp`, and CLI operations use `emdash` with `--url` and `--token`.

For a full post-deploy operational checklist (smoke checks, token flow, and what stays in Cloudflare tooling), see [Cloudflare Post-Deploy Operations](/runbooks/deployment/cloudflare-post-deploy-operations).

## Read Replicas

For globally distributed sites, enable D1 read replication to route read queries to nearby replicas instead of always hitting the primary database. This significantly reduces latency for visitors far from the primary region.
Expand Down
4 changes: 4 additions & 0 deletions docs/src/content/docs/reference/rest-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Generate tokens through the admin interface or programmatically.

## Response format

For post-deploy operational checks that separate EmDash API usage from Cloudflare platform tasks, see [Cloudflare Post-Deploy Operations](/runbooks/deployment/cloudflare-post-deploy-operations).

## Response Format
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I moved the Cloudflare post-deploy runbook link up under the Authentication section and removed the duplicated response-format heading so the section structure stays:

  • Authentication
  • Response format

That keeps the cross-link in a more appropriate place and avoids the duplicated heading.


All responses follow a consistent format. A successful response wraps the result in `data`:

```json
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
title: Cloudflare Post-Deploy Operations
description: Separate EmDash content API operations from Cloudflare infrastructure actions after deployment.
---

import { Steps, Aside } from "@astrojs/starlight/components";

## Scope

Use this runbook after `wrangler deploy` succeeds on a Worker that serves EmDash.

It covers:

- API verification and token-based access patterns,
- what to do for content workflows,
- what remains an infrastructure task outside of EmDash.

## Why this matters

EmDash's admin/content APIs are for **application data operations** only. All deployment and platform controls (`env`, `secrets`, `routes`, DNS, D1/R2 lifecycle) are handled by Cloudflare tooling.

## Preconditions

- EmDash worker URL is known (for example `https://my-emdash-site.<subdomain>.workers.dev` or custom domain).
- At least one `Role.ADMIN` account can access the admin UI to generate API tokens.
- `curl` available for API checks.
- Cloudflare deployment credentials available (`wrangler login` already run) when doing infra actions.

## Runbook

<Steps>

1. **Smoke check deployment surface (no auth required)**

Confirm the Worker answers and setup API is reachable:

```bash
BASE_URL="https://my-emdash-site.<subdomain>.workers.dev"
curl -i "${BASE_URL}/_emdash/api/setup/status"
```

Expect `200` with an `application/json` response containing `needsSetup`.

2. **Get baseline API auth behavior for a known content endpoint**

Confirm unauthorized access fails for protected operations:

```bash
curl -i "${BASE_URL}/_emdash/api/content/posts"
```

Expect `401` when route is available (missing token/cookie). If your instance has not created the `posts` collection yet, you may get `404` instead.

3. **Create and capture a Personal Access Token in the admin UI**

- Open **Settings > API tokens** (`/_emdash/admin/settings/api-tokens`).
- Create a token with only the scopes needed for your integration.
- Export the raw token to your shell immediately (it is shown once):

```bash
export EMDASH_TOKEN="<raw-token-string>"
```

A good first scope set for a publishing script is:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re right that the baseline token guidance was inconsistent with the next verification step.

I’ve updated the runbook to include content:read alongside content:write and media:write, so the subsequent GET /_emdash/api/content/posts check matches the recommended token scope set.

- `content:write`
- `media:write`

4. **Re-check API with bearer token**

```bash
curl -H "Authorization: Bearer ${EMDASH_TOKEN}" \
"${BASE_URL}/_emdash/api/content/posts"

curl -X POST \
-H "Authorization: Bearer ${EMDASH_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"slug":"deploy-smoke","data":{"title":"Deploy smoke"},"status":"draft"}' \
"${BASE_URL}/_emdash/api/content/posts"
```

If POST returns `403`, the token is missing scope for the route.
If POST returns `400`, verify your payload includes a valid object under `data` (for example `{"data": {...}}`).
If you get `404`, confirm the collection exists and your token endpoint URL is correct.

5. **Use tool endpoints when needed**

MCP clients and automation that supports JSON-RPC can connect at:

```text
${BASE_URL}/_emdash/api/mcp
```

CLI usage should set `--url ${BASE_URL}` and `--token ${EMDASH_TOKEN}`.

6. **Perform platform-level actions through Cloudflare control plane**

Use Cloudflare dashboard or Wrangler for:

- deploy/redeploy,
- secrets and bindings,
- DNS and custom domain changes,
- D1/R2 management and migrations,
- observability and log streaming.

Treat these as separate from EmDash runtime API usage:

```bash
# Example: inspect runtime logs during an issue
wrangler tail

# Example: update secret values
wrangler secret put EMDASH_ENCRYPTION_KEY
```

</Steps>

## Escalation paths

### If protected API calls return `404`

This can mean setup has not completed or collection names are different. Re-run setup in admin and verify collection slugs.

### If token operations return `401`

Recreate the token and ensure `Authorization` header is exactly `Bearer <token>` (no quotes).

### If deploy succeeds but API writes still fail

Use platform logs first before changing application code:

```bash
wrangler tail
```

If the worker logs show DB errors, check D1 binding names and migration state in `wrangler.jsonc` vs `emdash` config.

<Aside type="note">

Keep this distinction in incident notes:

- **EmDash API incidents:** missing/invalid tokens, scope errors, content endpoint regressions.
- **Cloudflare incidents:** bindings, secrets, DNS, replication, deploy target, and rollout state.

</Aside>
26 changes: 26 additions & 0 deletions docs/src/content/docs/runbooks/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Runbooks
description: Operational runbooks for platform upkeep, validation, and incident response.
---

Runbooks are the practical checklists behind this repo. They are intentionally concrete and command-driven so an agent or maintainer can execute the same sequence quickly.

## Available runbooks

- [Cloudflare Post-Deploy Operations](./deployment/cloudflare-post-deploy-operations): verify API access, token-based ops, and infrastructure handoff after deploy.

## Purpose and maintenance rhythm

These runbooks are written for:

- fast recovery after regressions in behavior-critical paths,
- release prep where repeatable validation matters,
- onboarding scripts for new automation actors (including the Master-Orchestrator).

Each runbook includes:

- expected prerequisites,
- exact commands,
- success criteria,
- known failure modes,
- a short note on what to do when the environment is not clean.
Loading