- Shipped
- August 19, 2026 at 6:19 AM UTC
- Author
- kamo
- Commit
- dd92529
The surface was a MUI tab strip over two AG Grids. Packages rendered as seven columns of counts and an actions cell of six unlabelled icon buttons, three of which disabled themselves without saying why — the only way to learn that Publish needs a binder was to add one and watch the button wake up. - A compliance meter opens the page: every assignment in the org as one stacked bar over four buckets, built from seven total-only counts because DocsService has no aggregate endpoint. Its legend rows are the controls (the bar itself is aria-hidden decoration), and choosing one filters the assignments through ?bucket= — a link an admin can send. - Packages become a deck of cards carrying what a table had to drop: the version as a medallion, the real **************** spine, audience, coverage, and the published content fingerprint as a monogram. Every blocked action stays visible and states its reason as text, never as a tooltip on a disabled control. - Assignments stay a grid, now with a leading state rail, the member over their address, signature progress as a bar, and a status SENTENCE in the state's own colour instead of a grey chip. - One vocabulary end to end (publish / deliver / reissue / withdraw), matching the backend's own verbs. Interaction colour is --legal-brand throughout, per the house rule that brand owns every hover ring and focus outline; --legal-seal stays for identity and state, so a white-label org still sees its own colour on this page. Every rule the surface draws is a pure function in app/lib/legalRegistry.ts with 36 tests, including a proof that the four buckets cover the seven assignment statuses exactly once — without it a status added to the backend would drop out of the meter silently, leaving the bar full width and part of the org uncounted. buildAssignmentQuery now sends statuses as REPEATED params so a whole bucket is one request; a CSV would arrive at DocsService double-encoded as one literal token.