Releases: BaryoDev/barakoBrew
Release list
barakoBrew 1.5.0
Speaks API contracts 1 to 4, which covers barakoCMS 4.4.0. That release keeps the contract
at 4. Limiting an API key to content types needs 4.4.0; against an older API the control stays hidden.
Added
-
Tokens, tones and style recipes. The Theme screen edits
Tokens(named colours, lengths and
font stacks, with a swatch, a length bar or a font sample) andTones(an ink, a background and an
edge, each a token, a colour slot or a colour, with a preview chip). A new Style recipes screen
editsStyleRecipes: a name, optional classes, and properties picked from barakoPress's allowed
list, each a value that can name{token}or{colors.surface}and the like, with a live preview
of a sample block. Names and values are checked with barakoPress's own patterns, and a save that
would store something the site drops is refused. In the block form, every tone field offers the
tenant's tones, and arecipefield suggests its recipe names while still taking a bound value.
The site type needs the three JSON fields; without one the screen says so. Recipes need
barakoPress with style recipes (barakoPress#131). (#182) -
The block form edits list and group fields. barakoPress publishes
listandgroupfields in
its version 2 block schema, and 1.4.0 edited them as JSON. A list is now its entries, each edited
as its kind: a box per text, link or number, and a row that opens to a sub-form for a group. Add,
Remove, Move up and Move down work from the keyboard, focus stays on the entry that moved, and the
list'sminandmaxhold Add and Remove back. A group is a sub-form. They nest three deep, as the
site reads them, the Use data control is on every text box inside them, and a list or group bound
whole to data shows its placeholder. What is wrong is said where it is: a list with too few
entries on the list, a missing part on the entry, and the row counts it. A schema with no list or
group draws the form as before. (#181) -
An API key can be limited to content types. The new key dialog lists the content types beside
the scopes, with the note that a key limited to types can only use
POST /api/collections/{type}/push, and the list shows each key's types, or Any. That is the key a
repository's CI holds to push a changelog or a contributor list. A key with no type chosen is sent
with the body it always was. The control shows only against an API that knows the field: a listed
key carryingcontentTypessays so, and with no key to read, barakoCMS 4.4.0 or later. An older API
ignores a field it does not know and would mint a key with no limit, so if one ever answers without
the types, the console revokes that key before it can be copied and says why. (#184)
Image: ghcr.io/baryodev/barako-brew:1.5.0, linux/amd64 and linux/arm64. Also pushed as ghcr.io/baryodev/barako-admin:1.5.0 until 2.0.0.
barakoBrew 1.4.0
Added
-
Content types are where writing starts, and a type opens its entries. A content type card
used to lead to the field designer, which is the one screen an editor has no use for. Opening a
type now opens its entries, with the fields a second link beside it, and a type holding a single
entry opens that entry. The screen shows cards or a compact list, remembered per browser, with a
search and a sort by name, field count or last edited, and Single entry and Public badges on each
type. The entries screen keeps the type, the search, the status and the page in the URL, so the
link opens the same screen it was copied from, and names the type with a way back to the list of
them. The crumb above an entry now reads the entry's title instead of its uuid. The markdown
toolbar gained Quote, which it had always been documented as having. (#138) -
The content form is a package.
packages/content-formdraws the form from a content type
definition and imports nothing from the console, so the portal in #4 renders the same form without
a copy of it. Field sensitivity moved into the package and is decided before any host control
runs: a field a viewer's roles cannot read is drawn read only with a line saying why, rather than
as an editable box whose edits the API silently discards. The console keeps the controls that need
data the package does not fetch, and hands them in. Astringfield is a single line now, which
is what the type means; it was a two row textarea. MIT, with its own LICENSE, because a package is
bundled into its consumers' builds. (#5) -
Uploads run in the background, with a tray that follows you. Pressing Upload used to hold the
dialog open until the API answered, so a 10 MB image on a slow connection took the screen with it.
The dialog now hands the files to a queue and closes, and a tray in the corner of every screen
lists what is queued, what is uploading with its progress, what finished and what failed. A
refusal keeps the API's own reason on its row, with Retry and Dismiss beside it. Two files upload
at a time, so a batch does not saturate the connection, and several can be chosen at once or
dropped anywhere on the Files screen. Closing or reloading the tab while an upload is in flight
asks first, since an upload dies with its page, and each finished file appears in the list without
a reload. (#133) -
An image can be checked before it is uploaded and looked at afterwards. The upload dialog
draws the image you chose, from the file on your machine, before anything is sent; a PDF still
shows its name and size. On the Files screen a thumbnail is now a button that opens the image
fitted to the screen, with its name, its size, the size of the copy on screen and the public link
when it has one. The viewer asks the API for the resized copy that covers the screen rather than
the original, so opening a 4 MB photo does not download 4 MB, and a private file loads through the
same signed-in request the thumbnail already used. (#132) -
The rail lists the modules the deployment actually runs. The Modules group was a fixed list of
six items shown to everyone, so a deployment without Accounting still offered an Accounting link
that led to an empty screen. The console now readsGET /api/modulesand leaves out the item for
any module the API does not report as running. Until that call answers, and for a caller it
refuses (it needs SuperAdmin or Admin) or that it fails for, the rail is exactly what it was, so
nothing flickers or disappears on a slow or unreadable response. The Pages screen learns the same
way instead of reading a 404 as an answer, and keeps the 404 as its fallback. (#161) -
The block editor picks data bindings, and saves blocks for reuse. Beside any block field a
site says takes one, a Use data control builds{{scope.Field | format ?? fallback}}from a scope,
a field, a format and a fallback, so nobody types a brace. The scopes and formats come from the
site's own/api/blocks, and the fields fromGET /api/content-types, so a deployment that adds
either gets it without a console release. Removing a bound field from a content type marks every
block that uses it and says what the page will show instead. The palette groups blocks by the
layer the site publishes, and a block can be saved as a named block for the tenant, stored in the
Presetssite setting and offered on every page. Needs a barakoPress publishing schema version 2
(BaryoDev/barakoPress#33); against one that publishes version 1 the editor is exactly what it was,
with no picker, no marks and no extra API reads. (#140)
Changed
- One save flow for a refused write, not three. A 412 was answered in three places in three
ways: the entry editor raised a banner and stopped, the Site and Theme screens merged each edited
key by hand, and Pages threw and reloaded the tree. Entries, Site, Theme and Pages now write
through one flow: write, and if the server refuses, read what is stored, move the edit onto it key
by key, and write again. So a change somebody else made to a field you did not touch survives your
save instead of costing you a round of copy and paste. A field you both changed is named and the
save is refused, with the same two answers everywhere: take their version, or keep yours over it.
Saving a reusable block turned out to be a fourth answer to the same refusal, and goes the same
way now.rebaseMapEditmoves out of the site library tolib/rebase.ts, where every screen can
reach it. (#164) - The share links panel takes a scope, and reads the maximum expiry from the API. The panel
used to know only the whole site and to own the expiry rules itself: the day choices, the 30 day
default and the 90 day clamp were console constants. It now takes a scope that carries the
endpoint, the wording and how to build the link, and the Site screen passes the site scope, so the
entry and page scopes in BaryoDev/barakoCMS#857 need a builder besidesiteShareScopeand no
second panel. The longest expiry is read frommaxExpiryDayson the list response, and the
choices, the starting value and the clamp all follow it. No barakoCMS reports that field yet, so
the 90 days its create validator enforces is the fallback and is what runs today. (#163) - The base path is set at container start, not at build.
BARAKO_BASE_PATH=/barakocmson the
published image serves the console under that prefix; leave it unset and it serves the domain root
as before. Next resolvesbasePathandassetPrefixduring the build, so the image is built
against a placeholder prefix andentrypoint.shwrites the real one into the build output before
the server starts. Serving a console under a path no longer needs its own image. The value has to
be/segmentsof letters, digits, dot, underscore, tilde or hyphen; anything else is refused at
start rather than written into the bundle. Building with--build-arg NEXT_BASE_PATH=/pathstill
bakes it in, and an image built that way ignoresBARAKO_BASE_PATHand says so in its log. (#167) - The playground image is the published image with configuration on it, not a second build of
the console.Dockerfile.playgroundadds twoENVlines to the digest the release just pushed,
so:playgroundand:latesthold the same code. It goes away when the playground's own deploy
setsBARAKO_BASE_PATHitself. (#167)
Fixed
- A save could write over somebody else's, with the banner on screen saying it had not. The
entry editor sent the version and the ETag of its latest read rather than of the read its edit was
built from. So after the conflict banner appeared, pressing Save wrote this editor's older
document under a precondition the server was happy with, and the other change went with no error
anywhere. It sends what it read now, which is what lets the server refuse it. The Site and Theme
screens had the same hole through a different door: edits were laid over the freshest read and the
save carried that read's version, so a field both people changed was written with nothing to
notice it. (#164) - The entries list showed version 0 as if it were a version. The API sends 0 for an entry with
no event stream behind it, which is every seeded row on a fresh deployment, and that means the
server has no version rather than the entry being at version zero. The V column now leaves the
cell empty for 0, the same as for an API too old to send a version at all. (#10) - A secret shown once outlived the dialog that showed it. The API key, the two-factor setup key
and the recovery codes were left in the TanStack mutation cache for five minutes after the screen
closed, where anything else in the page could read them back and a navigation did not clear them.
Every mutation that returns a secret now spreadsSECRET_MUTATION(gcTime: 0) and the screen
resets it as soon as the value is in component state, so the only copy left is the one on screen
and closing the panel is what removes it. Share links already did this; the other three did not.
All four now render through oneRevealOncecomponent, so the copy button, the "cannot be shown
again" wording and the dismiss behaviour are the same on each. (#165) - A route rendered on demand under a base path asked for
/env-config.jsat the domain root.
The root layout readNEXT_BASE_PATH, which only the builder stage ever set, so prerendered pages
carried the prefix and pages rendered per request did not. It readsNEXT_PUBLIC_BASE_PATHnow,
which is compiled into the output and rewritten at start with everything else. (#167)
Image: ghcr.io/baryodev/barako-brew:1.4.0, linux/amd64 and linux/arm64. Also pushed as ghcr.io/baryodev/barako-admin:1.4.0 until 2.0.0.
barakoBrew 1.3.0
Changed
- Speaks API contracts 1 to 4. barakoCMS 4.2.0 moves the contract to 4: a locked account is answered
like a wrong password (BaryoDev/barakoCMS#640) and a content type holds at most 200 fields
(BaryoDev/barakoCMS#650). This console works against 4.1.x and 4.2.0, so upgrade the console before
the API.
Added
-
API keys offer the
content:destructivescope. Erasing an entry and rolling one back now need
it, andcontent:writesays it does not cover them. The new key dialog warns when that scope or
*is picked. Needs BaryoDev/barakoCMS#863; an older API refuses the scope with its own message. -
Site mode, the holding page and share links on the Site screen. A Mode select (Live or
Holding, unset reads as Live, a choice field's own options when it has them) with a note that
Holding changes what visitors see and hides nothing at the API. A holding page picker from the page
tree, empty for the default holding page, typed as a path when the Pages module is off. A Share
links panel creates a link with a label and an expiry of 1, 7, 30 or 90 days, shows
{site address}/_share#{key}once with a copy button, lists each link as active, expired or
revoked with when it was last used, and revokes after a confirmation. Mode and holding page show
only when the site type has those fields, and the panel is hidden when
/api/site/share-linksanswers 404. Needs BaryoDev/barakoCMS#850. (#147) -
Pages has a tree.
/pagesshows the page tree fromGET /api/pages/tree: drag a page, or use
its move buttons, to reorder it or put it under another page, with the new path shown while
dragging. Each move saves through the ordinary content update withIf-Match, writing
NavigationOrderandParentPage. The API's refusal (a cycle, too deep, a reserved slug) is shown
on the row, and a 412 reloads the tree and says someone else changed the page. Rows show status and
path, switch the navigation flag, change the slug, add a page under a page, and open the entry.
After a move or slug change that changes addresses, the screen offers a redirect from each old
path. A 404 says the Pages module is not enabled, and a contract other than 1 lists the pages flat.
Needs BaryoDev/barakoCMS#826. Seedocs/pages.md. (#91) -
A page's blocks are edited as blocks. A json field named
Blocksgets a list built from the
block schema the site publishes at/api/blocks: add from a palette, drag or use Move up and Move
down to reorder, remove, and a form per block using the same controls as entry fields, with blocks
nested in aslotsfield such as columns. What the site would refuse to render is marked on the
row and the field. A block of a type the site does not list is shown read-only and saved as it was.
SetNEXT_PUBLIC_PRESS_URLto turn it on; without it, or when the schema cannot be read, the field
stays the JSON editor. Seedocs/blocks.md. (#90) -
Choice fields. The content type designer offers a Choice type: options with a value and a
label, reordered by dragging or with the move buttons, and whether the field holds several values.
Values that differ only in case are flagged before the API refuses them. In the entry editor a
single choice is a radio group up to five options and a select beyond that, and a multiple choice
is checkboxes. Clearing an optional choice leaves the value out of the save. A stored value the
field no longer offers is marked "not offered any more" and the save waits until it is changed.
A type's detail screen edits a choice field's options later through
PUT /api/content-types/{name}/fields/{field}/options; when entries hold an option being removed,
the API's message and entry count are shown with a Remove anyway button that resends withforce.
A saved query filters a choice by option; the entries list waits on BaryoDev/barakoCMS#825 for a
field filter. Needs BaryoDev/barakoCMS#820; an API without the choice
type refuses the content type and the page shows its message. (#136) -
Site and Theme screens. Site edits a tenant's name, tagline, address, locale, logo, footer logo,
favicon, share image, top bar, header links, footer columns and social links; image fields can pick a
public image from Files. Theme edits the colour slots and site colours, fonts, corner radii, widths,
visitor variants and colours per option, with a preview of a header, card, dark band and prose block.
Each text colour is measured against its background, and a pair below WCAG AA is flagged but never
blocks the save. Both edit the one entry of thesitetype and send the whole stored document back,
so neither wipes what the other saved. A tenant without the type is offered the site blueprint, which
needs barakoCMS after 4.1.0 (BaryoDev/barakoCMS#797). A link the renderer would drop is flagged, and a
stored value not in the documented shape is shown as JSON rather than trimmed to fit. (#134) -
Tenants shows and edits each tenant's domains. A domain another tenant holds is refused inline with
the API's own sentence naming that tenant. The save sends the rest of the tenant back unchanged, since
the endpoint overwrites every profile field. Needs BaryoDev/barakoCMS#796; an API that reports no
domains shows that instead of an edit button. (#134) -
Resolving an error asks for a reference and remarks. Resolve on the Errors screen opens a dialog
with an optional reference (a pull request or ticket link, or a number such asAB#1234or
PROJ-42) and optional remarks. The error details show who resolved it, when, and both fields, with
an http or https reference as a link. Needs BaryoDev/barakoCMS#790 to store them; an older API
ignores the extra fields and resolves as before. (#130)
Changed
- barakoBrew is MIT.
LICENSE, thelicensefield inpackage.jsonand the image's
org.opencontainers.image.licenseslabel say MIT from this release. Releases up to and including
1.2.0 keep MPL-2.0. The contributor terms inCLA.mdnow name barakoBrew rather than barakoCMS,
state MIT, and grant a patent licence of their own, since MIT carries none. Follows the licence
rule in BaryoDev/barakoCMS#815. (#135)
Fixed
-
An expired session keeps the base path. When a token refresh failed, the console sent the
browser to/loginat the domain root, so a build withNEXT_BASE_PATH(the playground and
barakocms.com) left the console. It now goes to{base path}/login. -
The PWA installs screen crashed on load with
filter is not a function. It read
GET /api/pwa/installsas a bare list, but the API returns the paged envelope and has since
barakoCMS 4.0.0. The screen now readsitems, asks for the largest page the API serves (100), and
takes the device count fromtotalItems, saying so when there are more devices than the table
shows. (#128) -
Import says when a large sheet cannot be imported in full. The analyze step returns at most 500
rows and the import is built from those, so the rows after them were never imported while the page
said a large sheet was imported in full. The Import step now names how many rows will be left out
and asks for a confirmation first. Importing a whole sheet on the server is BaryoDev/barakoCMS#870. -
The Kubernetes health panel is hidden when the API has no Kubernetes endpoint. A 404 from
GET /api/monitoring/k8snow hides the panel instead of showing an unnecessary error state.
Other API failures remain visible with a retry action. (#103)
Image: ghcr.io/baryodev/barako-brew:1.3.0, linux/amd64 and linux/arm64. Also pushed as ghcr.io/baryodev/barako-admin:1.3.0 until 2.0.0.
barakoBrew 1.2.0
Works against barakoCMS 4.1.0, and speaks API contracts 1 to 3. The grouped action picker below
needs a barakoCMS release that includes BaryoDev/barakoCMS#783, which reports a group for each
workflow action kind. That is merged and not yet released. On 4.1.0 the picker shows the flat list
it showed before, and nothing else depends on it.
Added
- Files shows a thumbnail for each image. It is the API's 160px copy (
?w=160), never the
original, so a page of uploads costs kilobytes rather than megabytes. A public image loads from
the anonymous route with a srcset; a private one is fetched with the session's token in a header
and shown from a local object URL, so the token never appears in a URL. PDF, GIF and AVIF files,
which the API does not resize, show an icon instead of downloading the original. The console
still has no image optimiser and ships no image binary (#80). - A navigation menu is reordered without editing JSON. The
Itemsfield of amenuentry is
a list now: add and remove items, move them up and down, nest one under the item above and move it
back out, all from the keyboard. The saved value keeps each item's keys and casing and changes only
order and nesting, one level deep, which is whatpublic.menu()in the client reads. A value the
list cannot show without losing part of it stays in the JSON editor. The shape and the naming
convention are indocs/menus.md(#86). - Files has a screen.
/fileslists the tenant's uploads 20 at a time with name, type, size,
visibility and upload date. Upload states the API's rules (PNG, JPEG, GIF, WebP, AVIF or PDF, up
to 10 MB) and refuses a file that breaks them before sending it; a refusal from the server, such
as the virus scanner's, is shown in the dialog. Delete asks first, and when entries still use the
file it names them and deletes only on "Delete anyway". A public file has a copy link button.
Delete is offered on a file to its uploader, Admin and SuperAdmin, which is who the API allows.
An account the API refuses the list to is told so, with no upload control. The rail lists Files
under Modules for Admin and SuperAdmin (#3). - A content type that holds one entry is edited on one screen, not a list. barakoCMS 4.1.0
marks such a type withisSingletonand refuses a second create. The console now lists each one
in the rail under Entries and opens it at/content/singleton/{type}. With no entry yet, the first
save creates it; after that the same screen edits it, with schedule and history. Links that used
to open the list or the new entry form for such a type (the type's own page,/content?type=,
/content/new?type=) land on that screen instead, and a type can be created with the flag on
(#89). - A markdown field is a composer with a preview, not a bare textarea. Write and Preview tabs,
a toolbar for bold, italic, heading, link, list and code, and a word count. The preview renders
with barakoPress's rules, so raw HTML shows as text and a link that is not http, https, mailto or
relative keeps its words and loses its destination. The saved value is the text as typed; toggling
the preview never writes to it.textandrichtextfields are unchanged (#85). - A webhook workflow can be built from the new workflow form.
Publishedis offered as a
trigger next to Created, Updated and the type's transitions. An action's optional parameters get
inputs marked "(optional)", read from the example configuration the API publishes with each
action, which is where the Webhook action namesSecret. A parameter the API redacts on read
(secret, token, password, API key and the like) is a password input with a hint that it will not
be shown again, and a blank optional parameter is left out of the request rather than sent empty.
The saved workflow says "Secret: set, not shown". The API never returns the value and has no
update endpoint, so replacing a Secret means recreating the workflow. The trigger selects and the
action picker have accessible names (part of #87). - The action picker groups kinds under Content, Delivery, Comms, Data and Flow. The console no
longer keeps its own list of action kinds: it shows whatGET /api/workflows/actionsreturns,
keeps the API's order inside a group, leaves out empty groups, and puts a missing or unknown group
under Other, last. An API that sends no group, barakoCMS 4.1.0 included, gets the flat list with
no headings. The Request action is drawn with the connector icon rather than the fallback (part
of #50).
Changed
- The image is published as
ghcr.io/baryodev/barako-brew. It was the last place the old name
survived. Every tag (latest,<version>,dev,dev-<sha>,playground,
playground-<version>) is also pushed asghcr.io/baryodev/barako-adminpointing at the same
digest, and the publish job fails if the two names disagree.barako-adminstops at 2.0.0;
move compose files and deploy scripts tobarako-brewbefore then. Tags already pulled under the
old name stay resolvable (#84). - The unmocked pack runs against a pinned API image on pull requests, the merge queue and pushes
(barako-cms:4.1.0, read from.github/barako-api-version), and againstbarako-cms:master
nightly and on demand. A failed nightly opens or comments on one tracking issue.
scripts/smoke-check.shdefaults to the same pin (#58). - CodeQL runs on merge queue batches and on every pull request, markdown-only ones included, so it
can be a required check (part of #26). - Every third-party action in the workflows is pinned to a commit SHA, with its tag in a comment
(#59). - Every accessibility scan checks that reduced motion is on and waits for animations to settle
before it audits the page (#92). - CodeRabbit no longer reviews every pull request on its own, matching barakoCMS. Commenting
@coderabbitai full reviewstill asks for one (#60).
Fixed
- Import a spreadsheet sends the file. The shared API client defaults to a JSON content type,
and axios turned the upload form into JSON, so the analyze request reached the API with no file.
The client now drops that default for any form body, so the browser sends multipart form data
with its boundary. File uploads used to work around this on their own request and now rely on the
same rule (#119).
Image: ghcr.io/baryodev/barako-brew:1.2.0, linux/amd64 and linux/arm64. Also pushed as ghcr.io/baryodev/barako-admin:1.2.0 until 2.0.0.
barakoBrew 1.1.0
Changed
-
The console speaks API contract 3, and has to ship with barakoCMS 4.1.0. That release refuses
a role namedSuperAdmin,Admin,HRorUseron create and on update, because a custom role
taking one of those names inherited a full authorisation bypass and, through the role claim in the
JWT, switched off field-level sensitivity masking as well (GHSA-2522-rpv2-6p99). Refusing a request
the API used to accept tightens validation, soX-Api-Contract-Versionmoves to 3
(BaryoDev/barakoCMS#740). Nothing else in the console changed: the refusal arrives as a 400 with a
ProblemDetails reason, whichapiErrorMessagealready reads, the same path that surfaces the
slug-uniqueness refusal below. Contracts 1 and 2 stay supported. -
The console speaks API contract 2 as well as contract 1, and has to ship with the barakoCMS
release that moves to 2. That release enforces slug uniqueness within a content type, so a
create, an update, a rollback or an import row carrying a slug another entry already holds is
refused with 400. Tightening request validation is a breaking change to the HTTP surface, so the
API movesX-Api-Contract-Versionto 2 (BaryoDev/barakoCMS#717). The console refuses to render at
all against a contract version it does not speak, so a console pinned to 1 shows one page of
explanation instead of the product the moment that API is deployed. Contract 1 stays supported:
every released API sends it, and a rolling upgrade answers with both at once. Nothing else about
the console changes, because contract 2's only behavioural difference is a refusal, and the entry
form, the version rollback and the importer already render the server's own sentence when a write
is refused. -
A pull request red only because its base is old now fixes itself. When master moves, any open
pull request that is behind it and failing gets its branch updated and CI runs again.minio/minio
being removed from Docker Hub failed the API repository's integration suite on every branch at
once, and after the fix landed there two pull requests stayed red for a reason that was already
fixed until somebody worked it out by hand. Nothing is merged and no job is retried: a retry hides
a flake, where rebuilding on a newer base rules out one cause and leaves a real failure visible.
Green-but-behind is left alone, and theno-self-heallabel opts a branch out.
Fixed
- A reference field is a search over the content type it points at, not a box for pasting a GUID
into. The API has always sentreferenceTypenaming that type, and the console's
FieldDefinitiondropped it on the way in, so Author, Category and every other relation could
only be set by typing an id. Entries read as their titles now, the search runs on the server, and
a definition that names no target type keeps the id box it had. Additive: no contract change, and
the supported API range does not move.smoke/reference-fields.spec.tsholds the server to
sending the field, since nothing mocked can. - A reference that could not be read says which of the two things happened. "This id does not
resolve to an entry" used to be the answer to every failure, including a timeout or a 500, which
told an editor their data was broken when the connection was. A 404 keeps that sentence, anything
else renders the server's own and offers a retry, and a failed entry list now says so instead of
reporting that the target type holds no entries. Closing the picker returns focus to the field
that opened it, on both exits, rather than dropping a keyboard user at the top of the form. - The smoke pack refuses to send the seeded administrator's token over plain HTTP to anywhere but
this machine.SMOKE_API_URLis an override four specs read, and it could name any origin, so an
http://value pointing off-box put a working administrator credential on the wire in clear and
the run passed.smoke/api-url.tschecks it once for all four: https anywhere, plain http to
loopback only, and a failed run naming the reason otherwise. scripts/preflight.shruns every gate a laptop can run, in the order CI runs them, and names the
ones it could not. CI's jobs are independent and the unmocked pack takes twelve minutes to stand up
a database and build the console, so a mistake the thirty second job could have caught was costing
a push and a wait. The two Playwright configs now pintestMatchto.spec.tsand
src/test/runner-globs.test.tsholds that line, because vitest collects*.test.tseverywhere and
Playwright's default collects it too: a unit test written next to a pack's specs was loaded by
Playwright, which died importing vitest before running one of them.
Image: ghcr.io/baryodev/barako-admin:1.1.0, linux/amd64 and linux/arm64.
barakoBrew 1.0.0
Works against barakoCMS 4.0.1 and later. It cannot drive 3.21: 4.0 moved enums to strings, put
lists in an items envelope, returns ProblemDetails, answers 401 on a failed sign-in, and serves
content types at /api/content-types. It refuses 4.0.0 from a different origin to the API, which is
every ordinary deployment: the console reads the contract version from a response header, and 4.0.0
sends that header without exposing it to script, so the console cannot see it and stops rather than
half-working. 4.0.1 exposes it.
The first release of the console as its own product. The code is not new, it shipped inside the API
repository for a year, but nothing about how it was built, tested or published survived the split
until now. This release is the console becoming something that can be depended on: it has a version,
it says what it is licensed as, its tests run before it ships, and the image it publishes is built
from a commit anyone can point at.
Added
- A CI suite that actually runs on
master: lint, typecheck, 291 unit tests, Playwright with an axe
pass, an image build, an SBOM, and an unmocked run of the console against a real API image. - CodeQL, Dependabot for npm and Actions, issue and pull request templates.
LICENSE(MPL-2.0),SECURITY.md,CODE_OF_CONDUCT.md,CLA.mdandCONTRIBUTING.md, with
AGENTS.mdas the coding standard both people and agents read.quickstart/, a compose file that brings up Postgres, the API and the console from published
images with nothing to build.- A gate that fails the build when an image in the repository carries provenance or identity
metadata. The design screenshots each arrived with a 5,758 byte C2PA manifest naming the tool that
made them, and every text-reading check was green over them. docs/design/barakobrew-2026/, the redesign handoff, its prototypes and an audit of every screen
against the code as it stands.- A gate that refuses to publish a tag serving only one architecture, and a CI job that proves the
gate can fail.barako-admin:3.21.0islinux/amd64only, sodocker pullof the version the
documentation pins fails on Ampere, Graviton and Apple Silicon. The check reads the pushed
manifest rather than the build config, because the config being right is not evidence the push
was, and CI runs it against that known-bad tag on every pull request so its failure has been
watched rather than assumed. - The console refuses to start against an API whose contract version it does not speak, naming both
numbers and which one to change. barakoCMS sendsX-Api-Contract-Versionon every response, 401s
included, so the check needs no request of its own and covers the sign-in page too. A missing header
counts as incompatible: it means an API old enough to predate the contract version entirely. - A test that checks every enum this console mirrors against the server's own declaration, so a value
added on one side cannot sit unnoticed on the other. - Two licence gates.
scripts/check-licences.shreads the installed tree and fails on anything
outside the permissive allow list, proven in CI against a scratch install offfmpeg-static, which
is GPL-3.0-or-later.scripts/check-image-licences.shreads the published image, which is a
different question: the runtime stage copies Next's traced output rather thannode_modules, so the
tree being clean is not evidence the image is. Rules that cannot be automated, no runtime licence
gates and a maintenance check, are a checklist inCONTRIBUTING.mdand a line in the pull request
template. CODEOWNERS.
Fixed
- The editor no longer loses an unsaved draft. A newer version of an entry arriving in the
background (a refetch afterstaleTime, on window focus) replaced every field with the other
person's values, with no error and no race involved. It now keeps what you typed and asks. - Two editors no longer overwrite each other. The entry editor sends
If-Matchwith theETagit
loaded, so a save against a version somebody else has already changed is refused and the editor
says so, rather than the last writer winning in silence. It needs barakoCMS 4.0.1, which is the
first release to let a browser read that header. - The image ships no LGPL binary. Next's image optimiser wants
sharp, whose prebuilt libvips
binaries are LGPL-3.0-or-later, and it arrives as an optional dependency of Next itself, so 27MB of
it was traced into the published image while the licence audit read direct dependencies and said
there was no copyleft. The optimiser is off, because nothing here renders a remote image: the one
<img>is an MFA QR code delivered as a data URL. Turning it off is not sufficient on its own, so
sharpis excluded from output tracing as well, and a CI gate now reads the built image rather than
the dependency tree, refusing copyleft and anything that does not say what it is licensed as.
THIRD-PARTY-NOTICES.mdstates the artifact's position and ships at/app/inside the image, since
a claim about what an image redistributes is worth little if it only exists in a repository nobody
pulls. Where resizing belongs when the redesign needs it is an open spike. - The field picker carries all 20 field types, grouped, and resolves the registry's aliases. It was
three short, so three types the API accepts could not be chosen here. - The five status states live in one module instead of being spelled out per screen, which is what let
them drift apart. - The default API URL is port 5005, the port the quickstart actually publishes. It was 5006, so the
first thing a newcomer saw was a console that could not reach its API. - Both configured Playwright projects run. They were declared and never selected, so a second browser
was carried in the config and exercised nowhere. - A refused save says so on the page rather than only in a toast that has gone in four seconds.
scripts/verify-runtime-config.shrestorespublic/env-config.jswhen the verification fails.
It moved the real file aside and exited before the restore, so a failing run left the working tree
without its config. Fixed by @kasapdev.- Both scripts resolve paths from the repository root instead of one developer's home directory.
- ESLint no longer reads the vendored design prototypes, which is what turned the repository setup
red and got it abandoned.
Changed
- The npm package is
barakobrew, notadmin, and carries a real version. It is what appears in
npm audit, the SBOM, and every CI log line.
Image: ghcr.io/baryodev/barako-admin:1.0.0, linux/amd64 and linux/arm64.