* add clinic-console live-artifact template
Adds a built-in clinic-console template under
skills/live-artifact/assets/templates/, fulfilling the
assets/templates/<name> directory shape that
specs/2026-04-29-live-artifacts/spec.md §5.1 already plans for but
has not yet populated.
Three files, no other changes:
- template.html — html_template_v1 source, only DOM, CSS tokens, and {{data.*}} bindings
- data.json — canonical default sample (~6.7 KB, well within bounded JSON limits)
- README.md — data contract + telemedicine/pharmacy/pediatric variants
Verified locally against apps/daemon/src/live-artifacts/render.ts:
all paths match the html_template_v1 grammar, all bindings resolve
to scalars, no script/iframe/srcdoc/on*=/javascript:/raw HTML
directives, no forbidden JSON keys, JSON within bounded envelope.
* clinic-console: hardcode icon refs, drop icon_href bindings
Address @mrcfps's review on PR #795: stop interpolating {{data.*}} into
<use href="..."> attributes. The html_template_v1 binding contract
forbids interpolation inside URL-bearing attributes, and the security
validator runs *before* {{data.*}} substitution — so even a benign
icon_href today could be replaced with javascript:alert(1) tomorrow
without the validator ever seeing it.
Fix:
- template.html: every <use href="..."> is now a hardcoded literal
(#icon-dashboard, #icon-message, …). 14 nav slots + 4 KPI tiles
converted; total <use href="..."> count unchanged at 28, all
fragment-id literals, zero {{data.*}} inside URL-bearing attrs.
- data.json: icon_href removed from each nav_main[] item, each
nav_management[] item, and from kpi_a / kpi_b / kpi_c / kpi_d
(14 keys removed). Sample is now 6,333 bytes (was ~6,840).
- README.md: data-contract tables no longer list icon_href; new
"Icons are template-locked" section explains the binding-contract
rationale, lists the hardcoded id per slot, and gives guidance for
future runtime-configurable icons (route through a constrained,
non-URL mechanism such as enumerated CSS classes — never interpolate
into <use href> directly).
Verified locally against apps/daemon/src/live-artifacts/render.ts:
298 bindings, 297 unique paths, all resolve to scalars; zero
{{...}} inside any URL-bearing attribute (href / src / action /
formaction / srcset / xlink:href / ping / background / poster /
cite); none of the 6 forbidden security patterns present; bounded
JSON envelope: 6.3 KiB / depth 5 / max 22 keys / max 35 array items
/ max 45-char string — all well within limits.
---------
Co-authored-by: Joey-nexu <236967869+joeylee12629-star@users.noreply.github.com>