BaryoDev / BaryoDev/barakoBrew
A portal for people doing the work, generated from the definitions rather than written per project
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 2
- Avg merge
- 4h 34m
- Merged PRs (30d)
- 60
Description
BaryoDev/barakoCMS#339 gets a process owner to the point where an invoice type exists, two groups have different rights over it, and approval routes to the supplier. It leaves one question unanswered: where does the clerk actually work?
## The question
Either the admin UI serves as the end-user application, or there is a second surface for people doing the job rather than configuring the system.
## The recommendation: a third surface, generated rather than written
**Console, app, API.** The admin UI stays the console. The API is already headless and serves both. A portal is added for end users.
### Why not the admin UI
**Least privilege.** An invoice clerk would authenticate into a surface whose navigation includes content types, roles, tenants, API keys, feature flags and ops. Server-side authorisation can refuse every one of those requests and the surface is still reachable, still an attack surface, and still a mistake surface. The job needs a form and a list.
**The information architecture is wrong, not just too large.** A console is organised around objects: here are your content types, here are your roles. An application is organised around tasks: raise an invoice, approve what is waiting on you. Bending the console into the app produces a console with most of its navigation hidden, and CLAUDE.md section 9 is explicit that hiding is not access control, so the hiding is paid for and the gates are still required.
**Identity.** A surface staff and suppliers use carries the organisation's branding. A CMS console carries the CMS's.
### Why not a hand-written frontend per project
That is the thing this whole direction exists to avoid. A developer writing an invoice screen is a developer writing code, and the second project writes it again.
### So: generated from what is already declared
By the time BaryoDev/barakoCMS#339 lands, the system already holds everything a task-oriented UI needs:
| what the portal needs | where it already is |
|---|---|
| fields, types, validation, defaults | `ContentTypeDefinition`, `FieldTypeRegistry` |
| what this user may see | `FieldDefinition.Sensitivity`, `ISensitivityService` |
| what this user may do | `ContentTypePermission` plus transition permissions (#341) |
| which buttons to show | the lifecycle's transitions from this state (#340) |
| what happens next | workflows on transition (#342) |
A portal screen is a form over a content type, a list with filters, and a button per permitted transition. None of that needs new declarations. It needs a renderer.
The admin UI already generates forms from content types, so the first step is extracting that renderer into a package both surfaces use rather than writing a second one that drifts.
## What the process owner configures
In the admin UI: which types the portal exposes, which lists appear in the navigation, branding, and who may log in. Deliberately not a page builder. The moment the portal accepts arbitrary layout it becomes a product with its own roadmap, and the value here is that a correct screen appears without anyone designing it.
## Constraints
**A separate origin.** Its own host or subdomain, not a path under the console, so cookie scope, CSP and session boundaries separate too. A path split shares all three.
**No new authorisation.** The portal calls the same API with the same tokens and gets the same refusals. If a portal user can do something a direct API call cannot, the portal has invented permissions, which is the failure mode this design is most likely to produce.
**Sensitivity applies unchanged.** A field a user may not see is filtered by the API before it reaches the portal, not hidden by the portal.
**It can be turned off.** `Portal:Enabled`, defaulting to off. A deployment using barakoCMS as a headless CMS has no use for it, and an unused surface that is reachable is a liability rather than a feature.
## Scope, stated plainly
This is the largest single item in the 4.x direction, larger than BaryoDev/barakoCMS#339 and BaryoDev/barakoCMS#338 individually. It is also the one that makes them worth having, because without it the invoice scenario ends at "and then the clerk uses the admin console", which is the answer this issue exists to avoid.
It does not block anything. BaryoDev/barakoCMS#339 and BaryoDev/barakoCMS#338 are independently useful and the portal is additive on top of them.
## Done when
- A process owner exposes the invoice type to the portal from the admin UI, and a clerk logs into a surface that offers raising an invoice and nothing else.
- An approver sees an Approve button and a clerk does not, because the transition permission says so, asserted by a test against the API rather than against the button.
- The portal renders a content type it has never seen before, with no code change, which is the test that it is generated rather than written.
Related: BaryoDev/barakoCMS#339, BaryoDev/barakoCMS#340, BaryoDev/barakoCMS#341, BaryoDev/barakoCMS#342, and `docs/2026-08-18-client-layer-design.md`, which covers generated clients for developers building their own frontends and is a different question from this one.
Contributor guide
Assessment
This issue has not been assessed yet.