Taking a talk deck public
A talk deck goes public the moment a link leaves the building — a LinkedIn post, a slide photographed in the room, a line in a conference programme. Everything the deck POINTS AT is public at the same instant, and that is where it breaks. This page is the checklist, written from the 2026-09-10 dry run of the SAV Generalversammlung talk, one day before it went out.
The rule the whole page reduces to: walk the visitor's path yourself, signed out, then signed in as somebody who owns nothing. Neither state is the one you develop in, and each hides a different half of the funnel.
1. What a signed-out visitor actually reaches
Grants are per node and they inherit downward, so a deck can be public while its parent is not. Check each hop the deck names, not the deck alone:
mcp search "path:{Partition} scope:subtree nodeType:AccessAssignment" # every grant
mcp get "@{Partition}/_Policy" # publicRead: true? absent = no
Both Anonymous (not logged in) and Public (any signed-in account) are needed — they are
different subjects, and a deck carrying only Public looks fine to you and bounces the world.
Measured on the SAV deck: Event/SavGeneralversammlung2026/Talk carried both and rendered
anonymously; its PARENT Event/SavGeneralversammlung2026 carried neither, so the breadcrumb one
click above the deck dead-ends at /login. Nothing warns you — the deck works.
2. Where the visitor is asked to register
On memex there is no local account: /login offers Microsoft, Google, LinkedIn and GitHub, and
nothing else. So "register" always means an external identity, and the ask lands at the first gated
hop — typically /{package}/Subscribe, which for a signed-out visitor renders the plan pitch and
"Please sign in to subscribe — your enrollment is stored with your account."
A gated child does not 404: it REDIRECTS to that paywall. /ReinsuranceDemo/Walkthrough becoming
/ReinsuranceDemo/Subscribe is the funnel working, not a broken link.
3. 🚨 The account you test with decides what you can see
Two traps, both of which make a broken funnel look healthy:
- An all-access plan hides the paywall entirely.
SubscriptionFact.Coversis consulted BEFORE the contact-sales and price branches, anddedicatedis all-access (PlanTiers.IsAllAccess), so a holder is auto-unlocked on arrival and routed straight into the content. The maintainer account is usually exactly that. Whatever it shows you is not what a visitor sees. - Signing in with a different PROVIDER is not a different ACCOUNT. Identities resolve by email
address, so signing into memex with GitHub instead of Microsoft lands on the SAME mesh partition
with the same entitlements. Measured 2026-09-10: a deliberate GitHub sign-in, intended to mint a
fresh account, arrived as
rbuergi. A genuinely fresh account needs a different EMAIL.
The usable test identity is one that holds nothing the funnel gates: no package entitlement for
the target, and no row at Admin/Subscriptions/{viewer}.
mcp search "name:{viewer} nodeType:Markdown" # every {package}/_Entitlements/{viewer} marker
mcp get "@Admin/Subscriptions/{viewer}" # not found = no plan = good for testing
4. The coupon: two independent ways it dies, both silent
A coupon on a slide has to survive both. Neither shows up as an error anywhere until somebody types the code in front of an audience.
It grants no plan. CouponRedemption.Validate checks the tier FIRST — before the window, before
the budget — and refuses a coupon that names none with "This coupon does not grant a plan."
A coupon authored before that rule shipped is dead the day the rule deploys, and the coupon node
looks perfectly healthy. Check content.tier and content.tierDays on every code you are about to
hand out, and remember TierExpiry is CLAMPED to the coupon's own validUntil — a code windowed to
31 December gives eleven days to somebody redeeming on the 20th, not ninety.
There is nowhere to type it. The redeem row is built near the END of
PluginLayoutAreas.BuildSubscribe, after several early returns. A package that declares
contactEmail returns a contact-sales form and never reaches it, so a valid coupon for that package
cannot be redeemed at all (MeshWeaver.Plugins#1617; worked around for the demo package in
MeshWeaver.Reinsurance#192). The paywall renders beautifully either way.
Trust the ROW, not the page. A rendered paywall says nothing about whether the code has a home on it. Look for "Have a coupon?" with your own eyes, as the visitor's account.
An expired window is the third, ordinary way — and worth stating because a code is often parked
INERT on purpose (validUntil in the past) while a build lands, and arming it again is a manual
step somebody has to remember. Both SAV codes were parked that way; one had been forgotten.
5. The dry run, in order
- Signed out: the deck renders, and every hop it names either renders or asks to sign in — never an error, never a blank.
- Signed in as an account that owns nothing: each gated package's
/Subscribeshows the redeem row, in the language the PACKAGE ROOT declares (StoreTexts.ResolveLocale), not the reader's. - Type each code. A free coupon grants, installs the dependency closure, and lands in the content.
- Walk the demo to its last step as that account — the entitlement cascade covers dependencies only if they are unpriced, so a tour that crosses into a priced package stops there.
- Only then hand the link out.
Steps 1, 2 and 4 are the ones that get skipped, and each of them hid a launch blocker in this run.