Официальный сайт SLAED CMS
Журнал изменений
The comment list takes the second part of the list canon of the panel: the canon draws the rows from their cells and names every cell by its column, so one table carries four views, stays readable as cards on a phone and keeps its head in view. Tablesort now binds on the first load, which no sortable table of the panel or the site did before.
Core changes:
- List canon rows and view (core/helpers.php, partials/admin-list.html, fragments/table.html, table-cells.html):
getTplAdminList() takes rows as cells and gives each cell the name of its column; rows_html stays for the screens not yet on the canon
the view switch stands at the right end of the row over the table: "Стандартный", "Полный", "Компактный", "Карточки", one stop of Tab, the arrows walk it
- the cookie density, read by getTplAdminList(), puts data-sl-density on the table in the first byte
- table-cells.html gains label (data-label), stamp (<time datetime> and data-sort) and text_html (sl-cell-text)
- table.html carries the key a kept sort is stored under and the words that say it
- Option op (admin/index.php):
- setAdminOption() takes the key density: full, compact or cards set the cookie, anything else deletes it
- Comments on the row canon (admin/modules/comments.php):
the rows are cells; the date is a stamp, the comment text a text cell, its popover a prefix with its own label ("Подробности: Комментарий N") and the id of its panel
- the title of the comment cell no longer shows the markup of the search highlight
- Behaviour (public/plugins/system/slaed.js, templates/admin/assets/js/admin-ui.js):
slaed.js runs before tablesort.min.js in the deferred bundle, so the tables now wait for the end of the bundle; every data-sl-table-sort table of the panel and the site sorts and shows its arrows on the first load
- a table naming its key gets the last sort of its viewer back quietly and says a new one on data-sl-said
- the view applies at once and is stored through op option; a refusal puts the view back
- the date of a list reads relative in the language of the page, the exact moment stays in its title
- the rows a filter, a tab or a page brings enter one after another; a list Back restores only stands
- Theme and canon fragments (templates/admin, templates/lite, tools/ui-contract.php):
the views, the sticky head, the tint of the row in hand and the stronger one of a picked row in theme.css admin
- cards on a phone with the names of their columns; a pick puts the bulk action at the foot of the screen
- the cascade fills backwards only, so no row stays a stacking context over the tip of the row above
popover.html of both themes opens from a real button beside its panel, with tip_label and tip_id
- the panel is no part of the button any more, so the IP link in it stays a link (axe nested-interactive)
- --sl-d-order is declared in the data list of the contract; the audit baseline is stored
- Texts, help and plan (lang/.php, admin/lang/.php, admin/info/comments/ru.md, docs/*):
_DETAILS in the site language, _ADM_VIEW, _ADM_STD, _ADM_FULL, _ADM_DENSE, _ADM_CARDS in the panel language, all six locales
- the help of "Comments" describes the views, the sort, the date and the tip
- the answers of step 9 are recorded in docs/12-ADMIN-UI-2026.md and step 97 is ticked in docs/ROADMAP-2026.md
Benefits:
- one row canon for every panel list of steps 12-13: the module passes cells, the phone cards come with them
- sorting works on the first load on every sortable table, not only after an htmx swap
- the popover is a named button whose panel a screen reader reads, in both themes
Technical notes:
- no schema or route change; op option gains the key density and the cookie user_c-density
- the tables that never sorted on the first load now do: a visible change on every sortable screen of both themes
- the stand's config/local.php has to be rebuilt after the CSS and JS change, as after every release
The comment list is the first consumer of the list canon of the panel: one helper draws the head, the table or the empty state and a pager over and under it inside one element that htmx redraws in place, and the footer of the panel answers such a request with the title and the content only, so no module carries code of its own for it.
Core changes:
- List canon frame (core/helpers.php, core/system.php, partials/admin-list.html):
getTplAdminList() renders #sl-list with hx-target this, outerHTML, hx-history-elt and the header X-SL-Part
- the pager is drawn twice: the copy over the list carries "Down" to #sl-list-end instead of "Top"
- the empty state says "nothing found" under a filter and "all checked" in a calm tone for an empty queue
- the shell carries the line a screen reader hears, copied into the status line of the layout after a swap
- setFoot() answers X-SL-Part with the title and the content only; a request without a session gets HX-Refresh
- getTplAdminTabs() takes the key part: the tabs that switch the list in place carry hx-get with a pushed address
- Comments on the canon (admin/modules/comments.php, fragments/list-filter.html):
getCommentsFilter() replaces six copies of the filter parsing and keeps num in the way back
- edit, save, approve, delete and the bulk action return to the same page when the tab does not change
the filter moved from PHP strings into a fragment: every field labelled, the module applies at once, the search on OK
- OnChange="submit()" is gone; data-sl-filter-now submits the form, htmx carries it inside a live list
- Behaviour (public/plugins/system/slaed.js, templates/admin/assets/js/admin-ui.js):
- a list loading is aria-busy under the loading mark; a failed load keeps rows and filters and offers "Retry"
- the tab title takes the count of the queues again after a swap
- Back or Forward redraws a restored history element through htmx:historyRestore, the Node list of the site included
- Theme and canon fragments (templates/admin, templates/lite):
- pager.html of both themes gains is_top; the dead hx_get branch of tabs-link.html serves the in-place tabs
the filter, the list head, the notes, the empty and busy states in theme.css; the key tip and the ways up and down of every panel pager in their tones; under 900px the module head stacks its title over its filter
- fragments/module-foot.html and the .sl-module-foot rules are deleted: the canon owns the bottom row now
- three coincidental rule bodies are recorded in tools/ui-contract.php; the audit baseline is stored
- Texts and plan (lang/.php, admin/lang/.php, docs/12-ADMIN-UI-2026.md, docs/ROADMAP-2026.md):
- _PAGEEND in the site language, _ADM_LISTERR and _ADM_CLEAN in the panel language, all six locales
- the answers of step 8 are recorded, step 96 is ticked, the Tablesort load order found on the way goes to step 9
Benefits:
- one frame for every panel list of steps 12-13, without a partial check in any module
- a filter, a tab or a page no longer reloads the panel, and Back returns the previous view
- the filter is labelled and announced: axe on "Comments" falls from 30 to 27 nodes
Technical notes:
- no schema, route or op changes; the list keeps its query parameters modul, search, chng, status and num
- the stand's config/local.php has to be rebuilt after the CSS and JS change, as after every release
Steps 94 and 95 of the roadmap, batches 6 and 7 of the panel plan: the quick jump Ctrl+K and the rail of the etalon demo/admin moved into the theme admin, and the idle limit of the administrator session with a warning window that counts down, extends the session and leaves for the login at zero.
Core changes:
- Palette Ctrl+K (fragments/palette.html, layouts/admin.html, admin-ui.js, theme.css):
One palette on the shared setPaletteOpen(), printed next to "Опции"
- the group "Действия" folds the menu, sets the three colour modes, the motion and opens "Опции"
- "Разделы" are clones of a <template> row from the links of the menu or the cards of the home
- The home cards get their search; _EDITOR_NONE becomes the global _NONE_FOUND that both palettes read
- Rail (core/system.php, admin/index.php, layouts/admin.html, admin-ui.js, theme.css):
- The cookie rail goes through op option; isThemeFlag(key) replaces isThemeStill() and reads still and rail
- data-sl-rail stands in <html> from the first byte; the key [ folds and unfolds the menu
- The folded rail shows the menu and "Ждут внимания" as icons; the other blocks step out until batches 16 and 19
- Idle limit (config/security.php, core/security.php, admin/modules/security.php):
- The key idle (seconds, 3600) with a field in minutes on "Безопасность" and a hint of the limit in effect
- getAdminIdle() answers the lesser of idle and session.gc_maxlifetime, never under a minute
The time of the last action is $_SESSION[admin_c.'-time']; core/security.php drops an expired session on every request of the panel and the site, and renews it on every request of the panel without X-SL-Poll
- Both logins set the time: the panel (admin/index.php) and the light mode of an update (admin/update.php)
- End of session window (layouts/admin.html, admin/index.php, core/admin.php, admin-ui.js):
#sl-session on sl-modal sl-modal-sm sl-modal-warn opens two minutes before the limit and counts down
- "Продлить сессию" posts op keep to updateAdminSession(), which checks the token and answers 204
- "Выход" is the link op=logout; at zero the page leaves for the login with a GET of its own address
- The poll of the bell answers {left, rows}, so every tab follows the actions of the others
- Polls are no actions (admin-ui.js, public/plugins/system/slaed.js):
- The bell sends X-SL-Poll in its fetch
A request htmx fires by an every trigger without an event gets the header in htmx:configRequest
- the poll of "Мониторинг" and the live block "Пользователи" of the site no longer keep a session alive
- Language, tests and reference (admin/lang/.php, lang/.php, config/modules.php, tests/, tools/, docs/*):
_ADM_GOTO, _ADM_GOFIND, _ADM_PARTS, _ADM_ACTS, _ADM_FOLD, _ADM_UNFOLD, _ADM_END, _ADM_LEFT, _ADM_LOST, _ADM_KEEP, _SEC_IDLE and _SEC_IDLE_ON in the six panel locales, _NONE_FOUND in the six site locales
- The module master is registered in config/modules.php, inactive
- Every probe that fakes an administrator session sets its time as well
The audit baseline is stored; the answers of steps 6 and 7 stand in docs/12-ADMIN-UI-2026.md; steps 94 and 95 ticked in the roadmap
Benefits:
- A section, a theme mode or the menu fold is one key away on every screen of the panel
- An unattended panel closes itself after the idle limit and warns before work is lost
- A poll or a live block never holds a session open, whatever screen is left open
Technical notes:
- New config key security.idle and session key $conf['admin_c'].'-time'; new cookie $conf['user_c'].'-rail'
Breaking: a session opened before this version has no time and ends once; the JSON of getAdminQueueData is now an object {left, rows} instead of an array
- A template reads a {{ _CONST }} of at most 12 characters, hence the short _ADM_END … _ADM_KEEP
Step 93 of the roadmap, batch 5 of the panel plan: the window "Опции" of the etalon demo/admin stores every answer through one op option with a token and a 204, the page applies it at once, and the new row "Движение" stills the panel and the site from the first byte by a cookie the server reads.
Core changes:
- One op for the options (admin/index.php):
setAdminOption() checks the token of the scope option and stores the key mode, still or editor
- mode and still as cookies through setCookies(), the editor on the _admins row and in the session
- an unknown key or an unreadable session answers 400 and is logged as refused, a bad token 403
- The ops mode and changeeditor of the panel are gone with setAdminThemeMode() and updateAdminEditor()
- The language keeps its form with the op newlang and its redirect: the one row that reloads
- Motion from the first byte (core/system.php, core/security.php, five document templates):
- isThemeStill() reads the cookie still; the pages get is_still next to mode
data-sl-still stands in <html> of layouts/admin.html and bare.html of both themes and partials/site-header.html
- the switch of batch 1 (--sl-time-scale: 0) follows it in the panel and on the site, with no inline script
- Rows of the window (core/admin.php, fragments/settings-row.html, admin-ui.js):
getAdminSettingsRow() draws mode, motion, editor and language; each list is captioned by a label for its field
- no inline onchange and no aria-label carrying the current value; the theme row keeps the icon circle-half
A row marked data-sl-option applies data-theme or data-sl-still at once and posts the form with fetch silently
- a refused answer puts the row and the root attribute back to the value the server rendered
- Language and reference (lang/.php, admin/lang/.php, docs/*):
- _ON and _OFF in the six site locales, _ADM_MOTION in the six panel locales
- The answers of step 5 stand in docs/12-ADMIN-UI-2026.md; step 93 ticked in the roadmap
Benefits:
- No row of "Опции" but the language reloads the page; the theme and the motion change in place
- One op and one handler instead of three, each answering a status the page can act on
- The motion choice holds on every page without a flash, since the server writes it before the first paint
Technical notes:
- New cookie $conf['user_c'].'-still' with the value 1, one year, httponly like mode
- Breaking for scripts of the panel: admin.php?op=mode and op=changeeditor no longer exist; post op=option instead
Steps 91 and 92 of the roadmap, batches 3 and 4 of the panel plan: the menu of the etalon demo/admin with its filter and current section, the closed fan sl-dial as one stop of Tab in both themes, and one source of the queues of the panel that the bell, the block "Ждут внимания", the chips and the title of the tab read.
Core changes:
- Menu filter and current section (layouts/admin.html, admin/index.php, admin-ui.js, theme.css):
A find field sl-menu-find in the row sl-menu-top narrows the menu by name and module key; sl-menu-empty says so
- module screens only; the home gets its search in batch 6
- getAdminMenu() marks the open section with aria-current and carries the module key in data-sl-menu-item
- The open section takes the tint and the brand bar; the fan of a row and a card shows only on hover and focus
- Fan as one Tab stop (public/plugins/system/slaed.js, fragments/dial.html and share.html of both themes):
- The toggle carries aria-expanded; the items of a closed fan stay hidden until it opens
- Escape folds the fan and gives the focus back to its toggle; a fan folds once the focus leaves it
- Tab stops fell from 233 to 104 on the home and from 470 to 242 on "Комментарии"
- One source of the queues (core/system.php, core/admin.php, public/index.php):
getAdminQueues() answers key, mod, label, title, icon, href and num of every queue the administrator may open
- new users, comments for the super-administrator only, every Node type the administrator moderates
- the fullest first, counted once per request
- getAdminInfo() renders one block "Ждут внимания" from it in place of "Новые" and "Ждут проверки"
- getAdminCountRow() is gone; the op getAdminQueueData of go=5 answers the poll in JSON for every administrator
- Bell, chips and poll (fragments/bell.html, menu-list-item.html, menu-grid-item.html, admin-ui.js, theme.css):
- The bell stands in the header of every screen: the sum on its corner, the waiting rows in a tip sl-float
- The chip sl-queue sits on every section with a queue in the menu and on the cards; "Материалы" sums its types
A poll once a minute updates rows, order, chips and sum; a grown sum stirs the bell
- while the tab is not seen the title counts the arrivals as "(N)" and drops the count once it is
- Below 560 px the header items give up half their padding, so nine icons fit a phone
- Block tone by role (partials/block-sidebar.html, theme.css):
- sl-block-menu and sl-block-queue colour the heads of the column; the rules by sl-block-N are gone
- Language, tests and reference (admin/lang/.php, tests/Unit/, tools/, docs/):
- _ADM_FIND, _ADM_NOFIND, _ADM_BELL and _ADM_WAIT in the six panel locales
- CommentIsolationTest guards getTableCount() against the comment table; DeskKeysTest follows setDialState()
- The audit baseline is stored; docs/PERFORMANCE.md names the queue counts
- The answers of steps 3 and 4 stand in docs/12-ADMIN-UI-2026.md; steps 91 and 92 ticked in the roadmap
Benefits:
- One number for every place that shows a queue instead of two blocks built as HTML strings
- A keyboard walks the menu and the lists without passing every hidden fan item
- Block colours follow the role of a block, not its number or order
Technical notes:
- The comment queue is no longer shown to an administrator of modules, who cannot open that screen
- go=5 lets an administrator of modules reach the op getAdminQueueData only; every other op stays super-administrator
Steps 89 and 90 of the roadmap, batches 1 and 2 of the panel plan: the shared base in JS that the etalons need - one notice, one motion switch, the axis of the slide, the toggle storage and the palette controller - and the header of the panel moved from the etalon demo/admin into the theme.
Core changes:
- Notice with undo (public/plugins/system/slaed.js, fragments/toast.html of both themes):
setToast(text, opts) takes { warn, undo, time } and every call is moved onto it
- admin prints a flash alert with a countdown ring in sl-toast-host, lite a pill with sl-toast-undo
- _EDITOR_UNDO becomes the shared _UNDO in the six locales
- Motion switch (base.css of both themes, tools/ui-contract.php, tools/ui-audit.php):
--sl-time-scale multiplies every duration of the API block
- prefers-reduced-motion and :root[data-sl-still] set only --sl-time-scale: 0
- the component blocks of animation: none are gone; the audit no longer counts such root modes as scoped
- isMotionStill() reads the media and data-sl-still; setSlideMotion() gets its axis
- Shared helpers (slaed.js, editor.js, emoji.js, admin-ui.js):
- window.setPaletteOpen() is the one palette controller the editor calls
- window.getToggleState()/setToggleState() are open; the group fold and the recent emoji use them
- Header of the panel (layouts/admin.html, partials/dashboard-panel.html, fragments/link.html):
- The logo is a link sl-brand home to the panel without h1; the home carries one hidden h1
- The heads of the two home panels are buttons inside h2; a native button keeps its own keys in the toggle
- A skip link to #sl-main is the first stop of Tab; Options is an icon with its label
- Below 900 px the menu is a drawer behind a menu button: scrim, close button, Escape, the rest inert
- Tab title (core/system.php, core/helpers.php, admin/index.php):
- setFoot() names the section, an open tab other than the first, _ADMIN and the site, joined by defis
- getTplAdminTabs() records the section and the tab; setHead() keeps them when the tabs came first
- Theme, language and reference (theme.css, base.css, admin/lang/.php, docs/):
- --sl-layout-sidebar replaces the two literal sidebar widths; sl-visually-hidden is one rule in both themes
- _ADM_MENU and _ADM_SKIP in the six panel locales
- The answers of steps 1 and 2 stand in docs/12-ADMIN-UI-2026.md; steps 89 and 90 ticked in the roadmap
Benefits:
- One mechanism for notices, motion, storage and the palette instead of one per consumer
- One h1 per screen, a named browser tab and a usable panel on a phone
- The later batches of the plan build on the shared base instead of copying the etalon
Technical notes:
- No schema, route or API change; the ui-audit baseline is stored again
- Remembered emoji and group folds are reset once, their storage keys changed
- The tab title order changes from "Site - Administrator" to "Section - Administrator - Site"
Roadmap step 88 is batch 0 of docs/12-ADMIN-UI-2026.md: the owner answered the nineteen open questions, the panel lists are inventoried for the list canon and the baseline is taken. Taking it showed the label crawl had walked the site blind since the readable addresses of 2026-10-14; it reads paths again, the five unnamed hints it reported are tied to their controls, and its baseline is rebuilt green.
Core changes:
- Plan of the panel (docs/12-ADMIN-UI-2026.md):
"Ответы шага 0": the nineteen answers under their numbers
- the window "Наблюдение" shows only the present of _session, no graph, no history, no cache
- the session limit of the administrator is done now on the PHP session, a key in config/security.php
- every site sound with an event ships, the private messages by a poll; no zone for mentions
- undo by a deferred send, "all N" in portions from the browser, the prefix ADM, motion by tokens
"Инвентарь списков": 35 list screens with their op, kind of delete, mass actions, pager and filter; group A of 16 for batch 12, group B of 17 for batch 13; the file manager stays outside the canon; the defects found on the way
"Базовая линия": ui-audit counts, the label crawl, 264 shots, axe on the home, "Комментарии" and "Конфигурации", the response times under a session (home 338 ms, the measure of batch 14)
- Batches 7, 12, 13, 17, 21 and 23 follow the answers; the status line names batch 1 next
- Label crawl (tools/label-audit.mjs, tests/Support/address_probe.php, tools/label-audit-baseline.json):
getRouteSig() read the route only from name= and op=, so every readable path read as the home page and the site side walked 15 routes
The probe answers every new path by Route::isRouteReserved() (an operation, still under the allowlist of ops) or Route::getRoute() (a record, view#rec; a category or forum section is the list of its prefix); a path that is neither is skipped
The baseline is rebuilt from a clean run: 442 routes, no violation; the routes of the deleted types jokes and media left it, account:view became users:view#rec
Hints tied to their controls (admin/modules/update.php, public/templates/admin/partials/group-form.html, public/templates/admin/fragments/code-block.html, public/templates/lite/fragments/code-block.html):
The code blocks of the site id and the rescue code, the radio groups of the update settings and the colour of the group form carry a hint id and an aria-describedby
- code-block takes an optional describedby in both themes
- Shared login and axe (tools/ui-probe.mjs, tools/ui-shots.mjs, tools/browser-audit.mjs, package.json):
- setSession() lives once in ui-probe.mjs; the screenshot rig, the label crawl and the browser audit call it
- browser-audit.mjs gains --as admin|site and --axe (axe-core 4.14.0, WCAG 2.2 AA, a devDependency)
- Screenshot manifest (tools/ui-shots.json):
- node-view opens a live docs material instead of one that answers 404; node-media of the deleted type media leaves
- Stand (public/demo/admin/index.html, public/demo/assets/demo.js):
- The mark Э30 and its line of the legend leave: the live panel already gives the tab
Roadmap, ideas and reference (docs/ROADMAP-2026.md, docs/2027-IDEAS.md, docs/2027-CORE.md, docs/TESTS.md, docs/TEMPLATES.md):
- Step 88 closed; ideas 9 (history of online visitors) and 10 (mentions and replies to me with their sound)
- 2027-CORE question 2 links the session limit of the panel plan
- TESTS.md: the flags --as and --axe; TEMPLATES.md: how the crawl reads readable paths
Benefits:
- The label gate covers the lite theme again before the panel plan puts the menu and the block on the site
- Every later batch is measured against one recorded baseline
- One login for every browser tool
Technical notes:
- The probe reads the stand database and writes nothing
The full phpunit run has three failures that fail on the clean HEAD as well: AssetVersionTest (presentation.css), RouteRegistryTest::twoWritersRaceForOnePath and PhpFileFormatTest (tools/ui-contract.php)
- No schema, URL or API changes
The etalons demo/admin/ and demo/site/ are checked code by code against the live panel, the lite site and every rule, and the transfer into the themes admin and lite becomes the plan docs/12-ADMIN-UI-2026.md: 24 batches, steps 88-111 of the roadmap, its batch 0 the nineteen open questions. The former step 88 DIAL is one of its batches.
Core changes:
- Plan of the panel (docs/12-ADMIN-UI-2026.md):
Decisions of the owner, 2026-10-19: docs/2027-ADMIN-UX.md stays its own plan; one canon of the list and the form in the theme and the shared helpers, "Комментарии" and "Конфигурации" first, the other panel lists in two batches; DIAL folded in; sounds as files in sound/ of each theme, the engine in public/plugins/system, public/sound/ retired
Nineteen open questions, each with a proposal: the state of the shell in cookies the server writes into <html>, the undo by a deferred send, the session lifetime, the monitor functions into core/monitor.php, the prefix of the shell constants, the motion switch beside prefers-reduced-motion, the module administrator, axe-core
- Findings of the check, verified in code: soft delete without restore, the award of a first publication kept,
go=5 only for the super administrator, no single source of the queues, admin-block.css off the contract
Design: rules of the transfer, a consolidation table (one notice, one palette, one motion switch, one queue source, getThemeFileUrl()), the list and form canon, sound and the screensaver
- 24 batches; every one of the 126 codes of both legends is named by a batch, the stale mark Э30 leaves the stand
- Roadmap (docs/ROADMAP-2026.md):
- The plan joins the table; step 88 DIAL becomes steps 88-111 of the plan, Close becomes 112
- Admin UX 2027 (docs/2027-ADMIN-UX.md):
- A line "Связь": its draft steps 2 and 6 and part of 3 are done by the new plan, the rest stays here
- The note on sl-dial points at batch 3 of the new plan
Benefits:
- One file names what moves from the stand, in which batch and on which existing mechanism
- The decisions the transfer needs are asked once, before any code
Technical notes:
- Documentation only; no code, template or schema changes
The block "Администрация" (adminblock(), bkey admin) and its twin "Наблюдение" are redesigned on the demo stand: the series demo/ab-01…09 carries the variants, and the owner's choice - the floating menu 09 and the merged block 08 - stands in the panel etalon demo/admin/ and in the new site etalon demo/site/, with marks, descriptions and one shared stylesheet, so the transfer into the themes is one step. On the live site the total of the visitor summary gets its own icon.
Core changes:
Admin block series (public/demo/ab-01-card.html … ab-09-menu.html, public/demo/assets/ablock.js, public/demo/assets/ablock.css, public/demo/assets/demo.js, public/demo/README.md):
Nine faces, each in two rooms: ?ctx=admin on the admin theme with the block form, ?ctx=site on the lite theme
- ablock.js holds the corpus of the stand: block id 2 word for word, the queue, the sessions, the live tick,
the summary, the window "Наблюдение" and the stand desk
01-08 merge "Администрация" and "Наблюдение" into one block; 08 "Пульт" is the leader: the summary, six square icon keys (panel, statistics, refresh, site, own links, logout), the own links open as the rows of the user block
09 "Плавающее меню" is the leader of the menu: a solid layer over the page, placed anywhere and remembered, turned across or upright, folded with the slide of the column blocks, only the icon under the hand grows
- demo.js lists the series (DEMO_ABLOCK); README.md records the series, its history and the rejected ideas
- Panel etalon (public/demo/admin/index.html, public/demo/admin/admin.js, public/demo/admin/admin.css):
М1-М14: the floating menu with its pins from the fan of a section, the quick jump, the watch ring, the own links, the admin window, the turn, the fold and the grip; Options get "Плавающее меню", "Меню на сайте" and "Позиция меню" (top, right, bottom, left; a place set by the grip reads "Произвольная")
- А1-А8: block 08 on the home, always, whatever the menu; the rail shows it beside its icon, opening upward
- The window "Наблюдение" (#sl-stats): filter by kind, pause, figures, the hour, shares, who and where, pages, countries
Fixes found on the stand: the grip cancelled by the page's own drag (preventDefault, pointercancel), the growth measured from the wrong parent (the hovered icon now grows), the toast lifted only over a menu lying at the bottom
Five own links: Sypex Dumper (dead, flagged), SLAED CMS on GitHub, PageSpeed Insights, Google Search Console, Яндекс Вебмастер; each row ends with the chevron of the site's user block
- Labels in plain words; the legend gets the sections М and А and rewrites Г5, Э13, Н4, Н5, В09.3
- Site etalon (public/demo/site/index.html, public/demo/site/site.js, public/demo/site/site.css):
The server answer of the live news page under an administrator: the real lite chrome, without htmx, the pseudo-cron, the debug panel and the form tokens; the stand posts nothing and calls no server
Block 08 first in the column, always; menu 09 with what the site needs of its own: the mark into the panel with the queue sum when folded, "Эта страница в панели", the queue (four apps, one bell upright), "Все разделы" with search and stars instead of Ctrl+K, the setToast pill with "Отменить"
The panel's Options act here at once (shared keys sl.dock.side, sl.dock.pins, sl.dock.mag; sl.dock.site switches the site); the place dragged on the site is the site's own
- Marks С1-С14 with their descriptions and the stand desk of the site
- Shared stylesheet (public/demo/assets/admin-block.css):
The menu, the block and the window move out of admin.css into one file both etalons link; admin.css keeps only the lift over its toast host and the rail rule, site.css only what the site adds
Visitor summary of the site (public/templates/lite/partials/session-summary.html, public/templates/lite/assets/css/theme.css, tools/ui-contract.php):
- The total line carries bi-people in the text tone and stands in the column of the lines above it
- Its rule body now equals the two changelog rules; the dup allowlist entry names it with the reason
- Scheduler (config/scheduler.php):
- The update check runs at 24 0 instead of 40 4
Benefits:
- The owner judges the menu and the block where they will live, in the panel and on the site, before any transfer
- One markup and one stylesheet for the menu, the block and the window on both themes
- The live block's faults (list markers, the empty ring, the dead link, the wrong tooltip) are shown and repaired
Technical notes:
Storage of the stand only: sl.dock, sl.dock.site, sl.dock.side, sl.dock.at, sl.dock.dir, sl.dock.fold, sl.dock.mag, sl.dock.pins, sl.dock.site.at, sl.dock.site.dir, sl.dock.site.fold
For the transfer: setToast() of slaed.js gains an undo action, the lite theme gains the token --sl-solid-text, setSlideMotion() gains an axis option
- No breaking change: the only change to a shipped template is the added icon of the summary total
Roadmap step 87 finishes batch 11 of the update plan: the factory keys of the core are the keys of the owner's ceremony, README.md publishes their fingerprints, and docs/11-UPDATE-2026.md is deleted with its lasting part in docs/UPDATE.md. On the owner's word the release archive leaves out every file a site does not run, the modules changelog and master of slaed.net included, so the core no longer names either; the GitHub release goes to the repository the sites link to. The help of the client and the master covers keys, versions and releases.
Core changes:
- Factory keys (core/classes/update.php, README.md, docs/ROADMAP-2026.md, docs/11-UPDATE-2026.md):
- Update::PRIMARY and Update::RECOVERY are the public keys of the ceremony; README.md carries both fingerprints
- docs/11-UPDATE-2026.md is deleted, roadmap step 87 is closed
- Release archive (.gitattributes, tools/release.php):
export-ignore: tests/, tools/, docs/, public/demo/, public/phoenix/, public/sound/, modules/changelog with its templates in admin and lite, composer.json and the other files of development and documents of the root
- the root keeps LICENSE, .htaccess and nginx.conf.example; uploads/presentation/ and storage/geoip/ ship
setArchiveModules() cuts from config/modules.php of the archive the row of every module whose folder the tag holds and the archive lacks; the result must return the same array without those keys, or the build stops
- the stand keeps its rows; files.json hashes the cut file, and the delta takes it from the full archive
- Publishing (tools/release.php):
getReleaseRepo() reads the repository from Update::PAGE; checkReleaseRepo() refuses while origin points elsewhere, and every gh call names that repository with --repo
getReleaseNotes(): which archive installs and which updates, their SHA-256, that the "Source code" archives of GitHub are sources only, and the link to docs/VERSIONS.md of the tag
- The address of origin is never printed, and an error of git has the userinfo of any address masked
- Scheduler jobs of a module (core/system.php, modules/master/scheduler.php, modules/master/admin/index.php):
modules/<name>/scheduler.php declares its jobs with their row defaults and a closure under run; getSchedulerModuleJobs() collects them, addSchedulerModuleJob() runs one while its module is active
- masterclean and masterwatch moved there; addMasterTask() and both names left the core
- Saving the settings of the master writes the rows from that declaration
Names of modules (core/system.php, core/helpers.php, admin/index.php, admin/modules/modules.php, admin/modules/security.php, lang/.php, modules/changelog/lang, modules/master/*lang):
getModuleLabel(): the constant a row names, read from the language of the module for this context when the common language lacks it
- _CHANGELOG and _MASTER moved from lang/*.php into the site and panel languages of their modules
The menus, the list of modules, the journal filter and the tabs header use it; getModuleName() answers the name of a site module its map lacks, node included
- Presentation (modules/presentation/index.php, modules/presentation/lang/*.php):
- The commits of the changelog are read only while modules/changelog/ exists, with its language loaded first
- Its own label _PRES_DV_LOG and the icon concept commits in getIconName()
- Light mode (admin/update.php):
After the database steps it clears config/local.php, the caches of pages and assets and OPcache, as step 7 of an installation does
Tests (tests/Unit/ReleaseToolTest.php, tests/Unit/MasterTest.php, tests/Unit/UpdateGateTest.php, tests/Support/route_probe.php):
ReleaseToolTest: the archive lacks the excluded files and the row of a left-out module, keeps a panel module, files.json holds the cut hash; publish refuses without origin and with origin on another repository and prints no address
- MasterTest: the core names no job of the master; the jobs run through the hook
- UpdateGateTest: the light mode leaves no configuration or page of the old code cached
Reference and help (docs/UPDATE.md, docs/VERSIONS.md, docs/ARCHITECTURE.md, docs/2027-CORE.md, README.md, UPGRADING.md, admin/info/update/ru.md, modules/master/admin/info/ru.md):
- docs/UPDATE.md: what the archive leaves out, the GitHub release, the jobs of a module, the light mode cache
The help of the master: what the owner's machine needs, preparing a version, build options, signing, publishing, the red rehearsal, creating, storing and changing both keys, the privacy note, what slaed.net takes by SFTP
The help of the client: the manual path with the archive source, the panel entry, setup.php, robots.txt, files a release deleted, and the caches cleared after the steps
- docs/ARCHITECTURE.md: names and scheduler jobs at the module boundary; docs/2027-CORE.md item 4 records the hook
- Ideas (docs/2027-IDEAS.md):
The section "PHP 8.4": small means of 8.2-8.4, enums for closed number sets, property hooks, lazy objects and the new DOM, the analyser before the hints
Benefits:
- No release can be signed with a key anyone else holds, and no site receives code it does not run
- A module of slaed.net needs nothing in the core: its folder, its languages and its scheduler.php
- The GitHub release and the links of the sites point to the same repository
Technical notes:
Breaking: _CHANGELOG and _MASTER are no longer in lang/*.php; addMasterTask() is gone; getModuleName() answers the name of a site module outside its map instead of its key
- publish needs origin on github.com/SLAED-CMS/SLAED, which does not exist yet; until then it refuses
- config/scheduler.php stays out of this commit: its minute of updatecheck is the stand's own
- No schema or URL changes