Summary
The Timmy launcher button in the threat model edit view renders unconditionally, even when the server has Timmy disabled or unconfigured — the user clicks through to a chat page that fails at request time (server returns 404/503 on chat endpoints).
Actual Behavior
src/app/pages/tm/tm-edit.component.html:21-29 — timmy-header-button has no @if, no capability check; openChat() (tm-edit.component.ts:2181-2184) only guards on threatModel existing.
- No availability probe exists in
timmy-chat.service.ts.
- The natural channel —
GET /config → ClientConfig.features — has no Timmy entry today, and nothing in the client reads features at all (BrandingConfigService, src/app/core/services/branding-config.service.ts:37-75, derives only from ui.*).
Trap for the implementer: the spec's per-entity timmy_enabled fields (ThreatBase, AssetBase, etc., ~30 occurrences in api-types.d.ts) are content-inclusion toggles, NOT a feature-availability flag. Do not wire the launcher to these.
Proposed Approach
Blocked on ericfitz/tmi#644 (server advertises timmy_enabled in ClientConfig.features). Then: add a timmyEnabled$ observable to BrandingConfigService mapping c?.features?.['timmy_enabled'] ?? false (default hidden so older servers don't advertise a broken feature), wrap the button in @if (timmyEnabled$ | async), and apply the same guard to the /tm/:id/chat route since it is reachable by direct URL.
Impact
Users on deployments without Timmy see a prominent broken feature.
Summary
The Timmy launcher button in the threat model edit view renders unconditionally, even when the server has Timmy disabled or unconfigured — the user clicks through to a chat page that fails at request time (server returns 404/503 on chat endpoints).
Actual Behavior
src/app/pages/tm/tm-edit.component.html:21-29—timmy-header-buttonhas no@if, no capability check;openChat()(tm-edit.component.ts:2181-2184) only guards onthreatModelexisting.timmy-chat.service.ts.GET /config→ClientConfig.features— has no Timmy entry today, and nothing in the client readsfeaturesat all (BrandingConfigService,src/app/core/services/branding-config.service.ts:37-75, derives only fromui.*).Trap for the implementer: the spec's per-entity
timmy_enabledfields (ThreatBase, AssetBase, etc., ~30 occurrences inapi-types.d.ts) are content-inclusion toggles, NOT a feature-availability flag. Do not wire the launcher to these.Proposed Approach
Blocked on ericfitz/tmi#644 (server advertises
timmy_enabledinClientConfig.features). Then: add atimmyEnabled$observable toBrandingConfigServicemappingc?.features?.['timmy_enabled'] ?? false(default hidden so older servers don't advertise a broken feature), wrap the button in@if (timmyEnabled$ | async), and apply the same guard to the/tm/:id/chatroute since it is reachable by direct URL.Impact
Users on deployments without Timmy see a prominent broken feature.