# Phase 10.1: Runtime admin extension point - Discussion Log > **Audit trail only.** Do not use as input to planning, research, or execution agents. > Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. **Date:** 2026-09-28 **Phase:** 10.1-runtime-admin-extension-point **Areas discussed:** Acceptance target, Widget contract, Partials and custom toolbar actions, Asset load and CSP --- ## Acceptance target | Option | Description | Selected | |--------|-------------|----------| | Fixture plugin | Framework test plugin ships widget + partial + custom button | | | Wait for a real plugin | Seams only; first consumer is user/media | | | Fixture now, real consumer later | Fixture proves contract; real plugin is a later port | | | Other: fonoteka statistics + Discogs widget | Real Albums list stats strip and Albums form Discogs widget | ✓ | **User's choice:** Add a statistics partial to the fonoteka plugin above the list, and a custom `fields.yaml` widget that is a button to load data from Discogs (stub until Phase 14). **Notes:** “Above the list” is list chrome, not `type: partial` in `fields.yaml`. Screens locked to Albums list + Albums form. | Option | Description | Selected | |--------|-------------|----------| | Click hits a stub endpoint | Enabled button, POST, Phase 14 replaces stub | ✓ | | Visible but disabled | No request until Phase 14 | | | Click only runs widget JS | No new backend action | | **User's choice:** Stub endpoint. | Option | Description | Selected | |--------|-------------|----------| | Albums list + Albums form | One controller owns both proofs | ✓ | | Collections list + Albums form | Two controllers load different assets | | | You decide | Planner picks screens | | **User's choice:** Albums list + Albums form. | Option | Description | Selected | |--------|-------------|----------| | Defer custom toolbar | create/delete only until a real third action | | | Add one Albums list action now | Third button, stub POST | ✓ | | Fixture-only custom action | No Płytarium toolbar change | | **User's choice:** Add one Albums list action now. --- ## Widget contract | Option | Description | Selected | |--------|-------------|----------| | SPA owns HTTP | CustomEvent; FieldRenderer POSTs with CSRF | ✓ | | Tiny same-origin helper | SummerAdmin.request() | | | Widget fetch() itself | Widget must remember X-Requested-With | | **User's choice:** SPA owns HTTP. | Option | Description | Selected | |--------|-------------|----------| | Patch declared fields | YAML `fill` keys; fixture payload allowed | ✓ | | Toast only | Form unchanged | | | Only this field’s value | Widget bound as one field | | **User's choice:** Patch declared fields. | Option | Description | Selected | |--------|-------------|----------| | Winter-shaped type: widget | tag/path, action, fill; unknown keys fail boot | ✓ | | type + path only | Action and fill live in Go | | | You decide | Planner picks keys | | **User's choice:** Winter-shaped `type: widget`. | Option | Description | Selected | |--------|-------------|----------| | Attributes + fill snapshot | record-id, field, locale, current fill values | ✓ | | record-id only | Widget cannot see current name/year | | | You decide | Planner picks attributes | | **User's choice:** Attributes + fill snapshot. --- ## Partials and custom toolbar actions | Option | Description | Selected | |--------|-------------|----------| | List-header only | Leave form `type: partial` as a boot error | | | List-header and form type: partial | Both in this phase | ✓ | | You decide | Planner scopes it | | **User's choice:** Both. | Option | Description | Selected | |--------|-------------|----------| | Curated view model | Typed struct from controller; auto-escaped | ✓ | | Record map + extras | More Winter-like; leak risk | | | You decide | Planner picks data shape | | **User's choice:** Curated view model. | Option | Description | Selected | |--------|-------------|----------| | config_list.yaml slot | e.g. headerPartial names the template | ✓ | | Controller Go API only | No YAML key | | | You decide | Planner picks declaration | | **User's choice:** YAML slot. | Option | Description | Selected | |--------|-------------|----------| | Named action + stub POST | toolbar.buttons string list; controller registers extras | ✓ | | Inline map in YAML | strings or {action, label, confirm} | | | You decide | Planner picks YAML | | **User's choice:** Named action + stub POST. --- ## Asset load and CSP | Option | Description | Selected | |--------|-------------|----------| | On controller open | Winter addJs/addCss timing | ✓ | | All registered assets at login | Simpler, more JS in the admin origin | | | Per widget/partial only | Finest grain, define() timing issues | | **User's choice:** On controller open. | Option | Description | Selected | |--------|-------------|----------| | Embed only | air / summer watch rebuilds; no disk-in-prod | ✓ | | Dev-mode disk override | Original 10.1 note; rejected | | | You decide | Planner picks | | **User's choice:** Embed only. | Option | Description | Selected | |--------|-------------|----------| | Under admin prefix, script-src 'self' | No unsafe-inline, no extra hosts | ✓ | | Allow nonce inline for widgets | Weaker than current hygiene | | | You decide | Planner picks URL layout | | **User's choice:** Prefix + `script-src 'self'`. | Option | Description | Selected | |--------|-------------|----------| | Go method on the controller | addJs/addCss; new interface name | ✓ | | YAML asset list | js:/css: in config | | | You decide | Planner picks Go vs YAML | | **User's choice:** Go method. --- ## the agent's Discretion - Exact YAML key names, JS/CSS interface name, stub payload/toast copy, stats numbers, form-partial proof vehicle, custom-element tag naming, create vs update for the widget, asset URL layout, PartialHost vs T-10-16, toolbar action identifier. ## Deferred Ideas - Phase 14: real Discogs client and non-stub payloads - Dev-mode disk override (rejected for v1) - WASM extension API (v2) - Phase 10 leftovers: Ctrl+K, badge columns, Playwright, user/media nav