Skip to content

v0.5.0

Choose a tag to compare

@Mrshahidali420 Mrshahidali420 released this 22 Aug 15:11
· 184 commits to 95fa9e9b8e3f0ae8921b734fdd516816657bd7ae since this release

[0.5.0] — 2026-08-22

Added

  • A switch on every Modules card that turns the whole module's operations on or off
    together — the same switches the Operations screen shows one row at a time, stored in
    the same option, so a module half-switched off there reads "N of M operations on" here.

  • Per-operation switches on the Operations screen. Every operation now has an
    on/off switch, with per-group counts, "All on" / "All off" per tool, and a sticky
    save bar. A switched-off operation leaves the catalogue, is refused with the
    same answer an unknown operation gets, and system-operation-schema will not
    describe it either; everything is on by default, including
    operations a later update adds. Stored in sitehelm_disabled_operations.

  • A one-time notice after activation pointing at the Connect screen, shown to the
    first operator who can open the console and then gone.

  • A Site Health test under Tools → Site Health that says whether client
    credentials reach WordPress on this server, with the .htaccess fix when they do not
    and a warning when application passwords are switched off.

  • Connect and Status links on the Plugins screen, beside Deactivate, for the
    moment after activation.

  • Filter the Activity log by period. Last hour, 24 hours, 7 days or 30 days,
    alongside the other filters; the period travels with the pager and the CSV export.

  • The Status screen now tests whether the Authorization header reaches WordPress.
    A loopback to the endpoint with a login that cannot exist tells a server that passes
    the header through from one that strips it (Apache as CGI/FastCGI), which is the
    commonest reason a fresh credential is "wrong"; when it is stripped the screen gives
    the three .htaccess lines that fix it.

  • Export the Activity log as CSV. The Activity screen's filter row now ends in
    an Export CSV link that downloads every row matching the filters shown, newest
    first, up to 10,000 rows (the file says so on its last line when it stops there).
    Cells that a spreadsheet would read as formulas are neutralised.

  • Set how long records are kept, on the Status screen. The pruning window
    (1–365 days, default 30) that governs the activity log and the snapshots behind
    each rollback was previously only reachable by editing an option; it is now one
    number and a Save button under "Record retention".

  • A SiteHelm widget on the wp-admin Dashboard. Whether writes are paused,
    how many credentials are issued, and the five most recent operations with their
    client and outcome — each linked to the console screen that explains it. It shows
    nothing to anyone who cannot open the console, and offers no controls.

  • Filter the Activity screen by client. A "Filter by client" field joins the
    operation, correlation and outcome filters, and every named client in the actor
    column is now a link to everything that client did on the site.

  • See and revoke issued credentials on the Connect screen. A new "Issued
    credentials" section lists every application password SiteHelm has created for
    the accounts you can act for — which account it acts as, when it was created,
    when it was last used — each with a Revoke button. Revoking cuts that client
    off at WordPress sign-in; nothing already recorded is touched. Only
    SiteHelm-named passwords are listed or revocable, and the handler enforces the
    same account boundary as minting.

  • Pause all writes from the Status screen. A "Write access" section shows whether
    connected clients may change anything, with one button: "Pause all writes" puts
    the gateway in read-only mode so every write from every client is refused at the
    gate before any module runs; "Resume writes" lets them through again. Reads keep
    working either way, nothing already recorded is touched, and resuming never
    rewrites a mode the operator set some other way.

  • Roll a change back from the Activity screen. Every applied row now carries a
    "Roll back" button beside its reference. The first click asks the change engine
    for a preview and shows a confirm panel — target, reference, a field-by-field
    Now / After rollback table, and any warnings — with nothing changed yet; "Roll
    back now" restores exactly what was shown, and the result is reported at the top
    of the screen in the engine's own words when it refuses. The restoration runs
    through the same dispatcher, capability checks, audit record and verification as
    a client-requested rollback, is recorded against the client wp-admin, and is
    itself re-restorable. The plan token never reaches the browser; it sits in a
    five-minute, per-user transient and is spent on the second click only.

Changed

  • The console now says what a blocked module is waiting on, and which operations
    that blocks.
    A Modules card that is not active names the plugin and the lowest
    version SiteHelm accepts ("Activate Elementor 3.0.0 or newer", "Update to Advanced
    Custom Fields 5.9.0 or newer") and links to Plugins; a module backed by WordPress
    itself points at Status instead. Every Operations row names its module, and a row
    the site cannot run yet is dimmed, marked "Not active", and counted in the verdict
    — the catalogue stays complete, so an operator sees which rows are promises. The
    Status verdict's "N modules are not active" now links to the screen that explains
    why. The version floors are read from the same constants the gateway enforces, so
    the two cannot drift.

Fixed

  • Every string a request can carry now has an upper bound too. Ninety-four of
    the catalog's string arguments already declared a maximum length; five did not,
    including the redirect target, whose limit the handler was already enforcing
    without ever publishing it. All five are now declared, from what the storage can
    actually hold rather than from a round number. With lists, maps and strings all
    bounded, no argument the gateway accepts is unbounded in size.

  • Every map a request can carry now has an upper bound too. Six operations
    accept a free-form object whose keys are the site's own vocabulary — a widget's
    settings, a block's attributes, a typography entry — and none of them said how
    many members one request could carry. Elementor's known-key check is not that
    bound: it refuses names a widget does not declare, and it does not run at all
    when the widget type is unknown. maxProperties is now both applied by the
    validator and declared on all six, two of them from limits their handlers were
    already enforcing without publishing. An over-large object is refused whole.

  • Every list a request can carry now has an upper bound. Eight arrays across
    content-block-update, content-meta-update, content-terms-assign,
    elementor-theme-conditions-set, menu-item-create, menu-item-update and
    menu-items-reorder accepted a list of any length, so their size was discovered
    by running out of time or memory rather than by being refused. One of them —
    the term identifiers inside content-terms-assign — sat one level down, inside
    an entry of another list. elementor-theme-conditions-set already enforced its
    limit in the handler and simply never published it; the schema now names the same
    constant. A new registry-wide test sweeps every input schema recursively and
    fails on the first array that declares no bound.

  • Five constraints the operation schemas declared are now actually applied. The
    gateway validator applied type, enum, minimum, maxLength and the structural
    keywords, and silently ignored minLength, maximum, pattern, minItems and
    maxItems — 44 declarations across 22 files. A published schema is what an agent
    reads to learn what a site accepts, so a declared bound that is never checked is
    worse than an absent one: a well-behaved client stops checking for itself.
    maxItems was the only declared upper bound on array size anywhere in the catalog,
    so every batch operation accepted a list of any length and discovered the size only
    while walking it; an over-long array is now refused whole, before the walk. A new
    registry-wide test fails on the next keyword written into a schema that the
    validator does not apply.

  • A part-completed taxonomy assignment now says which taxonomies were already
    written.
    content-terms-assign writes one taxonomy at a time, but a failure
    reported the same two completed steps whichever write it happened on — so an
    operator whose second taxonomy failed was told that nothing had changed, when the
    first had already been applied. The rollback record was always complete; only the
    account of it was not.

  • A menu name too long to belong to any menu is now refused before the lookup.
    The four operations that take a menu argument — menu-get, menu-item-create,
    menu-items-reorder, menu-location-assign — accepted a string of any length. A menu
    is a nav_menu term, and all three ways to name one resolve against columns bounded at
    200 characters, so a longer string could never have matched one. It is now rejected by
    the argument schema, which says the bound, instead of by a not-found result after the
    search.

  • Importing from a URL now stops downloading at the size this site will actually
    accept.
    The transfer was bounded by the plugin's built-in 8 MiB ceiling on every
    site, so a site configured to accept 2 MiB still pulled up to 8 MiB across the
    network and held it in memory before refusing it for size — four times the transfer
    and four times the peak memory for a refusal that was never in doubt. Both the wire
    limit and the check after it now use the effective cap, the smaller of the built-in
    ceiling and the site's own upload limit. A site reporting no positive limit still
    falls back to the built-in ceiling rather than to zero.

  • Refusals on the import path no longer say "uploaded". Six messages shared by
    media-upload and media-import described content that was fetched from a URL as
    though the caller had uploaded it, which reads as a refusal of some other request.

  • The import operation states the punycode requirement up front. An
    internationalised domain name must be supplied already in its xn-- form — the
    address is never converted, because the name checked and the name dialled would then
    be two different strings. That was learnable only from a refusal; it is now in the
    url field's own description.