← Design · c121

plan/03-publishing.md

03 · Publishing: tray + Changes page (Wave 2)

TL;DR: local staging stays; "Save to draft" puts edits into one shared Policy Config draft (D4). The Changes page becomes: the shared draft (v13 · N pending changes, author per line, BlastRadius of the whole draft, Publish with a note), Policy Config versions (v13 live, rollback with a note, propagation bar), the log, and the config as syntax-coloured JSON with Download and Import.

Owns: app/pages/pages/phase4/mock/changes.vue, app/components/governance/mock/PublishTray.vue, app/layouts/governance-mock.vue, new app/components/governance/mock/ConfigJson.vue. Uses 00's publishing API and configJson/importConfig/fleetSummary, 01's BlastRadius.

Today

  • Tray PublishTray.vue: "Locally Staged Edits · N" (l.23), numbered list, "Preview changes in dashboard" (l.38–41), "Submit as draft…" title + note (l.42–54), "Discard all", footer "Live v13 · 97 of 100 endpoints · 2 open drafts · Changes →" (l.64–69).
  • changes.vue: drafts table with approval toggle (l.8–73), versions table with lineage + propagation bar + roll back (l.76–125), log (l.128–138). No JSON.

Steps

  1. Tray. Title stays "Locally Staged Edits · N" (Mark's 10-21 polish holds). Each line shows its reason when present; a loosening line without reason can't exist (00 refuses it). Replace "Submit as draft…" with "Save to draft" (no title; one click; optional note per batch is fine). Keep "Preview changes in dashboard" (now ?preview=draft + local edits). Footer: "Live Policy Config v13 · 97 of 100 endpoints · 6 pending changes · Changes →"; endpoints count links to the Endpoints page (06's URL).
  2. Changes: Pending. Header "Policy Config v13 · 6 pending changes". Itemized list: change · reason · author · when (who changed what and when, I). <BlastRadius variant="full" :impact="previewDraft(draft.changes)"> above the list (L: "use this component to visually, simply, clearly explain what the changes do"). Validation summary (00 errors, e.g. exception on a removed team) blocks Publish with the affected item named (I). Publish… → note (required) → "Publish v14". Discard draft. Changes marked redundant after a rollback show struck with "already live".
  3. Changes: Versions. Row label "Policy Config v13" + LIVE pill; drop branch lineage words that only made sense for multi-draft (keep "rolled away from"). Propagation bar per the note (../sources/logseq-propagation.png): green bar "97 of 100 endpoints · 3 still on earlier versions" on live, grey on others. "Roll back here…" with required note. Per row: View JSON / Download (policy-config-v13.json).
  4. ConfigJson.vue. A read-only code view of configJson(v) with syntax colouring done in the component (tokenise keys / strings / numbers / booleans with a small regex; no new dependency), line numbers, copy, download. Anchor #json; opens for the live version by default, a version picker for others and "draft".
  5. Import (#import): paste or file → importConfig() → errors listed, or "Staged N edits — review them in the tray". States: empty, invalid JSON, validation errors, success.
  6. Remove the approval toggle, Approve / Promote / Reconcile, the "viewing as" approval logic; ?as= still decides the author of new edits.
  7. Layout: only if the tray mount needs a prop change.

Done when

Flow: stage two edits on S3 → Save to draft → Changes shows 8 pending with authors + BlastRadius → Publish with note → v14 live, bar resets → Roll back to v13 with note → draft changes re-based. JSON view + download + import (valid, invalid). Screenshots shots/03-*.png.

Look for (review)

Nowhere says "draft D-n", "promote", "approve"; version strings are integers; JSON is the whole org config, not a policy.

Qpoint Brand Style Guide