Entitlement record privacy

Confirmed production observation

On 11 September 2026 local time, an anonymous browser on memex.meshweaver.cloud displayed _Entitlements 4 on the DataModeling cover. Following that existing link listed four learner identifiers. Opening only the operator's own listed record displayed its identifier and install-right Markdown while the page still offered Sign in. No other learner's detail was opened and no entitlement, grant, inquiry or course content was changed. Identifiers are intentionally omitted from this receipt. This is an actual anonymous record exposure, not only a discoverable count.

The authenticated policy audit found DataModeling/_Policy version 213947 carrying only redirectOnDenied: DataModeling/Subscribe. Root Anonymous and Public Viewer assignments were present (versions 9745 and 5635). DataModeling/_Entitlements/_Policy was absent.

Source cause

Entitlements.EntitlementMarker writes an ordinary Markdown node at {plugin}/_Entitlements/{viewer}. Its path and body identify the viewer and acquisition provenance. An underscore in the namespace does not itself restrict the node's Read permission.

PluginGate.GatedChildRoots skips every underscore-prefixed child root. The ordinary entitlement records therefore inherit the public cover's root Viewer grants. Hiding the folder from the catalog would leave both direct reads and searches authorized and would not correct the exposure. The system's Entitlements.IsEntitled probe already reads its two per-viewer records under the System identity; the caller does not need direct read access to the marker to remain entitled.

Prepared correction

Store seeds a PartitionAccessPolicy with read: false and no public-read grant at {plugin}/_Entitlements/_Policy. The normal gating pass verifies that policy before its public cover grants, even when the broad snapshot or parked-write state would otherwise skip a candidate. An unreadable or non-durable privacy policy stops the pass. The policy is treated as gating bookkeeping, so its own write cannot trigger a reconcile loop. A converged pass writes nothing.

The canonical GrantEntitlement marker write runs after two targeted prerequisites. The first, EnsureEntitlementPrivacy, verifies the private child policy. The second checks the root policy and removes a legacy blanket public grant when present. Each performs only an exact-path read and, when needed, a write plus exact-path read-back. Every read has a 30-second bound and converts a silent provider into the fail-closed privacy error. Coupon, order and admin acquisitions therefore close both bypasses without scanning the package subtree; the full reconcile remains in provisioning and the watcher. SeedGating completes both prerequisites before it acquires the root or either broad snapshot, then carries their outcomes into its write summary. A slow or failed package snapshot therefore cannot prevent the targeted privacy repair. A failed write is surfaced as the localized privacy error while retaining the provider or authorization failure as its inner exception.

Pre-installed roots now use an uncapped, no-redirect, publicRead: false role-open policy. Their existing explicit Public and Anonymous Viewer assignments still make the cover and content readable. A gating pass replaces the older blanket publicRead: true shape before it verifies private records. This matters on older supported evaluators: those versions apply descendant caps to role-derived permission, but an inherited blanket public grant bypasses a deeper Read cap. Removing that blanket grant makes the child policy effective without a framework-version barrier.

The background AddPluginGating watcher catches and logs a failed pass inside its per-change observable. On an existing public course, a later visible content change can then request a new pass. Propagating that error through Switch to the terminal subscription would dispose the entire watcher and prevent recovery. Direct provisioning and acquisition still receive the failure; the catch does not turn that failed pass into a successful privacy verdict or continue its remaining writes. The watcher's existing query identity is unchanged. A first-ever unpublished root whose initial pass fails before any cover grants exist is not covered by this recovery guarantee: later private children may be invisible to that query. Retry its normal Provision request after resolving the failure; do not add viewer grants to force watcher visibility. The separate unpublished-root diagnostic retained the private state and observed no later recovery (/tmp/store-gating-recovery-private-first/private-first-diagnostic.trx); it is not a passed watcher-recovery case.

The current framework also suppresses an inherited public grant at a deeper Read cap. That remains defense in depth; Store no longer depends on it for entitlement privacy. Production acceptance must still prove that every legacy blanket-open root was reconciled and that anonymous query and direct reads are denied.

Local validation

The prepared Store tree compiles all 89 node types with zero warnings/debt, new breaks or fingerprint drift (/tmp/store-entitlement-recovery-final-compile.log). The pinned ci8282 tester (a local candidate, not a sealed production publication) executes 872 Store cases across 17 types, with zero failures or skips. Its 49 mesh-required cases are explicitly separate from that native verdict (/tmp/store-entitlement-recovery-final-native.log, actual runner verdict: 872 passed, 17 types). The wrapper's separate tested 0 summary is a parser defect, not the runner's verdict. These are local receipts, not a production release claim.

EntitlementPrivacyTests adds a shape/hydration check and three hosted cases: privacy-before-public seed ordering and zero-write convergence; ordinary gated-root privacy; and migration of a legacy publicRead: true root to the role-open shape before its entitlement records are tested. The actual records are created through the canonical acquisition path. Query and direct-read assertions include public-content and System-read positive controls, plus enrolled-learner access outside the private subtree.

All three hosted cases pass against core commit 56260054a in an isolated Monolith ConfigureMeshBase fixture with in-memory persistence and no ambient Public Admin grant. The fixture compiles the actual 33 Store source/test files. It proves zero query rows and an actual UnauthorizedAccessException on direct reads for anonymous, unrelated signed-in and already entitled peer viewers, while the real System targets, public cover/content and enrolled-learner Read/Execute/Api checks succeed. The ordered seed also converges to zero writes. The refreshed final receipt is /tmp/store-entitlement-privacy-host-final/results/entitlement-privacy-final.trx (3/3). Its sibling receipt.json and portable-PDB checksums establish that all 33 compiled Store files match the final source. The earlier 3/3 receipt remains under /tmp/store-entitlement-privacy-host/. These are actual registered runtime access evaluations, not PostgreSQL-specific executions or production acceptance claims.

The durable compiled regression PluginGatingRecoveryTest.ExistingPublicCover_RequiredPrivacyFailure_ThenRealChildChange_StillGates uses the actual registered AddPluginGating pipeline and a public node validator that refuses the first required privacy-policy write. It seeds only the existing course's canonical cover Viewer assignments and verifies their versions remain unchanged. Both metadata observers explicitly include the AccessAssignment query; the test does not mistake an omitted security table for an absent grant. With the old watcher from e2540c2, the exact fixture fails because a later genuine lesson receives no denies (1 executed, 1 failed; 23 seconds). With the inner catch it passes (1/1; 9 seconds), verifying durable policy/denies and the public-cover and fresh-unentitled access controls. Receipts are /tmp/store-gating-recovery-red/results/recovery-red.trx and /tmp/store-gating-recovery-green/results/recovery-green.trx. Both compiled builds are strict, with zero warnings or errors. The test lives in MeshWeaver.PluginCatalog.Test; the canonical CI selector recognizes its linked Store sources, and the portal-hosts shard executes this suite and requires a fresh TRX. It is not a test that exists only in a temporary local harness. /tmp/store-gating-recovery-green/receipt.json records both portable-PDB source manifests: all 34 compiled Store documents match between causal red and green except PluginGating.cs itself. EntitlementAcquisitionPrivacyTest.GrantEntitlement_RefusedPrivacyPolicy_WritesNeitherMarkerNorGrant exercises the direct acquisition boundary. Its hosted mesh calls the real Entitlements.GrantEntitlement while a validator refuses creation of the required private policy. The acquisition must surface that refusal and leave the entitlement marker, viewer grant, purchase ledger row and both public cover grants absent. The compiled validation map now includes Store/ as an input for MeshWeaver.PluginCatalog.Test, so a Store-only pull request cannot omit either hosted regression from the selected compiled test projects.

Fresh review identified that calling the full SeedGating reconcile from every acquisition would put both capped subtree snapshots, up to 4,000 rows, on the coupon/order/admin critical path. The targeted prerequisite above removes those snapshots from acquisition while preserving the same read/write/read-back failure contract. After extraction, all 877 Store node tests pass, including the real coupon click/redraw case; the hosted acquisition and watcher regressions pass 3/3. The prerequisite preserves a provider, authorization or timeout failure as the safe outer privacy error's inner exception, so acquisition and watcher logs retain the actionable cause. The live privacy cases explicitly await SeedGating, use known purchase-ledger ids and replay their original verdict only after bounded best-effort cleanup of every synthetic partition and ledger row. They therefore do not depend on the delayed background watcher or accumulate records when rendered on a persistent mesh.

The compatibility iteration keeps those assertions and begins the pre-installed case with the literal legacy publicRead: true policy. The root compatibility prerequisite runs before the broad snapshots, and SeedGating also queues a targeted convergence check, so an undercounted snapshot cannot hide that unsafe row. The three live cases pass both on the older 45306a33 evaluator and on 56260054a (3/3 on each). Store's supported node runner passes 877/877. A hosted acquisition begins with a durably visible legacy blanket root and verifies that the canonical acquisition removes it before its marker and viewer grant appear; together with the refused-private-policy and watcher recovery cases, the focused compiled set passes 3/3. The coupon owner fixtures pass the live Monolith click (1/1) and the three input/redraw state cases (3/3). Their generic object fallback now serializes with the value's concrete runtime type, avoiding incidental runtime type registration in the test host. Receipts are under /private/tmp/pr1635-privacy-oldcore-review6-final-results/, /private/tmp/pr1635-privacy-current-review6-final-results/, /private/tmp/pr1635-compiled-review6c-results/, and /private/tmp/pr1635-coupon-{monolith,state}-review5-results/. The complete existing MeshWeaver.PluginCatalog.Test suite also passes with the final linked sources: 730/730, zero failures or skips, exit 0 in 6.23 minutes. The new watcher case passes in that full run too. Receipt: /tmp/store-gating-recovery-full/results/plugin-catalog-final.trx; log: /tmp/store-gating-recovery-full.log. The final repository shape gate validates 261 nodes across 60 packages; all manifest locks match.

The later linked-source compiled test build also corrects two existing nullable contracts: IsEntitled uses its already non-null hub parameter without null-conditional access, preserving the requirePurchase: false short circuit; policy hydration supplies the equivalent default JSON options when none are provided. These mechanical changes permit the strict test build without a project-wide warning downgrade. They are separate from watcher recovery.

The first PR CI run also exposed three pre-existing nullable primary-silo casts in OrleansThreadColdLoadHangTest. The canonical compiled selector declares src/ for all 52 entries, so adding the Store test correctly selected the AI Orleans suite too. Shard 3 of run 34546322972 failed compilation before executing tests; its core reference was 45306a33e9437f1b662450dc23c4dfa6d897fe41. Replacing those casts with explicit Assert.IsAssignableFrom<InProcessSiloHandle> preserves derived handles and all scenario assertions while rejecting a missing primary. The entire affected project builds with zero warnings/errors against that exact core, and all three focused cold-load scenarios pass with no skips. Local SDK 10.0.400 differs from CI's 10.0.401; both use Orleans TestingHost 10.3.1. The receipt is /private/tmp/store-1635-coldload-results/receipt.json. This is a focused execution, not a claim that the whole AI Orleans suite ran locally or that the failed CI shard passed.

Earlier CI exposed a blanket-public compatibility gap

At Store PR #1635 head 722d94ec, run 34547700269 tested merge source b32863765f. Gate job 103107985433 compiled all 89 node types and rendered Store/Licensing successfully, but its tests passed 69/70. The sole failure was “Privacy (live): an open course keeps enrollment records private”, with “An enrollment query disclosed synthetic learner records”. The gated-course privacy and ordered/idempotent seed cases passed. This was a real query-denial assertion, not a timeout. Aggregate job 103109341121 correctly folded its one shard and propagated the failure; it introduced no separate error.

The same run's separate portal-host shard 0, job 103104485330, failed before its moved-suite test loop: four nullable Cluster.Primary casts produced CS8600/CS8602 in OrleansSlideNavigationPostgresTest (three sites) and OrleansThreadColdLoadHangPostgresTest (one site). Both files were byte-identical on the PR's base and head. Commit b386b845 replaces only those casts with Assert.IsAssignableFrom<InProcessSiloHandle>(Cluster!.Primary), preserving the fixture's non-null, subtype-compatible contract and every scenario assertion. This compile correction is independent of the open-course privacy failure above.

Against that exact CI core 45306a33, the full PostgreSQL test project builds in Release with warnings treated as errors, with zero warnings/errors. The two existing slide-navigation cases and the existing cold-thread case then passed 3/3 against a fresh disposable pgvector 17 database, with MESHWEAVER_LOCAL_PG_CS explicitly set. The TRX results contain the scenarios' actual completion messages; none took the tests' no-database early return. The isolated database was removed afterward and existing previews were untouched. Local SDK/runtime were 10.0.400/10.0.11 versus CI's 10.0.401/10.0.12, with Orleans TestingHost 10.3.1 in both. Exact source hashes and the two TRX files are recorded in /private/tmp/store1635-pg-nullability-results/receipt.json. This validates the affected PostgreSQL scenarios, not the entire suite or the still-failed CI run. The privacy failure showed that the earlier Store candidate still depended on the newer evaluator.

The run's publication-inputs artifact 10179692416 identifies core 45306a33e9437f1b662450dc23c4dfa6d897fe41, tester digest sha256:cce1eb2672909751d983aa4506189b99e1dee371cdf2eddcdaac1412756f4379 and portal digest sha256:80030288ada670746f7ef6078dd05f2727076549be7ac9cae80142722110f30e. These match the gate's actual inputs and framework identity s3e3c80238a740a8cb895a72b0bfb9cd6; the newer b65c1957 workflow-script revision is not the runtime. That runtime's src/MeshWeaver.Mesh.Contract/Security/PermissionEvaluator.cs:698–703 accumulates the ancestor public grant without applying the descendant cap, then ORs that grant after the role cap at 348–349. Core #3990's evaluator at 269e48e572 has the exact tested 56260054a source (1e023fd77b9979c3f104704168a6f2393c2e638c2825a55e70a0d781716aa4dd): it intersects the inherited grant with each scope's cap before adding that scope's own public grant. All 33 Store documents match the earlier successful matched-core 3/3 receipt's portable-PDB hashes.

That result was valid for the earlier candidate, whose pre-installed root deliberately retained publicRead: true. Fresh review later removed the dependency at its source: the gating pass now migrates that blanket grant to the role-open policy while retaining the explicit root Viewer grants. The privacy test keeps the same query and direct-read assertions and now seeds the legacy shape explicitly, so passing on core 45306a33 proves the compatibility correction rather than hiding the evaluator difference. No image pin, run-input override or test exemption is used. The downloaded historical shard artifact is 10180255535; detailed evidence is /tmp/store-1635-34547700269-diagnosis/receipt.json and its sibling publication-inputs.json.

Supported adoption

A source publication does not itself prove every existing course has the new policy. All serving replicas must adopt this Store source and its current type builds before acceptance, including the newly compiled Store/Provision and Store/Plugin types used for repair and reconciliation.

Store does not need a minimum framework-version declaration for this correction. The role-open root shape is compatible with the older evaluator in core 45306a33: public access comes from the explicit root Viewer roles, so the _Entitlements Read cap applies through the ordinary role cap. Core 56260054a additionally suppresses inherited blanket public grants at deeper caps, but that fix is defense in depth rather than an admission dependency. Acceptance therefore records the actual Store source/type fingerprints and access behavior instead of relying on version metadata.

Store/Plugin registers AddPluginGating. A newly activated current hub runs its initial gating pass; later real content changes run another pass. PluginHubWarmer touches catalog roots to start cold hubs, but touching an already active hub does not prove it rebound to a newer assembly. Modules:AutoRecycleOnStaleBuild is off by default; its value was not audited on production for this fix. Use the supported adoption path and verify actual builds and policies, without changing that setting merely to pass acceptance.

For a confirmed existing, readable root already typed Store/Plugin, a fresh normal Store/Provision request in Admin/Provision may specify only packageId and requestedAction: "Provision" in registered ProvisionContent. Omit repository, branch and subdirectory for this repair. ProvisionContent.ToRequest has no registry-source fallback. SystemInstall.Plan then skips root creation/retyping, GitSync wiring, source import and registry install. It still performs authorization when an invoker is present, both declared and derived dependency checks, the full normal SeedGating pass, and CompileAllTypes. It does not fetch or adopt compiled module bundles. This is not a policy-only operation: a course containing NodeTypes (for example AgenticPrimerDe's WishBook and DiceGame) can request course-local type releases. Inspect that root's actual type census and dependencies before using this path. An absent or incorrectly typed root needs its normal source-backed provisioning procedure instead. A successful gating phase on the verified current Provision build includes the required System read-back of that root's private policy; pair that receipt with the viewer-facing denial checks. The learner/operator does not need new direct access to the protected policy to verify delivery.

SAV rollout checkpoints

The fifteen ordinary Provision requests in Edu/LearningRoadmapRelease remain sequential. Treat the first Store step as a verified bootstrap barrier: provision Store from the published source containing Plugins #1635 and require the whole-Store compile gate plus actual adopted source fingerprints for Store/Provision and Store/Plugin. Subsequent fresh requests must bind those current builds before proceeding with Edu, the courses or LearningRoadmap. A Store version label or a Done request alone is insufficient. This order follows Store/Publishing/Source/SystemInstall.cs (Plan: gating before CompileAllTypes) and the canonical acquisition prerequisite in Store/Licensing/Source/Entitlements.cs (GrantEntitlement).

If MeshWeaver.Courses still needs adoption after the correct publication, place the scoped Edu refresh after that barrier. Use a fresh normal Store/Maintenance request with MaintenanceContent fields task: "RefreshModules", package: "Edu", and requestedAction: "Run". An existing Plugins/Edu record at 1.8 does not pin the refresh to 1.8: Store/Maintenance/Source/ModuleRefresh.cs (Inventory, Select, RefreshOne) uses its ID only; Store/Publishing/Source/RegistryPackages.cs (Install) selects the registry's current manifest at HEAD. No installed-record version edit is needed. The offered manifest and module bundle must actually contain the intended published Edu 1.9 source.

This refresh installs package content before attempting module landing: RegistryPackages.Install calls PackageInstaller.Install before LandModule. It can update Edu nodes and the install record, and request NodeType releases, while zero new module files land. Core src/MeshWeaver.PluginCatalog/PluginBundleClient.cs (AdoptModule) chooses the registry bundle index entry and compares it with the actual module activation entry; it does not choose a version from the old Plugins/Edu record. Core src/MeshWeaver.PluginCatalog/PackageInstaller.cs (WriteInstalledRecord, RequestReleases) explains why a new record or requested release is not a loaded-module or successful-compilation receipt. Require the intended bundle identity, actual landing/proposal outcome, supported deployment activation and served MeshWeaver.Courses generation before continuing with the ordinary Edu Provision compile gate and the remaining requests. These are source-backed rollout requirements; this audit did not execute a refresh, provision or deployment.

The private policy is required regardless of whether a root is gated or pre-installed. A legacy blanket publicRead: true root is migrated to the role-open shape while its explicit Public and Anonymous Viewer assignments keep public content readable. The descendant Read cap then protects records on both old and current evaluators. Runtime policies and markers are governance paths: StaticRepoImporter.ComputePrunableNodes excludes underscore segments from pruning, so ordinary source reconciliation preserves them. That source review is not a substitute for the repeated runtime acceptance below.

Combined coupon correction — 11 September 2026

The coupon correction from b09e2d0f892f0b0fc0f154f1f8291c82a6494c0d is integrated with this privacy candidate's c33cc1dddae356abc7fd5ad1b4f58c77f912fc53 baseline. The authored changes merge without conflict: the coupon panel's original source is byte-identical on that baseline and Plugins main 481298ac. No main merge is needed for this correction. The private policy, marker ordering, recovery watcher and the stronger explicit primary-silo assertions remain unchanged. The Store lock is regenerated over both changes.

The actual combined source passes:

The three compiled host fixture builds are strict, with zero warnings or errors. The unchanged 730-case PluginCatalog suite's earlier complete receipt remains above; this integration reruns its affected watcher case rather than claiming another full run. Current logs, TRX files, input hashes and the final package receipt are under /private/tmp/store-coupon-privacy-integration/. The local runner requires a coherent host reference set: the image-derived reference cache used for compilation cannot execute on macOS and the first attempt exited with BadImageFormatException before any test. The successful 872-case run uses the recorded b65 SDK reference set.

A single GitHub REST snapshot confirmed core #3990 and #3991 merged at 03:43:29 UTC on 11 September 2026 (merge commits ba954a2edc06acc8ae5358cb142accda40144c8f and 6231c4da4c1baa5dbcc9e44b43020006583fcb2c). Merge is not a seal or deployment receipt. The combined Store candidate remains local until normal fresh Store CI and the production acceptance below complete.

Final Store integration — 11 September 2026, 04:42 UTC

The earlier coupon-only overlap assessment did not include three compiled test-fixture files. After pushing 794244d1, GitHub correctly reported a conflict and created no normal CI run. Merge 25a56f83 incorporates main 481298ac and retains all seven stronger Assert.IsAssignableFrom assertions from this branch. The actual privacy and coupon product sources are unchanged by that merge. Release builds of the affected AI Orleans and PostgreSQL fixture projects pass with zero warnings or errors against the established coherent b65 core.

The cover-action correction from 8e91b731 is integrated as 19d0d2f0. It gives course controls stable semantic identities, so a click retained while Resume arrives still reaches the current Get/Repair dialog. See Course cover action identity for the matched two-fail-before/two-pass-after owner-dispatch evidence and its browser acceptance boundary. This change preserves the private policy, acquisition ordering and recovery watcher.

Core #3990 and #3991 merged into 6231c4da, but the successful CD run 34559585291 actually built the earlier target 6e024887d6dac6a28378d989c95d71e763fb9cc7 as 3.0.0-ci.8322. Its workflow-definition HEAD was 6231c4da; that is not the image source. The earlier interpretation that this completed run delivered the two fixes was incorrect. The production version endpoint still returned core 45306a33 at 04:41 UTC; neither that snapshot nor the completed older publication proves repaired production privacy.

Historical final-candidate failure on an older image target

At head ea5e500d, Store CI 34563552104 again passed Store/Licensing compilation and rendering, then failed the open-course privacy query assertion (69/70). Store/Plugin passed 88/88. This is not the local stale test-registration incident. The actual anonymous query failure also reproduces in a fresh disposable full Store gate using the same pinned ci8322 image indexes and module artifacts. Both entitlement markers exist, the child read:false policy is saved, and the evaluator's cached policy query contains both the child cap and parent publicRead:true. Its permission subscription still grants Read during the bounded observation. No privacy assertion or access fixture was weakened.

Matching DLL/PDB records explain the failure. In both the exact Linux AMD64 portal and tester, MeshWeaver.Mesh.Contract.dll hashes 374b5a21393625c8d39ebb17256591d47eda8b77aab1ffb950546c538a9b6558; the PDB matches the DLL's CodeView GUID and records PermissionEvaluator.cs source hash 472c97c6d7419145178cff0e693bde17cad2e9d17d35ecbfb96bf222e1af3219. That is exactly source 6e024887 before #3990. The corrected source in 6231c4da hashes 1e023fd77b9979c3f104704168a6f2393c2e638c2825a55e70a0d781716aa4dd. The ARM64 variants independently contain the same old source. The producer's target output and both image-job checkouts confirm 6e024887; there is no evidence of a corrupt build cache or incorrectly compiled image.

The Store resolver at 04:48 UTC skipped runs 8324 and 8323 because their required publication jobs were skipped or absent, then correctly selected the latest available sealed set, 8322: portal e30481c6f6aeb2ffdacec3e1cb7c6fe29de00dca2eba1c32333adbe80399aa44, tester f230783c40f2df235118ed20cc2060be9f022d91876c584ec4b21b429ca9c045. However, scripts/resolve-platform.py then derived its reported core sha from workflow_run.head_sha, incorrectly reporting 6231c4da for those older image bytes. That field identifies the workflow definition for this event; the producer's resolved target identifies the image source. The resolver's source/image provenance needs to use the latter.

The failure proved that the then-current Store shape was unsafe on a still-supported evaluator. The final role-open migration addresses that Store-owned compatibility gap, while retaining the same privacy assertions. Production privacy still requires ordinary Store adoption plus anonymous query/direct-read checks below. Full raw logs, image manifests, matching DLL/PDB receipts, source comparisons and the disposable reproduction are conserved at /private/tmp/store1635-final-ci-diagnosis/. Existing local previews and production were not changed during this diagnosis.

The next set, 3.0.0-ci.8323 from CD 34559736018, sealed and registered at 05:15 UTC, after the failed Store run had already selected its inputs. Its actual image target is 6231c4da; portal index a3a9f38c09a6c3adbdc5af5334ba3439cc77ef891e624cb48b44e866e012c6f6 and tester index 5947d86c0406be4a445c13781cb7082384c91626de7f4ef6aab9d8d2935d2cf8 both contain the corrected evaluator. Matching AMD64 DLL/PDB records confirm source hash 1e023fd7…4dd; the DLL hashes 60e30696bb21c83a8a98b2a820fdafffdad44bb4fb46e9c99a0885b3cfa6f74c.

A fresh local full Store gate then used that set's ARM64 portal/tester and the same run's AI, Markdown.Collaboration, Maps and Stripe bundles, with the exact unchanged ea5e500d Store source and assertions. All 17 types compile, render and execute their Tests areas: 895/895 reported cases, including Licensing 70/70 and Plugin 88/88, exit 0. The gate also reports no install, idempotence or content errors for its 205 Store nodes. Receipt: store8323-full-gate-report.json and store8323-full-gate.log in the diagnosis folder above. This is a full local gate on the corrected release, not a rerun of CI or a production privacy claim. The next normal CI must freshly resolve this set or a verified successor; the independent resolver provenance correction remains necessary.

The previous coupon-only local browser run passed 27 of 28 cases with zero retries. Coupon submission used a 1.889 ms fill-to-click gap and the complete 22-root acquisition, fresh Get and Reset passed. Final Repair opened no dialog while Resume changed the row. That trace is consistent with the independently proven cover-action defect but does not itself record owner dispatch order. Both saved learner Plans were unchanged. The final corrected browser run must have its own receipt; the earlier failure is retained under /private/tmp/education313-coupon-coordinated-acceptance/.

The final combined source passes all 89 compilation sets, 261 node-shape checks and 60 manifest checks. Its supported Store runner executes 872 pure cases. The actual compiled host fixtures execute all five coupon/cover-action cases and all four privacy/watcher cases successfully, with zero skipped tests and strict zero-warning builds. Source parity confirms the six coupon/CTA files match 8e91b731 and the private-policy, watcher and stronger fixture paths remain unchanged. Detailed receipts are retained under /private/tmp/store-cta-coupon-privacy-final/.

The separate 8339 preview imported the isolated final coupon/CTA Store package successfully, then its normal Compile action failed at 04:43:49 with an assembly-context unloading error from CompilationCacheService.PinResolved. The old preview runtime already includes that bounded pin/re-resolution mechanism; this receipt does not assume a newer framework fixes the error. Both saved Plans remain unchanged. The final browser run is held pending supported recovery and verified compiled-source/test registration. This runtime failure is not a passed local mesh test, and the successful native fixtures are not substituted for browser or production acceptance.

Acceptance boundary

The correction must enforce the existing access model on actual query and direct-read paths:

Local preparation does not change production permissions. Production acceptance remains pending review, release-owner clearance, normal published delivery and a repeated anonymous boundary check. For the production receipt:

  1. Record the selected publication, serving replica framework/build identities and actual Store source/type fingerprints. A new Store root version alone is insufficient.
  2. Inventory existing course roots and verify each private cap after normal activation or the scoped Provision path above. Include a blanket-public root without changing its public policy.
  3. Recheck anonymous list and direct-read denial using only the operator's own known record; retain redacted evidence. Check the public cover and Subscribe page, a fresh unentitled signed-in visitor's gated lesson redirect, and an entitled learner's ordinary course access.
  4. Exercise the authorized coupon acquisition through the normal UI and confirm the System entitlement probe still succeeds. No manual access grants or direct marker writes are needed.
  5. Repeat policy, source fingerprint and access checks after normal source reconciliation and a fresh page load. Only then claim durable delivery. Keep the selected-publication hold until review and required CI/release checks are satisfied.
Reconnecting…
The server was updated. Reloading the page to pick up the latest version.