Skip to content

Publish and rollback

Policies are versioned. You publish drafts to activate them, and you roll back to previous versions when something goes wrong.

The model

  • Every edit creates a new row in the policies table with published_at = NULL — a draft.
  • Publish stamps published_at = clock_timestamp() on a draft. The latest published_at is the active version.
  • Rollback copies an older version’s body into a brand-new draft and publishes it. The old version stays in the table. No destructive operations.

This means every change is reversible by going forward, not backward — you create a new published row.

Via the dashboard

Open /policies/{class_id}. The versions rail on the left shows every version with:

  • a green dot = currently active
  • a grey dot = published, not active
  • a teal dot = draft (unpublished)

Click any version to see its body on the right. Then:

Source stateAvailable action
DraftPublish this draft — stamps published_at, becomes active
Published but not activeRollback to this — creates a new draft from this body and publishes it
Currently active(no actions — already in use)

Via the CLI

There are no CLI commands for policy lifecycle yet. Use HTTP or the dashboard.

Via HTTP

List versions for a class

Terminal window
curl http://localhost:8000/api/v1/policy/class/<class_id>/versions

Returns newest first. The active one has published_at set; the rest are drafts or older published versions.

Get the active policy

Terminal window
curl http://localhost:8000/api/v1/policy/class/<class_id>/active

Create a draft

Terminal window
curl -X POST http://localhost:8000/api/v1/policy/class/<class_id>/drafts \
-H "Content-Type: application/json" \
-d @new-policy-body.json

Returns 201 Created with the new row, published_at: null.

Publish a draft

Terminal window
curl -X POST http://localhost:8000/api/v1/policy/<policy_id>/publish

Returns the same row with published_at set.

Rollback to a previous version

Terminal window
curl -X POST http://localhost:8000/api/v1/policy/class/<class_id>/rollback/<target_version>

Returns a brand-new published row whose body is copied from target_version.

What you can’t do

  • Edit a published row in place — no PUT or PATCH on policy bodies. Always create a new draft.
  • Delete a version — nothing destructive. If a body is sensitive, rotate to a newer draft and the older content stays in the table for audit; full deletion is a Postgres-level operation.
  • Publish two drafts to the same version — each draft creates a new monotonic version number per class.

Quayside re-validates on rollback

When you roll back to version N, Quayside re-validates the old body through the current Pydantic schema before publishing the new copy. This means: if the schema has tightened since you originally wrote version N, the rollback fails — you have to write a fresh draft instead. That’s a feature, not a bug.

Audit

Every policy version stays in the table forever. Joining your access logs against the published_at timestamps gives you a complete history of “what policy was active at time T, and who pushed the change.” For deployments with stricter compliance needs, layer a separate “who clicked publish” log on top of the API endpoints.