feat(stacks): add Stack Dossier tab with operator notes and Markdown export (#1326)

* feat(stacks): add Stack Dossier tab with operator notes and Markdown export

Add a Dossier tab beside Anatomy and Activity on the stack detail panel. It
shows a read-only summary auto-derived from the stack's Compose anatomy
(services, ports, volumes, network, restart policy, env file, source) plus an
editable form for the context Sencho cannot infer: purpose, owner, access URLs,
static IP, VLAN, and firewall, reverse-proxy, backup, upgrade, recovery, and
custom notes.

Notes persist per stack and per node in a new stack_dossiers table, reached
transparently through the remote-node proxy so a remote stack's dossier
round-trips to the node that owns it. Reading a dossier needs stack read
permission; saving needs stack edit. The tab exports a single Markdown document
combining the generated facts and the operator notes, with copy-to-clipboard and
download actions; env values are never exported, only variable names and counts.

Available on all tiers. The standalone anatomy copy-as-Markdown shortcut is
removed since the Dossier export supersedes it.

* fix(stacks): gate dossier reads/writes on stack existence; clear dossier on node delete

A dossier endpoint validated the stack name but not that the stack exists, so an
editor could PUT a dossier for a name with no stack, leaving an orphan row that a
later stack of the same name would inherit. Require the stack to exist (existing
requireStackExists guard) on the dossier GET and PUT, returning 404 otherwise.

Also clear a node's stack_dossiers rows when the node is deleted, alongside the
other node-scoped cleanup, so removing a node leaves no orphan dossiers.

Docs: scope the "no secret exported" statement to the generated facts (which only
ever carry variable names and counts) and clarify that operator notes are
exported exactly as written.
This commit is contained in:
Anso
2026-06-06 22:21:30 -04:00
committed by GitHub
parent af4083175c
commit 57fe430db8
12 changed files with 1034 additions and 33 deletions
+4 -6
View File
@@ -65,9 +65,9 @@ When the container has a compose service name attached, an extra `⋮` button ap
## Anatomy panel
The right column shows the **Anatomy panel** by default: a read-only summary of the compose file with a tab for the stack's activity timeline.
The right column shows the **Anatomy panel** by default: a read-only summary of the compose file, alongside tabs for the stack's activity timeline and its dossier.
The header strip carries two tabs (**Anatomy** and **Activity**) plus shortcuts to **copy md** (export the summary as Markdown), open the **files** tab, and enter **edit** mode. The shortcuts belong to the strip itself and remain available regardless of which tab is active.
The header strip carries three tabs (**Anatomy**, **Activity**, and **Dossier**) plus shortcuts to open the **files** tab and enter **edit** mode. The shortcuts belong to the strip itself and remain available regardless of which tab is active.
The Anatomy tab lists:
@@ -81,11 +81,9 @@ The Anatomy tab lists:
When an image update is available, an inline banner appears at the top of the panel. Its tone follows the version-bump severity: `safe to apply` (patch), `review recommended` (minor), `breaking changes possible` (major), or `review required` when the bump cannot be classified. The banner has an inline **apply** button that runs the same operation as the action bar's **Update**; it is hidden for roles that lack the `stack:edit` permission and when the bump is flagged as blocked.
### Copy as Markdown
### Markdown export
The **copy md** shortcut copies the current anatomy to your clipboard as a Markdown document: the stack name, services, a ports table, a volumes table, the restart policy, the env file with its variable count, any missing variables, the network, and the source. Paste it straight into a README, a Git repository, Obsidian, BookStack, or a support thread to keep a written record of how a stack is wired.
Empty sections render cleanly as `none`, and the export carries only variable **names** and **counts**, never the values stored in your `.env` file.
The **Dossier** tab turns this same anatomy into an exportable Markdown document, combined with your own operator notes, with copy-to-clipboard and download actions. Empty sections render cleanly as *none*. The generated facts carry only variable **names** and **counts**, never the values stored in your `.env` file; your own notes are exported as written. See [Stack Dossier](/features/stack-dossier).
The **Activity** tab streams every operational event scoped to this stack. See [Stack Activity](/features/stack-activity) for the full event catalog and attribution rules.