v0.5.3

<p>Pages get a published flag and an access limit that visitors and queries both respect, and the admin gains a page Settings tab, a ⌘K search palette and page status lights.</p>

3 October 2026

Added

  • Page::$published and Page::$access replace the old status string. A page is live only when published. access says who may open it: empty for anyone, login for any signed-in user, or role names joined by |. Page::save() rejects an unknown role.
  • Page::assertViewable() and Page::isViewable(), run first in Page::route(). An unpublished page is a 404, a gated page redirects a signed-out visitor to login, and the wrong role gets a 403. A page is closed if it or any ancestor is.
  • Registry queries apply the same rule in SQL, so find(), counts, limit and offset only see pages the visitor may open. The registry has published and access columns and a partial index, idx_registry_gated, that keeps the check fast (schema 15).
  • App::isEditor() (signed in with admin.access) and App::seesAll() (an editor, or the CLI). Both skip the checks above.
  • Page::settingFields() returns published, access, hidden and locked as ordinary fields. The edit panel has a Settings tab built on it, saved by page/settings/{path} and gated by pages.publish.
  • The checkboxes fieldtype, a multi-choice list. The access setting uses it.
  • hidden, open and readonly as global option fields. "label": false hides a field's label in the admin (Field::$labelled). A field with no stored value falls back to its default option.
  • phlat page:access <path> --to=public|login|<role>. make:page takes --publish and --access=, and page:status is now page:publish <path> [--off].
  • Page::new() emits page.create:after.
  • A ⌘K search palette replaces the admin search page.
  • Status lights on each row of the admin page tree, and a statusbar under the preview (ui/statusbar.latte, replaceable from site/views/@admin/ui/statusbar.latte). They show published, access, hidden, unsaved draft, uncommitted changes and locked.
  • A filter toggle on the page tree that turns secondary while a filter is active.
  • Dt::setTimezone(). The timezone config key is now applied at boot.
  • Session cookie hardening in phlat/php.ini: session.cookie_httponly, session.cookie_samesite=Lax and session.use_strict_mode. PHP errors go to the log instead of the response (display_errors=Off), and expose_php is off.

Changed

  • status is gone from Record, the registry and History. Pages made by make:page and the admin start unpublished.
  • An editor's autosave draft shows only in the admin preview iframe. The same editor browsing the site directly sees what is saved.
  • created and updated are always written in UTC, so they sort chronologically whatever the site timezone.
  • phlat/config.json defaults timezone to UTC, drops domains, api, auth.logout and auth.admin, and gains features.versions (off).
  • env.json and env.cli.json are read from site/ instead of data/. backup:create, backup:restore and deploy.php follow.
  • session.expire also sets gc_maxlifetime, so PHP's collector no longer deletes idle sessions after 1440 seconds. Session::isThrottled() loses its unused $window argument.
  • FieldValueSet::fromRequest() keeps a readonly field's stored value instead of reading its input, and does not validate a hidden field.
  • Registry::boot() is public and replaces ensureBooted().

Fixed

  • Textareas autosize again after an htmx swap, and use their content height as the minimum.

Removed

  • The nyholm/psr7 dependency.
  • App::noContent() and the App wrappers pushUrl(), replaceUrl(), retarget(), reswap() and reselect(). Use Hx::.
  • History::hasDeployKey(), deployKeyPublic(), generateDeployKey() and discardPath(). History::$deployKey is public.
  • Registry::batchGet() and Record::isAddonObject().

Comments

No comments yet. Be the first!

Loading form…