A deck manifest defines membership

A deck with a non-empty Slides manifest presents exactly the nodes named by that list, in that order. A sibling Slide node that is absent from the manifest can remain as a draft or archive, but it does not appear in the deck counter, Prev/Next navigation, or Present mode.

This is more than a sorting rule. Authors use the manifest to insert, reorder, and remove slides without moving or deleting their source nodes. Appending unlisted siblings makes removed slides silently return to the live talk.

The ordering rules are:

  1. A non-empty manifest defines membership and order.
  2. An unknown manifest reference is omitted until its node exists.
  3. A duplicate reference appears once, at its first position.
  4. A slide whose parent is not a deck, or a deck without a manifest, falls back to sibling MeshNode.Order, then path.

The SAV Generalversammlung 2026 deck exposed the defect: its manifest named 18 slides while four retired sibling drafts remained under the deck. The presenter displayed Slide 13 / 22 and could navigate into those drafts. Keeping navigation faithful to the manifest restores the authored 18-slide talk without deleting the drafts.

A viewer's deck holds only the slides that viewer may read

Membership is decided per viewer as well. The sibling query behind the counter, Prev/Next and Present mode runs as the viewer the slide page renders for, so a slide the viewer holds no read grant on is not in their deck: it is not counted, Prev/Next steps over it, and Present mode never lands on it. A manifest entry that names such a slide is omitted for that viewer, exactly as an unknown reference is. A viewer who may read none of the siblings sees an empty deck.

The query used to run as the platform identity, on the argument that order and neighbours are only navigation. They are data: every sibling's path, name and order, shown to a viewer who may read none of them (#2802). The viewer is the one the layout host captured when the page opened (LayoutAreaHost.ViewerContext), installed around the query's subscribe, because the deck is consumed in deferred continuations where the ambient identity does not flow. Pinned by SlideDeckReadAsViewerTest (src/MeshWeaver.Publish.Test), which compiles this type's own source.

The deck's own views read the same way. Publish/Deck does not reuse the slide's sibling map: its Overview nav and Present walk resolve the manifest one node stream per path, or run the deck's query/subtree selection. Both reads used to be issued in a deferred continuation of the deck node's stream with no viewer installed — the node-stream cache applies its per-user gate only to a real user, and the query filters by whoever is ambient — so the deck served a slide the viewer may not read. They now run under the same captured viewer (DeckLayoutAreas.AsViewer); a manifest entry the cache refuses for that viewer is answered absent and omitted, any other fault still surfaces. Pinned by DeckReadsSlidesAsViewerTest, which compiles the Deck's own source.