Deliver ribbon wording, and generate favicons from a tab icon

FeatureSecurityService
Shipped
September 6, 2026 at 3:15 AM UTC
Author
Kamo
Commit
306aa99

Provisioning learns two things: what an organization wants its public corner ribbons to say, and which artwork its browser-tab icons should be cut from. **Ribbons.** kamo-login, kamo-register and kamo-apps have no OrgContext, so the five wordings are resolved through the parent chain here and baked into the theme config.json — the same route the login and register logo overlays already take, and for the same reason. A wording nobody set omits its key entirely rather than carrying the English default, so kamo-apps keeps rendering its own translated line in all twenty-two locales. Because that file is only rewritten by a provision, PATCH /branch-titles now starts one and reports `reprovisioning` back. It fires server-side rather than as a second call from the browser on purpose: this endpoint is gated on "your session's org is the org in the path" while /provision-theme is gated on canManageOrgBranding, so a member who may rename labels without holding the branding right would have watched the save succeed and the follow-up 403 — labels stored, ribbons silently never delivered. It is best-effort: the labels are already saved by then, and an org with no alias to write a theme under must still be able to rename them. **Tab icons.** `faviconSourceKey` is the one place the chain is written down. Company is two states. Software degrades twice — to the software simple logo, but only when softwareLogoSimpleEnabled says that logo actually stands in for the company mark, and otherwise all the way back to whatever the company brand resolves to. Skipping that second condition is the tempting mistake: it paints the software mark on the tab of an org that explicitly said its software logo overrides nothing. favicon-software/ is generated only when the two brands resolve to DIFFERENT source objects, which for an org with no white-label brand is never — so this does not double the cost of a provision. config.json reports that as softwareFaviconEnabled, and a client that selects SOFTWARE without it reads favicon/ rather than requesting a directory nobody wrote and painting nothing. The software set gets its own site.webmanifest: the icon `src` values in there are relative, so pointing a software surface at favicon/site.webmanifest would install the company mark it was configured not to show. Two new upload types, tab-icon and tab-icon-software, keep the real extension rather than normalising to SVG the way the compact logos do — a favicon is only ever rasterised down to 16-180px, so demanding a vector would mean auto-tracing a PNG somebody already drew at the size it will be shown. The upload records the extension AND switches the icon on: uploading one is an unambiguous request to use it, and leaving the switch off would store the file and show the member nothing. Requires kamo-shared-library at 91052925 and the DDL in this commit applied by hand — ddl-auto is none and the initializer is not deployed.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing