Private release previewNo live purchasesRelease details ↗

EN · ORIGINAL REPOSITORY DOCUMENT

Release readiness

Original English text. Commands and evidence apply to the revision and environment stated in the document.

RELEASE-READINESS.md

On this page

Current candidate status: 1.26.0-rc.1

Production acceptance is pending. Use the implementation inventory and the release completion record for current evidence. Earlier successful checks below apply only to their recorded source revisions.

The owner requested development first and tests together at the end. Earlier PHP regression and real WordPress/standalone Redis runs did complete, as recorded in the inventory. Later features and refactors have not completed final acceptance. The local WordPress fixture starts with the current plugin/drop-in and answers HTTP requests, but startup and a successful Redis health check do not establish concurrency, commerce, Relay, topology, browser or performance acceptance.

A distributable ZIP must identify the exact accepted commit and match its runtime and drop-in bytes. Packaging does not itself approve a release. Five-repeat performance comparisons and staging/pilot/multisite rollout with fresh-prefix rollback remain required. See installation and the migration procedure.

Historical evidence (prior revisions only)

Private candidate release gates

The owner confirmed on October 2, 2026 that upstream reuse rights were checked and cleared, and authorized product-facing consistency edits. This records the owner’s confirmation; no independent legal opinion or new upstream license grant is claimed. Inherited files remain proprietary; concise project headers refer to the original notice preserved in THIRD_PARTY_NOTICES.md. New standalone FREE files carry their own GPL-2.0-or-later license. The referenced upstream LICENSE file is still absent from this checkout. No public deployment or directory submission is authorized. Remaining readiness gates are technical, operational and publication review.

Bounded software gap closure after 470ad49

Four reproduced software defects were corrected without changing public APIs, backends, namespaces, product headers or the negative-cache default:

Trigger / prior behavior Correction Evidence
Bulk ADD with split alloptions claimed success but wrote an ignored scalar key Delegate only that entry to the existing single-ADD hash path; preserve independently successful results if the ordinary pipeline fails Public regression fails before and passes after; 40 real Redis checks with splitting and negative cache OFF/ON, false/null/NX, cold/warm/fresh-instance reads
Sentinel discovers zero replicas: ordinary commands work but scans/listKeys crash on the empty pool Iterator reads fall back to primary only for empty Sentinel pools; nonempty first-node selection, iterator references and retry policy stay unchanged 26 mocked PhpRedis/Relay inheritance checks; 19 actual primary-only Sentinel checks across all scan types and incremental group flush isolation
Metadata cache reset resolves an empty path to the working directory and parses it as a plugin file Only regular files reach the metadata reader Baseline regression fails; 14 file/cache contracts pass, plus real WordPress reset and upgrade-event checks without the previous directory-read notice
A peer closes a declared-length HTTP response early, leaving valid JSON that was still accepted Reject any received-body length mismatch before returning JSON or ZIP Baseline real-loopback regression fails; eight real framing scenarios and 27 existing transport configuration/limit checks pass

The suspected mixed-invalid-key reply mapping defect was not reachable through the public API: existing filters remove invalid IDs before dispatch. A new public contract regression records that result; no speculative helper-only patch was made. Current set_multiple() already handles split alloptions and was preserved. Cold single-ADD hash merging and the ordinary cache APIs were not redesigned.

The focused Cloud fixture used WordPress 6.8.3, PHP 8.3.28, PhpRedis 6.1.0 and Redis 7.4.2. Ten affected regression scripts and the existing transport test passed. The primary-only probe initially used a plain MATCH prefix for serialized set members and checked Docker’s asynchronous --rm too early. Those test fixtures were corrected; only that probe was repeated. Previously passing checks were retained against identical runtime bytes. Both attempts, owned-key deletion, owned-container/project cleanup, exact source commit and installed immutable ZIP are recorded in build/software-gap-report.json and the initial/probe reports. WordPress emitted known upstream network warnings during ZIP installation; the metadata reset/upgrade commands themselves were warning-free. The regular fixture runner now includes the bulk-ADD check and adds the primary-only probe under --topologies.

A final installer is compared byte-for-byte against the ZIP installed in this fixture. Older core/portal/licensing reports remain historical evidence at their recorded commits; this round does not claim a rerun of the complete unit, WooCommerce, Cluster/failover, browser, HTTPS or durability suites. The independent review found no additional concrete regression. Broader runtime/Relay coverage, external production inputs and hosted CI access remain unchanged. No performance claim or public deployment follows from this bounded closure.

Current completion inventory (October 3)

The subsequent source-header cleanup replaces the shared 12-line upstream boilerplate in 122 PHP files with a concise six-line Object Cache Project header. The original notice is retained verbatim in THIRD_PARTY_NOTICES.md, included in the paid installer, with provenance updated and dependency notices untouched. PHP 8.3.28 syntax checks and executable-token parity passed for all 122 files. The byte-identical runtime ZIP claims in the core checkpoint below refer to its 44bdaa6 artifact; this later header cleanup changes comments and notice files, not executable PHP tokens. No cache, namespace, API or license terms are changed.

The checkpoint sections below retain earlier evidence; they are not all claims about the final cache runtime. The actual core refactoring checkpoint separates storage transport from runtime policy, centralizes runtime miss lifetimes, shares counter mutation/TTL fallback, shares replicated routing, and shares connection result/error observation. It preserves the existing architecture and public API. The previous SET option extraction remains separate from these completed changes.

Five runtime files changed. Their responsibilities are now explicit:

Work Before After / preserving contract
Storage reads get() mixed WordPress runtime policy and three transport paths readFromStore() owns alloptions/metadata/atomic fallback; get() retains found, metrics, prefetch, clone and error policy
Runtime misses Direct miss mutations across reads, writes, counters, deletes and flushes Three lifecycle helpers own forgetting, genuine-miss recording and group/global reset; errors remain uncached and default is OFF
Counters incr() and decr() repeated storage/error/TTL logic mutateCounter() preserves virtual arithmetic overrides, KEEPTTL/syntax fallback, missing/stored-false and failed-SET result/runtime behavior
Replica/Sentinel routing Duplicated readonly/alloptions selection commandNode() owns selection; Sentinel empty-pool fallback and one-retry rediscovery remain distinct
Command observations Single and batch duplicated successful metrics/logging and error wrapping Base completion/error helpers share publication; timing, native discard, exec-shape validation and success-only queue clearing stay at execution sites

Four new public-contract regressions passed against immutable 4754c34 and the refactored source with identical results: read/runtime lifetimes, 78 counter, 69 routing and 387 observation checks. All 77 existing method signatures in the five files remain unchanged. All 23 PHP regression files plus the legacy Sentinel case passed on PHP 8.3.28 without warning output. These scripts implement the unit suite’s checks; the PHPUnit runner itself was not rerun because its vendor tree is absent in this saved Cloud environment.

Fresh real WordPress/Redis checks passed core cache/multisite contracts, negative cache OFF/ON, WRONGTYPE/error recovery, SET options and 116 counter checks. Cluster passed 6/6 scenarios across three masters. Sentinel passed 6/6 actual failover scenarios, testing single-first, bulk-first and bulk-only writes with negative caching OFF/ON. Both probes removed their owned containers; the fixture project containers/network/volumes were removed and the existing Cloud loopback preview was preserved. The immutable 16e4929 installer was actually installed/upgraded, its drop-in bootstrapped and stored false verified. Drop-in lifecycle passed eight assertions, six upgrade scenarios and fresh-process deactivation/reactivation. The final ZIP runtime is compared byte-for-byte with this tested installer; documentation-only changes do not turn earlier unrelated 180-check licensing evidence into a fresh full-runtime result. All initial/follow-up attempts and fixture cleanup remain in build/core-refactor-initial-report.json and build/core-refactor-final-report.json.

The counter fixture initially exceeded the existing 32-character prefix limit; only its generated prefix was corrected. Already passing checks were retained against identical runtime bytes rather than repeated. WordPress emitted network warnings while querying WordPress.org during ZIP installation, and upgrade-event fixtures emitted directory-read notices; all affected commands exited successfully. The regression scripts above were warning-free. WooCommerce remains explicitly skipped: October 3 host checks returned curl exit 56, CONNECT HTTP403 from envoy for downloads.wordpress.org and pecl.php.net. Cached images supplied the fixture; no new pull/quota success or provider network change is claimed.

This is maintainability work with behavior-parity evidence; no speed or production throughput improvement is claimed. PHP 7.2 syntax compatibility is retained, but that runtime and licensed Relay execution have not been tested here. The exact source commit, commands, topology outcomes, installed ZIP manifest and cleanup are recorded with the candidate artifacts.

Current external limits remain explicit: production host/DNS/TLS/private keys, operator verification and delivery, payment-provider/public-account setup, broader runtime/workload testing and hosted CI access. These are not completed software features or simulated approvals. The durable local portal, manual fulfillment, FREE engine, paid updater and existing public APIs remain available.

Scope of this candidate

The existing architecture, API, namespace and negative-cache default remain in place. Focused corrections preserve cached null in bulk reads and runtime presence checks. Earlier stored-false, forced-miss and Sentinel bulk recovery fixes remain in place. The optional negative cache defaults to off.

The SET option refactor keeps write() and multiwrite() responsible for TTL policy, invalidation, dispatch and results, and assigns option construction to writeOptions(). Bulk writes build the same native options once per batch. No public API, backend, support path or feature is removed. Exact argument parity covers omitted options, NX/XX, EX, TTL caps, false/null and failure recovery; real Redis checks cover the changed write paths. Five bounded PHP stub runs measured median 34.930 ms before and 29.455 ms after for one allocation scenario. The committed measurement includes the noisy outlier and methodology; it does not establish production throughput or comparative product performance.

Differentiation is currently concrete behavior and engineering evidence: optional request-local miss caching with explicit visibility semantics, stored-false/null contract tests, repeatable failure/recovery probes, isolated fixture ownership, cross-process lifecycle tests, and reproducible private packages. No performance advantage or upstream product-ownership claim follows from these changes.

Bounded remaining work

Before claiming broader readiness, run the full WooCommerce fixture, unit suite, browser checks, and supported PHP/PhpRedis matrix. Relay, TLS integration, network partitions, replica-lag behavior, purchase/session concurrency and production load are not established by the bounded topology tests. Preserve the current contracts while extending these tests. Do not replace the architecture or introduce broad refactoring without an observed problem and regression test.

The owner-confirmed reuse authorization is recorded in provenance. The independent FREE core has a separate implementation and license. Product display names preserve original attribution and compatibility identifiers.

Package and recovery

python3 tests/integration/package.py --ref <commit> generates a deterministic runtime ZIP and a per-file SHA-256 manifest from that exact commit. Its runtime autoloading uses bootstrap.php and does not require Composer’s development vendor tree. Keep the manifest with the candidate; validate the ZIP in a new disposable WordPress fixture before any installation decision. Do not install on a live site during this task. A rollback must restore the prior plugin and drop-in together and configure an unused prefix before that code starts. Never reuse the pre-v2 namespace; follow MIGRATION-v2.md and rehearse on staging.

Evidence boundaries

Cloud validation on October 2, 2026 used an isolated minimal WordPress multisite fixture: WordPress 6.8.3, PHP 8.3.28, PhpRedis 6.1.0 and Redis 7.4.2. All 15 PHP regression files and the legacy Sentinel TLS argument case passed. Real Redis negative-cache and injected-error recovery passed. WordPress core contracts, including stored null and multisite isolation, passed with WooCommerce explicitly skipped. Drop-in lifecycle passed eight checks, six simulated upgrade scenarios, and fresh-process network deactivation/reactivation with stored-false verification. Cluster passed six scenarios across three masters, including stored null; Sentinel passed six real failover scenarios with one primary, one replica and three Sentinels. This does not replace the full WooCommerce runner.

The default fixture build failed resolving deb.debian.org inside Docker. Host requests to WordPress.org and PECL were denied with HTTP 403; Docker Hub image pulls succeeded without a quota error. An alternative test image used the official WordPress image and the pinned PhpRedis GitHub source, compiled with Docker build networking disabled. No provider network settings were changed.

Original commercial prototypes

product/site/ contains an original private website concept, configurable brand and illustrative plans, a mock purchase dialog, and an object-cache comparison matrix linked to official competitor documentation. Unknown capabilities are explicit, and no comparative performance advantage is claimed.

product/licensing/ contains an original loopback-only Python/SQLite server and standalone PHP client. Fifteen server tests cover approved origins, installation ownership, transactional limits, expiry/revocation, RSA-signed entitlements and protected delivery of an original fixture ZIP. PHP checks cover signature/binding, fixed cached grace, signed denial, key IDs, rollback high-water handling, concurrent writer races and storage failures. The explicit HTTPS transport has 27 focused validation checks; ten isolated real HTTP scenarios verify Python/PHP signatures, package SHA-256, ownership, actual service outage/grace and revoked downloads. Ephemeral fixture keys and packages are removed. No cache hot-path calls are added. The server rechecks entitlement when serving package bytes; an offline client cannot force a revoked download to succeed. No upstream package is configured.

Payment processing, authenticated customer/operator administration, automatic domain ownership proof, installation/key recovery, WordPress administrative hooks, production TLS operation and deployment remain gates. The site operator workspace is explicitly a local in-memory demo, not an account system or a live service. The licensing component does not grant rights to the upstream plugin.

Recording and publishing decisions

Machine-readable test reports belong under tests/integration/results/ and are excluded from Git and the runtime ZIP. Report exact candidate commit, runtime versions, fixture differences, command exit codes and cleanup alongside any readiness decision. A previously passing desktop fixture is useful context but is not a passing Cloud run. Network/setup failures and skipped scenarios are not test passes. No live deployment or public release is authorized here.

Separate FREE companion checkpoint

product/free/cache-contract-check/ is an original GPL-2.0-or-later diagnostic companion requiring separately installed official Redis Object Cache. Its license applies to these new files only. It includes no proprietary cache runtime or licensing/update prototype. product/FREE-STRATEGY.md records official comparison, directory rules and the remaining independently owned Free cache engine decision.

Nine focused PHP assertions and ten distinct real single-server WordPress scenarios checked accurate contract failure reporting, bounded keys/cleanup, HTTP permissions/nonces, dependency outage/restart and uninstall. Actual default upstream scalar contracts failed in this configuration and are reported honestly; passing diagnostic tests do not establish passing cache contracts. Pre-bootstrap failures cannot be diagnosed by the companion. Wider version/topology/multisite and browser coverage remain open. No public submission/release is authorized.

python3 tests/integration/package_free.py --ref <commit> packages only the new companion runtime, listing, documentation and GPL license from that commit, with a per-file manifest. The inherited cache candidate remains proprietary under the owner-confirmed reuse authorization. The companion does not complete a standalone Free/Pro cache engine split.

Standalone FREE core checkpoint

product/free-core/cache-core-free/ now contains the independently authored single-server PhpRedis engine and owned self-contained drop-in. It uses public WordPress cache contracts and Redis commands, includes no proprietary cache files, license calls or competitor cache dependency, and is packaged separately via python3 tests/integration/package_free.py --component core --ref <commit>.

The bounded real fixture passed 66 cache API, 16 cross-process/isolation/flush and 17 recovery/TTL assertions. Four workers performed 80 increment attempts: 78 successful mutations were persisted exactly; two returned false at the bounded CAS retry limit. Real Redis pause, fresh unavailable request and recovery with explicit scoped invalidation passed; offline writes were not replayed. Real HTTP lifecycle checks exercise permissions, nonce, owned update/disable/enable, foreign-file refusal, plugin-folder absence and network re-enable freshness.

A lifecycle defect found during validation was fixed: publishing a previously absent drop-in invalidates the configured namespace first, so cached network plugin metadata cannot outlive disabled persistence. Failed invalidation refuses configured persistence enable; existing enable/update remain idempotent/preserving. Failed backend cleanup closes the socket rather than issuing network commands.

Redis 6.2+, PhpRedis, PHP 8.0+ and WordPress 6.5+ are intended minimums; actual coverage is the exact runtime above. Sentinel/Cluster/Relay/TLS are unsupported in this FREE baseline, not product-wide removed features. Bounded cleanup can leave old keys, and outage consistency requires operator invalidation. Broader versions, plugin workloads and browser visual QA remain open. This is a private reviewable standalone candidate, not a production-readiness guarantee.

Go backend and retained-state FREE recovery milestone

The actual original entitlement backend is now Go; Python remains reference/test code only. Go operation and capacity boundaries cover its loopback-only listener, locked/fsynced JSON snapshots, RSA signing and unchanged PHP API. Real Go/PHP HTTP verification passed for signed active/denial, fixed grace, original ZIP digest and old-token denial. The standalone original WordPress admin binding passed actual WordPress 6.8.3/PHP 8.3.28 multisite actions, real permissions/nonces and a separate process’s persisted inactive denial with no HTTP. It does not replace inherited paid-cache licensing, create customer accounts or install packages.

FREE persistence now requires a coherent flock-capable recovery filesystem shared by every PHP writer of the namespace, using the same PHP UID. Durable pre-connect request tickets and lifetime leases prevent namespace recovery before earlier SQL writers finish; the next eligible request rotates the generation automatically. Missing/lost state also triggers invalidation. Normal Redis failures retain local fallback; unavailable initial recovery storage or exhausted bootstrap lock waits stop bootstrap rather than permitting an unrecordable SQL writer. This deliberate availability boundary and the per-operation directory/lock cost are documented in the FREE README. Multi-node filesystems and power-loss durability are unproven.

All 55 focused FREE checks passed. The changed snapshot also passed 66 WordPress cache-contract assertions, 16 cross-process/scope checks and 17 real Redis TTL/WRONGTYPE/recovery assertions. A real Redis pause retained old physical values: two overlapping requests used local null hits, resumed Redis remained untrusted while a prior offline request delayed its SQL write, then a fresh request read the updated SQL and invalidated the old namespace without an explicit flush. Initial unwritable recovery storage refused bootstrap; deliberate state-file loss also invalidated a retained stale value. See tests/integration/free_core_delayed_recovery.py.

Go/backend, licensing admin and FREE artifacts remain private review candidates. Commercial operation, browser testing, broad runtime coverage and exact-commit CI checks remain outside the proven evidence. The paid integration evidence below extends the earlier standalone administration milestone.

Installed paid-plugin integration and operations milestone

The actual paid plugin now loads the original entitlement adapter, exposes Premium access, and publishes a locally verified update selector to WordPress. Explicit administrator actions save/activate/refresh the installation and check update metadata. The core updater rechecks the grant and exact selected package, verifies SHA-256, and writes a private temporary ZIP. The vendor licensing/update API stays disabled; entitlement status does not gate or contact cache operations. Core update_plugins permission controls cached updater access independently of license-management permission. Automatic plugin updates remain disabled.

The immutable runtime candidate 2509cf90597abeba659cd23843d51345decfd04c (ZIP SHA-256 8da7555d0871e72461e3b38e6e0fc36294bbd986f0b579f9635d6c4024c503a1) passed 180 checks in ten phases through the actual paid-plugin runner. Coverage uses WordPress 6.8.3, PHP 8.3.28, PhpRedis 6.1.0, Redis 7.4.2, MariaDB 11.4 and the real Go HTTP service. It includes actual plugin ZIP installation, administrator permissions/core nonces, signed local cache, explicit bounded download, real WP_Upgrader::download_package() and single Plugin_Upgrader::upgrade() to a private fixture version 1.25.7. The installed drop-in matches the newer stub’s physical SHA-256 and version, even when metadata was primed before the update; a fresh process confirms current diagnostics. Core’s single updater silently deactivates an active plugin, so the fixture uses normal explicit WP-CLI network reactivation before the fresh-process check.

Every phase checks actual paid-cache stored-false/null behavior. A real anonymous HTTP request made zero HTTP attempts, retained those cache contracts, loaded the paid manager and never loaded the entitlement binding. A stopped Go process did not extend signed expiry/grace or disable cache; downloads failed. Live revoked server state denied a package despite a still-active local signed cache. Opt-in hourly refresh deduplicated its own event, refreshed as user 0, persisted signed revocation and cleared only its own schedule. A separate process read persisted denial with no HTTP. All fixture containers/network/volumes were removed.

Validation fixed three integration gaps: namespace-shadowed nonce verification, single-update completion events omitted by the old bulk-only callback, and request-cached file headers that survived replacement. Focused regressions also cover genuine core AJAX authorization, update-only capabilities and supported SemVer prerelease/build metadata. The AJAX authorization branch has focused test coverage; browser-driven update interaction has not been exercised.

The final Go suite passed 12 tests with race detection, including real PHP HTTP verification and an isolated backup/restore rehearsal; one subprocess helper is intentionally skipped when not invoked as a child. go vet and a static Linux amd64 build passed. Operational instructions cover startup, trusted configuration, key custody, fixed-lock/fsynced backup and restore to an isolated new path. The rehearsal confirms that an older backup can forget a later revocation and accept an old token; operators must reconcile state before exposing a restored service.

Recommendation: GO for private/staging evaluation in the proven topology; NO-GO for public commercial launch on this evidence alone. Production HTTPS proxy/access controls, operator origin approvals, billing/customer workflows, key rotation/recovery, backup reconciliation, deployment monitoring and browser QA remain operational work. Relay, broader runtime combinations, multi-node storage and representative production workloads remain untested. The outage fixture does not wait an entire grace period; clock-injected client tests cover elapsed expiry. The owner-confirmed reuse record is retained with original proprietary notices; the upstream-referenced LICENSE file remains absent, without inventing terms.

Deployment, customer recovery and rotation gates

The current software release profile is operator-managed manual fulfillment; the readiness matrix maps every remaining gate to code, evidence or an explicit operator input. The default site remains a labelled local demo; the local customer portal is covered separately below. Automated billing/public accounts are disabled. This is a deployable software candidate for that profile; no public service or completed checkout is claimed.

New local Go commands provide manually confirmed fulfillment, unique order references, customer-bound status/renewal/revocation, verified installation recovery and lost-bearer replacement. Concurrent fulfillment creates one key; replays reveal only its digest. Replacement atomically revokes the old license and preserves expiry/limits/approved origins, with no active installations. Recovery requires explicit independent verification and an old-owner digest, binds the new installation inactive, and invalidates old download tokens. Customer state uses schema 2 while legacy licenses remain readable; older schema-1-only backends reject schema 2 rather than silently dropping customer references. No public customer API or unverified payment callback can issue a license.

Signing-key IDs are configurable, with the prior fixture-v1 default retained. The actual PHP client passed overlapping old/new RSA verification-key tests; unknown/retired keys grant no access or extended cached deadlines. RSA rotation leaves HMAC tokens unchanged, while HMAC replacement invalidates old tokens. Conservative restore reconciliation requires a separately trusted latest snapshot, its exact SHA-256 and explicit operator freshness acknowledgment. It never imports new grants, raises expiry/limits, replaces ownership or reassigns customers. Conflicting or missing authoritative ownership—including a backup before first activation—is permanently revoked. Opposite-path concurrent reconciliation uses ordered fixed locks; publication retains atomic/fsynced snapshots. The operator must establish freshness: the software cannot infer it from unsigned state JSON.

The integrated Go suite passed 27 tests with race detection in 25.312 seconds, with two intentional subprocess-helper skips. It includes real PHP HTTP, rotation, restored-state reconciliation, customer operations, CLI credential parsing and readiness checks. Additional changed CLI assertions cover actual renewal, installation recovery, lost-license replacement and reconciliation subprocesses. go vet, static Linux amd64 build and Python syntax checks passed. The unaffected 180-check paid WordPress fixture was not rerun; final runtime-file comparison preserves its exact PHP/JavaScript/CSS/drop-in evidence.

A real loopback-only nginx/Go/PHP HTTPS rehearsal passed 14 checks using test certificates and trusted test CA verification. It exercised activation, selected RSA key ID, entitlement/update/download, exact ZIP digest, anonymous denial, method/query/body rejection, private operator routes and 429 rate limits. nginx configuration validation and systemd unit verification passed. The nginx image resolved to sha256:a8b39bd9cf0f83869a2162827a0caf6137ddf759d50a171451b335cecc87d236. Owned proxy/process/temp-directory absence was checked after cleanup. No public listener, actual target-host systemd startup, DNS or real certificate was provisioned.

Installed Chromium 151.0.7922.173 passed 86 browser checks across 1440×1000 desktop and 390×844 mobile emulation, with screenshots and no JavaScript errors or external requests. Coverage includes layout, themes, keyboard/dialog focus and the labelled demo account/license/site/download workflows. Other engines, physical devices and assistive technology remain outside this evidence. Actual WordPress/Go operations are independently tested; the default demo UI remains isolated, while the optional local customer portal below connects to Go.

Functional local customer portal closure

The website now has an explicit same-origin Go-backed local test mode, enabled only by all three matching serve --portal-fixture --portal-origin --portal-site flags on literal 127.0.0.1. With no flags, the labelled in-memory demo remains unchanged. Only allowlisted public site assets are served; fixture credentials, state, private keys, repository and build files are inaccessible through the site. Existing plugin licensing endpoints retain their original contracts.

Pre-existing synthetic customers can sign in, list only their own manually issued licenses and operator-approved sites, and download the actual configured ZIP. Downloads recheck live ownership, expiry and revocation; the UI verifies SHA256 before creating a local ZIP download. No portal action approves sites, issues licenses or modifies installation binding. Credentials/CSRF remain outside browser WebStorage, and logout/401 clears all owned data. Session cookies are random, HttpOnly and SameSite=Strict with a fixed 15-minute lifetime.

The integrated portal/asset/CLI gates passed 8 Go tests with race detection in 1.784 seconds; go vet and static Linux amd64 build passed. Real HTTP fixtures cover cross-customer/legacy-license denial, revocation, expiry, corrupt state, strict origins/CSRF/JSON, session expiry/logout, and concurrent one-use recovery. Recovery changes a test credential atomically, invalidates all previous customer sessions and denies old passwords/code replay without changing another customer.

The disposable actual binary/site harness passed 20 HTTP checks and 59 installed Chromium checks on desktop and mobile emulation. It verified two customer catalogs and ZIP ownership, actual paid-package digest, existing WordPress activation/signed entitlement endpoints, reload/logout/back navigation, recovery and live operator revocation. No JavaScript errors or external requests occurred. Owned Go process exit and temporary credential/key removal were verified. Three authenticated workspace screenshots were captured separately to include the complete mobile portal rather than only part of its viewport; no unaffected functional suite was rerun for that capture. The initial aggregate networkidle navigation wait timed out; DOM readiness plus explicit portal UI readiness passed without altering any network/browser security settings.

Run product/licensing/portal/check.py with the built service and reviewed paid ZIP to reproduce the disposable proof; see portal/provider documentation and browser instructions. Reports are in build/portal-check/, with focused Go output in build/portal-go-tests.log. The unchanged WordPress runtime retains its earlier 180-check evidence; unaffected cache/HTTPS/rotation suites were not repeated.

The PortalProvider interface establishes the local integration boundary. The legacy fixture provider remains a memory-only diagnostic; the durable adapter below replaces that reset-on-restart behavior for the recommended portal mode. Real account/recovery delivery or mail, public-portal HTTPS routing and target-host operation remain unconfigured. The ordinary HTTPS deployment template deliberately exposes no local test portal route. No production account, registration, payment, private key or public launch was created.

Durable customer identity and recovery closure

The recommended local portal now uses --portal-state, a separate existing operator-provisioned identity file. Explicit portal-provision --fixture --confirm-test-provision imports synthetic accounts once and refuses every existing target; serving never reads or reimports the plaintext fixture. The legacy memory-only adapter remains diagnostic and is not the durable release profile. This correction requires no external identity or email provider.

Private account state stores login/customer IDs, salted PBKDF2-HMAC-SHA256 hashes (600,000 iterations, random 32-byte salt), recovery-code hashes/consumption and credential revisions. Fixed pathname locks serialize independent processes; state publishes with a mode-0600 temporary file, file fsync, atomic rename and directory fsync. State/directory privacy, mandatory schema fields and single-link regular files are checked on each operation. Hardlink aliases are refused because alternative pathnames would otherwise use different lock files. Go 1.24+ is now required for standard-library PBKDF2; the tested compiler remains Go 1.26.1.

Password verification returns its credential revision in the same locked transaction. Login checks that generation before issuing a session, and every authenticated request checks the durable generation again. Cross-process recovery invalidates existing sessions; missing/corrupt identity state or revision errors fail closed and remove the old in-memory session. Process restart discards all sessions and preserves changed passwords and consumed recovery codes. Storage errors after publication can mean a committed change despite an error response; the live revision check still rejects prior sessions.

The integrated changed-path suite passed 13 Go tests with race detection in 41.300 seconds, with one intentional child-helper entry skipped (the actual child process executes within its parent recovery test). It covers durable provisioning/hashed state, restart/current backups, child-process and two-provider recovery, stale session/auth generation and storage failures, legacy fallback, provider flag validation, hardlink aliases, strict state schema and ordered restore locks. go vet and static Linux amd64 build passed.

The actual CLI/site HTTP durability harness passed 52 checks with binary SHA256 e62dbf7f3c119cf91c490bfae4df18fd1121ce3a73395cbbba33631ba0e6c087. Four simultaneous recovery calls produced exactly one success. Changed passwords, consumed codes and old-cookie denial survived same-state restart and latest snapshot cold restore. A reconciled older snapshot quarantined changed customer A, denying both passwords and the old code, while unchanged customer B retained its owned catalog and exact ZIP download. Reprovisioning and unacknowledged reconciliation made no writes. Owned process exit and temporary credential/key removal were verified in build/portal-durable-check/report.json. Physical filesystem/power-loss crash testing was not performed.

Identity and license state must both be backed up. Keep restored services isolated; portal-reconcile requires a separately trusted latest identity snapshot, exact SHA256 and explicit operator freshness confirmation. Conflicting or unknown identities are permanently quarantined, recovery consumed, with no credential/customer import or automatic identity regrant. Matching latest snapshots retain the new password and consumed-code state. Software cannot detect unacknowledged offline rollback or infer freshness from unsigned JSON; restore isolation and independently current authority remain operator requirements.

The unchanged portal UI retains its earlier 59-check Chromium evidence and three authenticated screenshots; the original 20-check HTTP proof and paid WordPress 180-check runtime evidence also remain attached. Unaffected browser/cache/HTTPS suites were not repeated. No real account, mail delivery, automated signup, payment, production key, domain/host provisioning or public launch occurred. Public-portal TLS routing and target-host operation remain unconfigured, with manual account/recovery delivery requiring operator setup. The original HTTPS service template still excludes the local portal routes.