Design and rulings on TASK-3452 (lead, day 89).
- Placement: a first-time card on /console's empty state (Start a new
project) and in the workspace launchpad's step 2 (Set up your workspace
with /pad onboard); each vanishes with its screen. The stable way back is
a Tutorials entry in the user menu's Resources block, right after Docs.
- Dismissal: users.ui_dismissals, a JSON set of keys behind an allow-list
(models.UIDismissalKeys), read-modify-written under the users row lock,
so a dismissal holds on every device. GET/PUT /me/ui-dismissals, web only.
- Pad Cloud: the server fetches https://www.getpad.dev/learn/catalog.json
(a constant; 1h cache, last good copy kept, 5 min back-off) and serves it
same-origin at /tutorials, with posters proxied at /tutorials/posters/
{slug} from www.getpad.dev only. The page CSP gains frame-src for
youtube-nocookie, Cloud only. /console/tutorials hosts the click-to-load
player and chapters; transcripts link to getpad.dev.
- Self-hosted: both routes 404, no outbound request, no CSP change; every
surface links to getpad.dev/learn.
Migration 127 / pg 101, after #1837's 126 / 100 (rides rc.7). No CLI or MCP surface.
Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS