66 changes:
- A sign-in is questioned when it looks wrong, not when the browser is new
- One TOTP code, one login
- A password change that cannot be the same password
- The bundled sign-in forms can price automation
- The mail an account was sent is on the account's screen
- Themed email: the column that had never been read
- An email is written in the recipient's language
- A datatable over an
authserver.* table read as empty on MySQL
- Authorization is three layers, and the guide said two
- Two reported bugs: a date of zero, and a cropped PNG's black corners
- Something runs the second-factor cleanups
- The services screen says whether anything is listening to its buttons
- A message to many accounts, composed and sent from a screen
- Three test classes were spending their time emptying the cache
- Requiring a second factor, and requiring a real one
- The debug bar says where the second factor stands — and stops forgetting your tab
- Three dead ends on the administration screens
- A settings row no longer opens the debug toolbar
- Nothing on the settings screen opens the DevPanel any more
- A scaffolded application comes with something that runs its background work
/admin/Services says how to create the supervisor
- New-sign-in alerts can be on unless turned off
- The DevPanel's Back button goes where you came from
Session can write, not only read
- One apostrophe no longer destroys a page's breadcrumb structured data
Html\Date renders the time and the dropdowns it always claimed to accept
- The queue worker runs under a supervisor
/admin/Services can see a supervisor in another container
- An unsubscribe link, and the two headers Gmail actually reads
Addon::trigerAddon() refuses a nameless addon too
- The default language is a list, not ten characters of free text
- Adminer, at
/adminer, behind the application's own gate
/messages — the inbox those internal messages were going into
- Any browser with JavaScript can solve the human check — and a test proves it
- A CSP-blocked redirect, and a script with two nonces
- Adminer signs itself in
Html\Date reads the properties it declares
- An idle connection is not a query running for three hours
Html\Date's field is validated by the browser again
- A date is written the way the language writes dates
- Two of the widest columns on the process list said the same thing four times
- Two empty boxes where the log charts should be
- The log dashboard's figures, asked for by something that is not a screen
- The components guide listed
Seo and then never mentioned it again
mcp:serve had its own copy of the tool catalogue, and it was stale
- The most frequent error in the log was the framework asking a question
- Every log entry was dated the moment you looked at it
mcp:serve is not something a person could debug
- An MCP tab in the DevPanel: the schema as a form, the answer on the page
find-symbol: the question grep cannot answer
- The DevPanel's MCP tab shipped with a JavaScript syntax error
route-list executed the views, and then said there were no routes
- A link in the DevPanel is styled wherever it is
- Two more MCP tools: what the CLI can do, and what the theme is made of
- Three tests that were a copy of the tool catalogue
api-docs and find-tests: the other two of the four
- Two rules that could not be checked, and now can
changelog-add: the one tool that writes
- The plain-text part of an email was the CSS, with the links removed
- Four headers that decide what happens to a message
- Gmail actions: a button in the message list, and the reason yours is not showing
- A ViewAction never needed a handler — the password-reset mail has one now
- One-click mail actions, and the handler a "this wasn't me" button needs
- The unsubscribe page was 181 KB, and 180 of them were the website
- A session count that was not a number, and four tables called
sessions
- Email tracking that works, and only for mail somebody agreed to receive
52 changes:
- A select and a pager that need no form around them
- Four legacy input classes become one
- One search box over many entities
- A model save cost 1358 milliseconds
- Two flags that keep a migration honest
- reset() left the page where the next request would find it
- The form field now uses the controls
- Nine readers of a stream that can only be read once
- An API endpoint's status code was untestable
- A flash that worked once per process
- A permanent cache entry was deleted by the next sweep
- The dashboard's JSON endpoints returned a web page too
- The backup codes a user saved were never the stored ones
- Adding a member to an organization was impossible
- Any signed-in account could rewrite the system settings
- The lockout settings configured nothing
- The tailwind scaffold theme is a daisyUI theme
- A view directory you half-own rendered a page shell
- An argument a method does not declare is dropped silently
- The datatable search that could not be slowed down, and the columns that were all searched the same way
- Every page after a sign-in page lost its header
- Seventy-nine queries had lost the table prefix
- The Redis cache listing read a key nothing writes
- Vendored assets that were still remote
- A page could not call its own API
- One palette, every UI system
- The administration area has its own directory
- Six filings from one project, all small and all silent
- The palette moves under app/themes/
- Two guides that had become their own history
- A generated screen the vanilla stacks could not reach
- Every breadcrumb in the area pointed at /adminusers
- URL is the administration area, sURL is the site
- Organizations had no way to look at one
- A column filter per column, on the lists that need one
- What a usertype means, and how an application changes it
- Row actions are icons, and the row is a link
- The log viewer's own endpoints 404'd inside its iframe
- Everything the framework knows about a user, on the user's screen
- Per-user settings, and permissions edited where the user is
- A screen for the message templates the framework already had
- New-sign-in alerts got a site policy
- A login left the previous session's token valid for a month
- One definition of the guard every admin screen opens with
- What each usertype may do, written down and on a screen
- A correct password was refused, and bcrypt had been dropping characters
- No language was ever selected
- The administration area may be in another language than the site
- A second factor that needs nothing set up in advance
- A new device can be made to prove something, not just reported
- A second factor an application can bring its own of
- Seven account-security switches, every one off until asked for
19 changes:
- One set of controllers, two addresses
- The administrator that could not administer
- The admin links that left the admin area
- The logout that revoked nothing
- A webhook queue with no consumer
- Three endpoints that had never worked
- A column you could write and not read
- Every scaffolded project refused to test itself on macOS
- The test database that would not copy
- The recovery path was the crash
- The HTTP tests that were all testing the home page
- The discovery document that was not JSON
- The pages that rendered nothing
- The scopes the server advertised and refused
- Five actions that could never be called
- Four views indexing keys that were never there
- A password you can set from a shell
- Two language objects, and themes that could not be found
- The manifest that synced nothing
39 changes:
- The server now says where its own time went
- An API request is not a browser session
auth:unlock — lifting a lockout you gave yourself
- The toolbar answers "who am I, and until when"
- A parent class for services, and a tab that admits they exist
- An Errors tab, for what the browser threw
- A Client tab: what the browser thinks the world is
- The page outranks the toolbar
- An API playground in the toolbar — and a doubled slash it found
- A WebSocket daemon that can read a Redis stream
- The body of a DELETE request
- A
? in a raw fragment now binds where it was written
init will not scaffold over your application
- Debug data for an application that does not use the API layer
- The other way to lose a page
- The toolbar injects through the response, not an output buffer
- Two build settings that failed quietly
- Three dead stubs, and four corrections to older posts
scaffold:spa — a front end for an application that already exists
- The MCP server says which project it is
- Typed endpoints, generated from the document
- Where the suite's fifteen minutes actually go
- A shared document, seven eight-second tests, and a
? in the bar
- A scaffolded application was set up to learn it the hard way
- The suite was running
composer update sixty-one times
- The test database was afraid of losing data
TRUNCATE is slower than dropping the table
- The comment said
// product 1 = Apple
- The same change made PostgreSQL slower
- A suite that only passed in one order
- The guide described an API nobody had built
- The widget area that rendered nothing
maxRuntime was a range, and it read like a number
- An empty ban list is still a ban list
- The ingest dropped the id it had just read
- Which rule said no
- Four corrections from the other side of the boundary
- "Minor variable name changes"
- A blank page is not an error
6 changes:
- Five rolled-up views were frozen on every database without TimescaleDB
- A model may give
load() whatever parameters it needs
- Five developer panels had been empty for years, and nothing said why
- The rate limiter counted the proxy, and counted it badly
- A human check that prices spam instead of pretending to detect it
getInstance() is a factory, and two call sites forgot
16 changes:
pramnos init checks both Docker ports before proposing one
init scaffolds a working SPA — Svelte + daisyUI, Vite, Vitest and Docker
- Files the container writes now belong to you, not to root
- SPA follow-ups: the dev server, the site root, and the docs generator
- The FK migration stops assuming the schema of tables it does not own
- The scaffolded SPA now actually talks to the API
create:crud builds the SPA half too
- A debug bar a SPA can actually use — and a guide for testing the front end
- Generated CRUD gets real authorisation — and
delete gets any at all
- A SPA project gets an administration screen
cache:clear no longer wipes every installation sharing the backend
- Signing in works, screens have URLs, and the SPA wears the project's colours
Permissions answers from whichever store the installation has
- One permission system, available to every project with users
timescale:ensure — repairing hypertables on a database that got TimescaleDB late
- The GDPR endpoints queried a table that does not exist
3 changes:
pramnos init works in a freshly created project again
- Scaffolded Docker images ship the database CLI client
- A failed schema import is no longer silent
2 changes:
- Per-column search works again on server-side DataTables
- Serving init-less apps: migrations, capability accessors, test DB, daemon status
8 changes:
- Column comments are now applied when altering a table
- Partial indexes and column ordering in the schema builder
- Native enum types in the schema builder
- Attribute-routed controller actions now dispatch
- Auth controller tests no longer drop the shared
users table
- The test suite no longer leaves an
app/ directory in the repo
- Realtime: pluggable SSE + WebSocket backplane
- Cross-cutting improvements: flat-key cache, log output modes, media alpha fix