PhoenixKitProjects. Web. ProjectWhiteboardsLive
(PhoenixKitProjects v0.23.1)
Copy Markdown
View Source
The Whiteboards extension tab (Step 11): board list + canvas, rendered
by the projects hub via live_render with the extension-tab session
contract (see PhoenixKitHelloWorld.Web.ProjectHelloTabLive for the
contract reference). Mounts off-router only; no handle_params/3.
Drawing itself is core's MediaCanvasViewer LiveComponent — annotation
persistence, palettes, and tools all live there; this LV only manages
board rows and hands the component either a board (a file-less
board since V16: Whiteboards.viewer_board/1, drawn on an empty
canvas with shapes anchored to the board's uuid) or a curated file map
(Whiteboards.viewer_file/1, for a board over a real image or one made
by the old white-PNG bridge).
Authorization: the hub renders extension tabs inside surfaces it has
already authorized (the admin show page / an authorized host embed), and
the tab session carries no scope — so, per the extension-tab contract,
this LV scopes every query by the session's project and does not re-run
Authz per event (same trust model as every contributed tab).
Board creation and deletion are identity-gated: no current_user_uuid
in the session, no writes (an unattributable actor on the activity row
is not an audit trail) — and write-gated on the session's "can_write",
which the HOST resolves from its scope against this extension's
declared write action (final panel: mutations must not ride the
view-only trust model). can_write also reaches the canvas as
can_annotate: a viewer without it sees every board locked — no
drawing tools, no pencil, and core refuses its shape changes — since
the drawing surface is the third write, and it used to ride the same
view-only trust (the sweep, 2026-09-05).
Phoenix-first: the board list, create, and delete all work without JS;
the canvas needs core's Fresco/Etcher hooks (already shipped by
phoenix_kit.js) and renders the background image server-side either way.