Latch 0.4.6.0
Changelog
All notable changes to Latch are documented here.
Format follows Keep a Changelog.
Versioning follows Semantic Versioning.
[Unreleased]
Work in progress on main — not tagged or released yet. Fold into the next version section before scripts/build-release.sh.
[0.4.6.0] — 2026-07-13
Added
- Forum UI cards — home board panels, board detail view, and topic header use unified card styling with stats where applicable.
- Privacy analytics tests —
PrivacyAnalyticsPluginTestfor audit, snippet rendering, and host validation. - Plugin asset docs —
docs/PLUGINS.mddocuments serving assets via routes,theme.assets/theme.scripts, HTML templates, and client-mode behaviour.
Fixed
- Client-mode plugin assets —
theme.assetsandtheme.scriptsstill run forguest_page: clientplugins; only content hooks (home.before_boards,home.after_boards,layout.head,layout.footer) use browser placeholders (PluginCacheCoordinator). - Admin SPA actions — board create/update, user search validation, and staff trash actions stay in the AJAX admin shell (
finishStaffAction/account-panel.js). - Moderation trash purge —
purgeArchivePosthandles orphaned archive rows; maintenance dashboard usescountArchiveQueue(). - Topic layout — post list separated from header card so replies no longer appear nested inside the topic header.
Changed
- Latch-plugins catalog — git-release 1.1.7 added (public GitHub release card); requires this core version for client-mode
theme.assets.
Tests
- PluginCacheCoordinator — regression test that client-mode plugins still collect
theme.assets. - GitReleasePluginTest — cache, stale fallback, and purge coverage (Latch-plugins catalog).
[0.4.5.3] — 2026-07-12
Added
- Plugin update —
php bin/latch plugin update <slug>and Admin → Plugins → Installed update action; replacesplugins/{slug}/from the catalog or a local zip while keepingstorage/plugins/{slug}/and enabled state. home.before_boardshook — home templates renderplugin_home_before_boards_htmlabove the board list (use with updated git-release for showcase layout).
Fixed
- Admin settings — saving site theme and other settings stays in the AJAX account panel / in-place admin shell instead of redirecting to the full admin layout.
Tests
- Link preview — regression test for
embed.jsplay-button binding (pair with link-preview 1.0.3 from Latch-plugins).
[0.4.5.2] — 2026-07-12
Fixed
- Admin log viewer — filter grid spacing; Apply/Clear on their own row below the filter panel.
- Admin audit log — code-view layout (summary row, Record/Details sub-rows) matching the log viewer.
- Modern theme —
asset_versionincludes active pack id so Cloudflare/CDN does not serve stale CSS when switching from Default.
Changed
- Maintenance / site lock — unlock CLI hint uses
sudo latch lock offon RPM installs (/usr/bin/latch). - Documentation —
INSTALL-FEDORA.mddisaster-recovery and fail2ban sections usesudo latch; jail documentssecurity.logpath.
[0.4.5.1] — 2026-07-12
Fixed
- Admin log viewer — code-style monospace panel;
Detailsand rawLineon full-width sub-rows below Time/Event/IP/User (no truncated inline JSON). - fail2ban
latch-login— jail watchessecurity.logforlogin_fail(real client IPs behind Cloudflare/local proxy); fixed Apache combinedfailregex; shiplatch-remoteip.conffor optional access-log client IPs.
Changed
- Documentation — fail2ban troubleshooting and server log viewer setup in
INSTALL-FEDORA.mdandSECURITY.md.
[0.4.5.0] — 2026-07-12
Added
- Admin log viewer —
/admin/logssource index and tail viewer forsecurity.logandrestore.log; optional Apache/PHP-FPM sources vialogs.server_logs_enabledinlocal.php. - Log engine — bounded reverse tail, byte cursors, rotation detection, security JSON filters (
event,ip,username, time range), textqsearch, and secret redaction on all output. - Live tail —
?live=1polls/admin/logs/feedevery 30s with rate limit and debouncedlogs.feedaudit. - CLI —
php bin/latch logs list|tailwith full filter parity and--follow. - Doctor — warns when configured server log paths are unreadable (with
setfaclhints). - Dashboard — login failure count from the last 500
security.loglines (links to filtered viewer).
Security
- Outbound URL guard — central SSRF checks cover IPv6 literals,
.localhosts, redirect targets, and plugin catalog GETs; link-preview delegates to coreOutboundUrlGuardand re-validates each redirect hop.
Fixed
- Showcase + account overlay — restore
containeron<main>so profile/admin AJAX panels load; account-panel.js also matchesmain.sc-main.
Documentation
- Server logs —
SECURITY.md,INSTALL.md,INSTALL-FEDORA.md,CLI.md, andpackaging/README.mdupdated for admin viewer setup and COPR log paths.
[0.4.4.4] — 2026-07-12
Added
- Branding v2 — favicon, Open Graph image, and optional dark-mode logo uploads (
/branding/favicon,/branding/og,/branding/logo-dark). - Admin site theme — choose the active visual theme pack from installed directories under
themes/(default,modern,showcase, …); stored asactive_themewithconfigfallback. - Showcase theme pack — reference implementation with custom layout shell, home/board/topic templates, partials, CSS, and
showcase.js(beyond token-only packs likemodern). - Profile color theme — instant-apply selector on the profile Appearance section (light / dark / system).
Fixed
- Custom logo in dark mode — single uploaded logo stays visible when no dark variant is configured.
0.4.4.3 — 2026-07-12
Added
- Operator site branding — Admin → Settings → Branding: upload SVG/PNG logo (max 512 KB), choose Latch built-in mark / custom image / text-only; served at
/branding/logo; sharedpartials/brand.html.twigfor default and modern themes.
Changed
- Admin settings — Branding section in a highlighted panel; Settings opens full page for reliable logo upload.
0.4.4.2 — 2026-07-12
Added
- Plugin client loader —
plugin-clients.jshydratesguest_page: clientplaceholders; loaded when any enabled plugin uses client cache mode.
Changed
- New topic form — removed markup hint text below the compose title.
Documentation
- Release — catalog publish checklist references Latch-plugins
check-release.shgate.
0.4.4.1 — 2026-07-12
Fixed
- Composer live preview — skips plugin link cards (link-preview) and inline images (image-upload); markdown images show a compact
[image]placeholder; smileys, spoilers, code, and other markup still render.
Changed
- Composer toolbar — grouped segmented buttons with icons, hover/focus states, and utility controls aligned to the right.
- Documentation — README, INSTALL, MARKUP, PLUGINS, and THEMING updated for v0.4.x (catalog admin UI, live preview, COPR).
0.4.4.0 — 2026-07-12
Added
- Plugin hook expansion (28 hooks total) — 11 new hooks for tier-1/2 plugins:
post.format.link,post.format.after— link preview / onebox at render timecsp.frame_src,csp.script_src— video embeds and analytics scriptslayout.head—<head>snippets (privacy analytics)topic.actions— topic header share buttons (fediverse-share)profile.form,profile.before_save— avatar-url and profile extensionspost.delete,topic.delete,post.vote— lifecycle hooks for plugin cleanup and reactions
- Standalone bare
https://URLs — auto-linked when alone on a line;post.format.linkreceives$standalone = true ProfileSaveContext— mutable context forprofile.before_save(mirrorsPostSaveContext)- Docs:
PLUGINS.mdhook reference updated;MARKUP.mdstandalone URL note
0.4.3.1 — 2026-07-12
Added
- Admin plugins UI — Installed / Catalog tabs with icon actions (install, enable, disable, settings, remove); SPA-friendly
?tab=navigation. fix-permsoverhaul — repairs all runtime paths (storage/,plugins/code, SQLite sidecars,local.php);--web-user/WEB_USERoverride (defaultapache).docs/RELEASE.md— full release checklist (VERSION, RPM, tarball, git tag, COPR);scripts/check-versions.shgate inbuild-release.sh.
Fixed
- GitHub release zip download — follow HTTP 302 redirect chain (GitHub →
release-assets.githubusercontent.com). - Catalog install permissions —
plugins/parent writable by web server; RPM%postsetsapache:apacheonplugins/. sudo latch fix-perms/plugin remove— wrapper stays root for chown and code deletion under/usr/share/latch/.- Admin plugins 500 — tab query uses
Request::input()(not missingquery()method).
Changed
- Remove control — trash icon beside plugin title; catalog install stays in-panel AJAX (no full-page bypass).
0.4.3.0 — 2026-07-12
Added
- Admin catalog plugin install — Admin → Plugins lists the Latch-plugins catalog and installs release zips with the same audit gate as
plugin install(plugin stays disabled until you enable it). php bin/latch totp reset <username> --confirm— operator recovery when 2FA codes fail after anencryption_keymismatch (documented inCLI.md,SECURITY.md,INSTALL.md).PluginCatalog/PluginReleaseDownloader— fetchescatalog.json, caches it, downloads GitHub release assets (API fallback when the direct zip URL 404s).
Fixed
- Admin SPA plugin actions — error flashes from catalog install are no longer wiped by an immediate in-panel reload; catalog install uses a full-page POST (
data-account-bypass). - Staff JSON errors — failed admin AJAX actions now also set session flash so messages survive navigation.
[0.4.2.0] — 2026-07-11
Added
bin/latch fix-perms— one-shot repair for root-ownedstorage/plugins/andstorage/cache/plugin-audits/(use after a badsudo php bin/latch plugin …).- Plugin auditor PSR-4 check — CRITICAL finding when a plugin class path does not match
PluginLoaderautoload layout (blocks enable). - Plugin auditor runtime checks — CRITICAL findings for root-owned or non-writable plugin storage on installed plugins under
plugins/. PluginStoragePermissions— whenplugin enableruns as root, chownstorage/plugins/{slug}/to the web server user.
Fixed
bin/latch audit— includes full Doctor layer-4 permission checks (plugin storage, audit cache, world-readable DB/config); install and upgrade gates catch permission regressions.- Plugin settings / audit cache writes — clearer errors pointing at
sudo latch fix-permsand the RPMlatchwrapper. - spam-bridge (Latch-plugins 1.0.2) — PSR-4 autoload split (
AppRegistrationEnforcer.php), reloadsettings.jsonon each check so provider changes apply without disable/enable.
Changed
scripts/install.sh— runsdoctorandauditas hard gates (no longer ignores doctor failures); prints RPM plugin permission reminders.- Audit / update failures — actionable “How to fix” hints (
fix-perms,doctor,sudo latch plugin enable). - Docs — production plugin permissions in
PLUGINS.md,INSTALL.md,INSTALL-FEDORA.md, andCLI.md.
[0.4.1.0] — 2026-07-11
Added
- Latch-plugins catalog v1.0.0 — tier 1 plugins (
forum-stats,image-upload,word-filter,spam-bridge,slack-notify) published at github.com/YeOK/Latch-plugins with per-plugin and bundle release zips. - PR-P6 manifest cache —
cacheobject inplugin.json;tagPlugin:{slug}invalidation; bake / fragment / client / bypass guest modes;PluginCollectContext; CLI enable/disable busts plugin cache. - PR-P3 plugin database — per-plugin
plugin.sqlite,PluginMigrator, migrations on enable/boot;docs/plugins/dbexample/reference. - spam-bridge — Akismet + Stop Forum Spam on
post.before_save/user.register;spam_login plugin SQLite (catalog). - slack-notify — Slack/Discord incoming webhooks on
post.after_save/user.register(catalog).
Fixed
- PluginCollectContext fatal —
Application::resolvedLocale()andcspNonce()are public so the app boots with PR-P6; regression test added. - Guest cache bypass —
guest_page: bypassnow disables fragment cache as well as full page cache.
Changed
- Plugin packaging — tier 1 plugins removed from core
plugins/; install viaplugin installfrom catalog zips. Operatormd-importexcluded from public tarball. - PR-P4 image-upload — operator toggles (
max_mb,key_prefix,allowed_types) in admin settings /settings.json; R2 secrets remain inlocal.phponly. - PHPUnit — catalog plugins resolved from sibling
Latch-plugins/(orLATCH_PLUGINS_CATALOG) for plugin tests. - Release build — exclude internal
docs/design/anddocs/RELEASE-v0.3.0.mdfrom public tarball.
[0.4.0.0] — 2026-07-11
Added
- Mail queue — optional
mail_queuetable and worker for notification email bursts; enabled in Admin → Settings; drained bycron hourlyorphp bin/latch mail process. Auth emails (verify, reset, email change) stay synchronous. - Plugin install/remove —
php bin/latch plugin install <dir|zip>copies intoplugins/{slug}/with audit gate (rollback on critical);plugin remove <slug> --confirmdeletes installed copy; optional--purge-storage. - Word filter plugin — bundled
plugins/word-filter/blocks or masks profanity onpost.before_save; ships basic blocked-word list; Aho-Corasick matcher; staff bypass; code fences ignored. - Plugin admin settings —
settings_schema/secrets_schemainplugin.json; generic form at/admin/plugins/{slug}/settings;PluginSettingsStoremerges defaults withstorage/plugins/{slug}/settings.json; word-filter is the first consumer. - Plugin catalog repo — github.com/YeOK/Latch-plugins created for future distributable plugins and GitHub Release zips; admin catalog install not implemented yet (
plugin installlocal dir/zip remains). - Bundled plugin install policy — documented and enforced:
"bundled": truein manifest;enabled_pluginsdefaults to[]on new installs; upgrades preserve operator enable/disable state (migration 028INSERT OR IGNORE).
0.3.0.23 — 2026-07-10
Added
- Fragment cache — guest HTML fragments for home board panels and board topic lists (
storage/cache/fragments/); same tag invalidation as page cache. - Large-topic pagination — cursor-based post chunks above
forum.topic_pagination_threshold(default 50);GET /topic/{id}/posts?after=load-more;?latest=1jump to tail. - SQLite scale guide — operator limits and migration notes in
docs/PERFORMANCE.md. - CDN guide — Cloudflare cache rules in
docs/CDN.md.
0.3.0.22 — 2026-07-10
Fixed
- Version display —
/health, admin dashboard, and plugin compatibility read the treeVERSIONfile first (RPM:/usr/share/latch/VERSION), withapp.versionin config as fallback. Fixes production showing0.3.0.20after deploying0.3.0.21whendefault.phpwas not bumped.
0.3.0.21 — 2026-07-10
Security
- Open redirect —
Request::safeRedirectFromReferer()requires exact host match withsite.url;safeRedirectPath()tightens path allowlist.LocaleControllerand rate-limit redirect inReportControlleruse the helper. Regression tests inSecurityRegressionTest.
Fixed
- Accessibility (light theme) — badge and footer link contrast via
--badge-fg/--footer-link-fg;.board-panel-view-alluses--accent-hoverfor WCAG 4.5:1 on white surfaces (default + modern themes). - GDPR / Gravatar — third-party avatars load only after
latch_cookie_consent=acceptedin EU hosting mode; identicon placeholders with deferreddata-gravatar-srcuntil accept.CookieConsentGate+ updated cookie policy copy (all locales).
Changed
- PHPUnit configs — split smoke/security into
phpunit-smoke.xml.distandphpunit-security.xml.dist;bin/latch testpicks config by suite (eliminates duplicate-suite warnings). - Public docs & templates — replace operator-specific
latch.networkexamples withforum.example.com; footer usessite.urland GitHub for “Powered by Latch”; release build rejectslatch.network/images.latch.networkin stagedsource/.
0.3.0.20 — 2026-07-07
Fixed
- Messages overlay (i18n) —
messages-panel.jsdefinedLatchI18nonly inside a click handler whileloadPanel()/closePanel()referenced it at module scope; opening Messages threwReferenceError: i18n is not definedand AJAX feeds never ran (v0.3.0.19 regression). - Admin overlay history — closing the account/admin panel after in-panel navigation now walks back the full
historystack (overlayPushDepth) so refresh no longer lands on the last admin URL. - Header vs main width — public header, main, and footer share one column rule (
.latch-header .header-barincluded); header no longer renders wider than topic/board content when guest cache omitspage-forum. - Pinned badge contrast — dark theme badge tokens (
--badge-fg/--badge-bg) meet WCAG contrast on pinned labels (default + modern themes).
Changed
md-importimages — HTML<img>/<picture>tags and foreign-host markdown images convert to a CDN placeholder (/.md-import/REPLACE-ME.png) so imports passimage-uploadBodyGuard and can be swapped in the editor.- Apache packaging example —
packaging/latch-httpd.confdocumentsServerAlias www.forum.example.com.
[0.3.0.19] — 2026-07-05
Fixed
- Forum layout width (board vs topic) — public
mainand footer width no longer depend on thepage-forumbody class, so board and topic/post views stay aligned with the header even when guest page cache serves stale HTML withoutpage-forum(default + modern themes). - Home page (members-only lead) — Twig
replacemap no longer uses an invalid dynamic key; fixes HTTP 500 on/when registration is disabled.
Added
- Internationalization (Phase 7) — guest/member Twig templates, legal pages, profile and auth flows, board/topic sort labels, and first-party JS overlays (
window.LatchI18n) uselang/{locale}.phpviatrans(). Catalog:en,es,de,fr,ar(complete Arabic; English fallback for missing keys). RTL layout hooks for Arabic in defaulttheme.css.LocaleCatalogTestasserts key parity across locale files. - PHP i18n (Phase 8) —
NotificationMessageFormatterlocalizes notification feed/page text at read time (notify.*keys); report reason labels usereport.*;Application::flashTrans()+FlashMessagekey constants for controller migration;api.*for JSON errors. Notificationmeta_jsonnow storestopic_titleon new events.
Changed
- Admin plugins audit column — pass/fail shown as icons; scan timestamp and cache status moved to hover tooltip.
- RPM upgrades —
packaging/latch-rpm-updaterunsscripts/update.sh --clear-cachesodnf upgrade latchpurges guest HTML after deploys (theme/layout fixes take effect without a manualcache-clear). - Packaging hygiene —
source/vendor/removed from git;composer.lockis the source of truth. COPR%build,scripts/build-release.sh, andscripts/install.shruncomposer install --no-dev(bundledsource/composer.pharfallback). Release tarballs still ship a populatedvendor/.
[0.3.0.18] — 2026-07-05
Changed
- Forum layout width —
page-forumnow aligns the site footer with header and main column on both default and modern themes (body.page-forum :is(main.container, .site-footer .container)). - COPR/RPM builds —
%buildrunscomposer install --no-devwhen mock builds have network access (BuildRequires: composer); release tarballs still shipvendor/(built bybuild-release.sh).
[0.3.0.17] — 2026-07-05
Changed
- Forum layout width — home, board, topic, tag, search, and watched pages share one content track (
page-forum); header and main column stay aligned on all forum views.
Fixed
app.versiondisplay —config/default.phpstays in sync withVERSION/ git tag (fixes/healthand admin version panel showing 0.3.0.15 after 0.3.0.16 RPM deploy).- Header consistency — site header uses the same width and desktop height on every public page, not only the home page.
[0.3.0.16] — 2026-07-05
Changed
- Bulk topic moderation (scale) —
BulkTopicActionServicedefers guest-cache and FTS side effects to one flush per request;ModerationTrashBatchbatches search removals on bulk delete; board UI sends large selections in chunks of 20 with progress (board-mod-tools.js); per-topic author notifications skipped in bulk (audit log unchanged); Delete all mod trash uses batched cache invalidation. Documented in PERFORMANCE.md. - Lighthouse (guest home page) — Chrome Lighthouse on dev (
127.0.0.1:8080, 2026-07-05): Performance 100, Accessibility 100, Best Practices 100, SEO 100. Production baseline before this release (v0.3.0.15): 100 / 94 / 81 / 100.
Fixed
- CSP on cached guest pages — guest page-cache hits rewrite inline
nonceattributes to match the per-request CSP header (fixes theme FOUC script blocked in Lighthouse/DevTools). - Admin users bulk script — inline bulk-action script includes CSP nonce.
- Lighthouse accessibility — header brand link uses visible text for its accessible name (drops redundant
aria-label); footer inline links are underlined so they are distinguishable without relying on color alone. - PHP 8.5 deprecations —
DatabaseusesPdo\Sqlite::OPEN_READONLYwhen available;BoardAcl::viewerLevelno longer indexesLEVELSwith a null role.
[0.3.0.15] — 2026-07-05
Added
- SQLite connection tuning — configurable
database.sqlitePRAGMAs inconfig/default.php(busy_timeout_ms,cache_size_kib,mmap_size); override inconfig/local.php; documented in INSTALL.md. - Theme JS security scan —
ThemeJsAuditorintest --securityfor first-partythemes/default/assets/js/(complements GitHub CodeQL); see TESTING.md. - Plugin audit cache — results stored under
storage/cache/plugin-audits/; admin Plugins reuses cache when files unchanged;cron dailyrefreshes all non-ignored plugins. - Plugin ignore (CLI) —
php bin/latch plugin ignore <slug>sets"ignored": trueinplugin.json, disables the plugin, and excludes it from discovery, audits, and admin UI;plugin unignore/plugin list --allrestore visibility.
Changed
- Plugin audits — admin page no longer re-scans every plugin on every load; enable and
plugin-auditstill force a fresh scan. - Documentation —
PLUGINS.md,CLI.md,TESTING.md,PERFORMANCE.md,SECURITY.md,CONTRIBUTING.md, andlocal.php.exampleupdated for SQLite tuning, XSS gates, and plugin audit workflow.
Fixed
db-checkcorrupt files — truncated or malformed SQLite files return a failed report instead of throwing during read-only open (regression after configurable PRAGMAs).- New topic composer — fixed regression where
restoreSavedDraft()cleared then immediately re-applied the saved draft; new-topic forms no longer restore localStorage drafts, use readonly-until-focus to block browser autofill onbody, and setautocomplete="one-time-code". - DOM XSS (CodeQL) —
account-panel.js,staff-actions.js,messages-panel.jsuse safe DOM APIs instead of unsanitizedinnerHTML/hrefconcatenation.
[0.3.0.14] — 2026-07-05
Changed
- Copyright headers — MIT
SPDX-License-Identifiernotices added to first-party PHP, shell scripts, and theme/plugin assets;scripts/add-copyright-headers.pybackfills new files. - Public tree hygiene —
.gitignoreblocks operator deploy symlinks (latch-logs.sh,setup-api-test-client.sh, etc.); test fixtures and docs examples use generic usernames instead of operator handles (COPR/gityeokpaths unchanged). - Account deletion — self-deleted users set
deleted_atinstead ofbanned_at; admin Users has a Deleted tab separate from Banned; migration032backfills existing self-deleted rows; daily cron hard-purges self-deleted accounts after 30 days (cron_deleted_user_retain_days) while posts/topics remain (author shows as[deleted]). db-check—foreign_key_checkignores expected author orphans (posts/topics/post_revisions→ missingusersrow) after retention purge; real FK problems still fail the gate.- Install / security bootstrap —
bin/latch installwritessecurity.encryption_keyinto newlocal.phpand runssecurity-bootstrapwhen the key is still missing;doctorfails on installed instances without a valid key; INSTALL.md documents 2FA and bootstrap in the first-deploy path. - First-time install script —
scripts/install.shwraps Composer,bin/latch install,doctor, and optional cron for tarball/git installs; cron template ships atscripts/cron/latch.cron.example(fixes brokeninstall-cron.shon public trees). - Operator preflight —
doctorwarns when daily cron has not run in 48h; admin Deleted tab shows retention fromcron_deleted_user_retain_days;UserDependencyCleanupclearsissued_by/editor_id/ OAuth client / trash staff references on purge. - Release gates — smoke suite adds account deletion, profile delete, report queue, DMs, 2FA cancel, and doctor checks; security suite adds OIDC authorization URL tests;
LATCH_TEST_URL/LATCH_URLenable HTTP smoke without a config file. - CONTRIBUTING.md — contributor setup, test gates, and release notes for OSS onboarding.
Fixed
- Two-factor sign-in — “Back to sign in” clears the pending 2FA session instead of looping back to the code prompt.
- New topic composer — no longer pre-fills from a stale quote/reply draft or browser
bodyfield cache; quote-shaped localStorage drafts are discarded; draft clears after a successful post.
0.3.0.13 — 2026-07-05
Added
- Direct messages — delete empty conversations (trash icon in thread header); per-message delete on your own messages is easier to spot on mobile.
- Post editor — toolbar adds bullet list, heading, and @mention helpers plus a
?markup cheat sheet; existing buttons show syntax in tooltips. - Code blocks — live AJAX preview under the composer (no Write/Preview tab); Code button inserts a fenced block and a language dropdown appears while the cursor is inside it; topic posts highlight fenced blocks with highlight.js; language label shown on read view; editor uses a 70/30 split with scroll-synced preview; textarea is vertically resizable while the preview pane stays fixed.
Changed
- Theme performance budgets (
docs/THEMING.md) — raised composeeditor.jscap to 32 KB (live preview, code blocks, reply flow); documentedhighlight.min.jsand refreshed CSS/staff size targets to match the default theme. - Footer — language selector moved from Explore to Operator column.
- README screenshots — refreshed boards home and admin dashboard images from latch.network.
- INSTALL.md / INSTALL-FEDORA.md — drop pre-COPR
sync-latch/publish-latch-serverwording; point vhost and permissions fixes at public paths (packaging/latch-httpd.conf,scripts/fix-latch-storage-perms.sh).
Fixed
- Topic reply — Reply no longer restores a stale quoted draft from localStorage (non-quote drafts are still restored); Quote still pre-fills the attributed quote; reply draft clears after submit.
- Code highlighting (dark theme) — syntax colours use a high-contrast dark palette so keywords and strings stay readable on dark backgrounds.
- Header alignment — theme toggle and sign-in / user menu align to the right edge of the main content column (matches boards Topics/Posts stats track); search bar centred in the header on desktop (equal side tracks in a 3-column grid).
- Release hygiene —
router-dev.phpmoved out ofsource/public/toscripts/router-dev.php(dev-only PHP built-in server router); excluded from release tarball and COPR%installso it is not web-accessible on production installs.
0.3.0.12 — 2026-07-04
Added
- phpBB import (Phase 6 v1) —
bin/latch import phpbbwith--dry-run/--confirm(JSON bundle) and--export --from-mysql=(requirespdo_mysql);BbcodeConverter,import_mapmigration031, fixture bundles underscripts/fixtures/phpbb/. - Phase 5 test gates —
bin/latch test --smokeandtest --securityrun dedicated PHPUnit suites (phpunit.xml.dist), thendb-check/audit; optional live HTTP probes with--url=ortests/smoke/config.local.php; smoke also runstests/api/harness when API config exists. CsrfTest,SecurityRegressionTest— CSRF rotation/validation and markup/SSRF regression coverage in the security suite.- Outbound URL guard — webhook create/delivery rejects private, loopback, and link-local targets (SSRF mitigation).
- Plugin enable gate — markup/JS injection audit warnings now block enable (stricter than audit pass).
- Theme manifest note —
themes/default/README.mddocuments thattheme.jsonis not loaded at runtime.
Fixed
- OIDC registration — new Google/GitHub sign-ups now respect registration disabled and per-IP signup rate limits; linking existing accounts is unchanged.
md-import+image-upload—BodyGuardno longer treats markdown image syntax inside inline or fenced code as real post images, so documentation likedocs/PLUGINS.mdimports successfully whenimage-uploadis enabled.md-importadmin form — import uses a full-page POST (data-account-bypass) so file uploads and hook rejection flashes are reliable; admin SPA now navigates away when a form redirects outside/admin(e.g. to the new topic).
Changed
- Locale quick switch —
POST /localewith CSRF replacesGET /locale/{code}. - TOTP enrollment — requires
security.encryption_keyinconfig/local.php(derived-key encrypt is decrypt-only for legacy secrets). - CSRF rotation — new token after login and sensitive profile/2FA mutations.
- Moderation trash — shared restore/purge logic for admin and mod controllers.
Removed
- Dead code:
BoardIconProviderInterface, unusedApplication::router()/hooks(), sortlabel()helpers, orphanfield_input.html.twigpartial.
[0.3.0.11] — 2026-07-04
Added
- Bulk topic moderation — moderators can multi-select topics on board pages to pin, unpin, lock, unlock, or remove in one action (shield toggle on the topic list).
- Post sort on topics — sort replies by oldest first, newest first, or most likes; control sits below the mod shield button, matching the board layout.
- Delete all mod trash — admins can permanently purge the entire moderation trash queue from Admin → Maintenance (with confirmation).
Changed
- Board topic sort — sort dropdown moved to the right column below the mod shield (no separate “Sort” label).
- Topic quick actions — pin, lock, and remove buttons moved beside the mod shield on topic pages; watch stays in the header.
[0.3.0.10] — 2026-07-04
Fixed
- Admin 500 after upgrade — stale PHP-FPM opcache could still run the pre-0.3.0.9
HookRegistryafterdnf upgrade, breaking plugin sidebar links (md-import). RPM%posttransnow restartsphp-fpm; admin layout skips non-mapping menu entries defensively.
[0.3.0.9] — 2026-07-04
Added
md-importoperator plugin — admin upload/paste of.mdfiles to create formatted topics (GitHub-style rendering); lives under Admin → Import markdown with in-panel SPA navigation. Excluded from public release tarballs; shipped in git/COPR for operator installs.
Fixed
- Plugin admin menu —
admin.menuhooks returning a single{label, href}item no longer break the admin layout (500 on strict Twig).
Changed
- Admin dashboard — added Topics, Boards, and Open reports stat cards; new System panel (database size with WAL breakdown, guest cache, last cron runs, mail status) sits below forum stats and above the version panel.
- Footer about text — site-specific copy below the footer logo is editable in Admin → Settings (below Tagline). Single line breaks and blank lines between paragraphs are preserved in the footer. Leave empty to fall back to the tagline. Fresh installs seed the previous default Latch marketing text.
- Example plugins —
example,badexample, andwarnexamplemoved fromplugins/todocs/plugins/so they are not auto-discovered; copy intoplugins/{slug}/when needed. Active bundled plugins remainforum-statsandimage-upload. - Plugin admin pages — document registering admin UI under
/admin/…for SPA in-place loading (PLUGINS.md).
[0.3.0.3] — 2026-07-03
Fixed
- Public docs — removed operator-specific references (
yeok,henpen.dev, private IPs) fromINSTALL.md,EMAIL.md,CLI.md, andUPGRADE.md; dropped henpen msmtp fallbacks fromMailauto-detect.
Changed
- Release tarball —
build-release.shnow excludesPLAN.md,deploy/forum-data/,deploy/msmtp.conf, site-local fail2ban overrides, and private deploy scripts; fails the build if operator hostnames or paths remain in the staged tree.
[0.3.0.2] — 2026-07-03
Fixed
- Fresh install migration order —
001.5_security.sqlsorted before001_initial.sqlundersort(), so new installs failed onALTER TABLE usersbefore the table existed. Renamed to001a_security.sql; existing databases that already recorded001.5_security.sqlinschema_migrationsare not re-applied.
0.3.0.1 — 2026-07-03
Security
- Removed leaked artifacts from release — v0.3.0 accidentally shipped
source/storage/backups/*.tar.gz(containedconfig/local.php+ SQLite) and operator forum-post manifests undersource/data/. If you downloaded v0.3.0, rotatesecurity.encryption_keyon any install that shared those backup files and treat the old key as compromised. build-release.shnow excludessource/data/andsource/storage/backups/*and fails the build if either is present in the staged tree.
Changed
- Operator forum-post JSON/MD lives under
deploy/forum-data/(local only, never in git or tarball).
0.3.0 — 2026-07-03
Withdrawn artifact — use 0.3.0.1 instead. The v0.3.0 tarball contained dev backup archives and operator forum-post data; do not use it.
First public release. Latch is an MIT-licensed, self-hosted PHP + SQLite forum engine. Production has been running at latch.network; this tag is the sanitized open-source artifact.
Added
Forum & UX
- Boards, topics, posts, Markdown-style formatting, spoilers, smileys, topic tags
- Full-text search (FTS5), RSS feeds, sitemap, guest page cache
- Light/dark theme, board icons, topic watch / unread state, post reactions (like/dislike)
- Direct messages with opt-in, staff warnings, and blocks
- In-app notifications and optional email copies
- User profiles, reputation ranks, board min-rank gates
- Report queue, quarantine, mod trash queue, user warnings
- Board ACLs (
guest/member/modread and post rules)
Security & auth
- Password login with account lockout counters and optional TOTP 2FA
- Password reset and email verification flows
- Session registry, security event log, CSP and security headers
- Admin audit log, login rate limiting (fail2ban-friendly HTTP 200 on failure)
- Site maintenance lock (blocks web + API during upgrades)
- OIDC social login hooks (Google/GitHub) — disabled until configured in
config/local.php
API & integrations
- OAuth 2.0 API (
/api/v1/*, client credentials and authorization code + PKCE) - Outbound webhooks with signed deliveries
- i18n foundation (
lang/files, locale switcher hooks)
Plugin system (Phase 4)
- Hook registry,
plugin.jsonmanifests, enable/disable via CLI and/admin/plugins - Static
plugin-auditscanner (PHP, markup, JS patterns) with audit gate on enable - Bundled reference plugins:
example— minimal route + footer hookforum-stats— home page totals panel (home.after_boards)image-upload— R2 presigned direct upload + compose toolbar (no files instorage/)badexample/warnexample— audit pass/fail fixtures for tests and docs
Operator CLI (source/bin/latch)
install,migrate,audit,backup,restore,db-check,update,lockcron hourly|daily|weekly— DB prunes, reputation jobs,ANALYZE(never purges guest page cache on daily)doctor— PHP extensions, vendor, DB permissions, writable pathstest,test --smoke,test --security— PHPUnit gates (+db-check/auditon smoke)plugin list|enable|disable,plugin-audit,api-client,search-reindex,benchmark- WAL-safe SQLite backup via
scripts/sqlite-backup.php
Release & docs
VERSION(0.3.0),scripts/build-release.sh(sanitized tarball + SHA256)scripts/update.sh— lock → backup → migrate → db-check → audit → unlock- Operator docs:
source/docs/INSTALL.md,UPGRADE.md,CLI.md,PLUGINS.md,API.md,SECURITY.md,PERFORMANCE.md,TESTING.md
Tests
- 216 PHPUnit tests (543 assertions) — forum core, plugins, backup/restore, cron, OAuth scopes, SQLite integrity
Fixed
- Mod topic delete confirm — staff trash icon on the topic header no longer clips the “Remove this topic from the board?” popover off-screen; popovers use fixed viewport positioning and right-aligned header CSS
- Theme asset cache busting —
Application::assetVersion()appends theme file mtimes so deploys invalidate CDN/browser caches without manually bumpingtheme.asset_version - Theme asset HTTP caching — static CSS/JS served with
max-age=86400, must-revalidate(removedimmutable) so upgrades pick up new assets within a day - PHPUnit schema cache —
Schema,UserRepository, andUserDependencyCleanupkey column/table caches per PDO connection (fixes false failures when tests swap in-memory databases) - PHPUnit fixtures — cron, direct-message, and moderation tests aligned with current schema (
verified_at, OAuth tables,reports,banned_at, etc.)
Changed
- Avatars: Gravatar + identicon only in core; arbitrary HTTPS avatar URLs removed (optional future plugin)
- Bundled
forum-statsandimage-uploadplugins useassetVersion()for their static assets - Upgrades replace
source/app/,bin/, and migrations;storage/,config/local.php, andplugins/are preserved
Security
- Release tarball excludes
local.php, live SQLite, logs, cache, and private deploy scripts build-release.shfails if likely secrets are detected in stagedsource/- Restore requires site lock by default; pre-restore snapshot on rollback path
Known limitations (planned follow-ups)
- Packagist / Docker install layers — tarball + git clone for 0.3.0
- phpBB import — design only (
docs/design/phpbb-import.md); Phase 6 - Admin UI localization — admin templates remain English-only
- Controller flash migration — most
session()->flash()calls still use hardcoded English; migrate toflashTrans()+FlashMessageincrementally - OIDC E2E — code ships; providers need operator credentials and manual checklist (
docs/TESTING.md) - Custom avatar URL plugin — optional; not bundled in 0.3.0
Release checklist (operators)
# Build (maintainer)
./scripts/build-release.sh
sha256sum -c dist/SHA256SUMS
# Fresh install
tar -xzf latch-0.3.0.tar.gz && cd latch-*-stage/source
composer install --no-dev
php bin/latch install --url=https://forum.example.com --name="My Forum"
# Upgrade existing install
cd /var/www/latch && sudo bash scripts/update.sh