This ledger responds to all 118 stable finding IDs in the original review. It covers the corrected cumulative implementation on codex/service-layer-review-fixes, based on Phase 7 6633bb59 and the latest integrated app branch snapshot 5152a5c4. Earlier phase PR history is retained; fixes target imp/blazor-hybrid-service-layer-decoupling. No final production-branch merge is authorized by this document.
Addressed means the code, test or documentation remedy exists at this cumulative tip. It does not mean native device acceptance passed. Findings refuted by the original review retain their recorded disposition and historical reasoning at the reviewed phase; those rows do not describe every later source change. F68 retains the guarded synchronous start because moving it outside the generation barrier would reopen an account-boundary race; no device contention measurement is claimed.
The final exact commands, tested code revision/tree, counts and native build results are recorded in review validation. Intermediate failures were read from uniquely named TRX files before rerunning. Historical phase counts remain in implementation evidence; they are not substituted for this review pass.
Native device walkthroughs were open at this review tip. They subsequently passed on reconciled application 8fb3181f1cefe66018305ac5dda917a0ec6fddfb: iOS run 16 followed by Android run 17. The current validation record contains per-walkthrough results, installed-artifact proofs, exact counts and evidence hashes. This closes device acceptance; the final integration still requires the target's human approval.
| ID | Status | Remedy or retained disposition and evidence |
|---|---|---|
| F01 | Addressed | Fixed remaining tip behavior; earlier aggregate code is historical — MenuService now distinguishes explicit context invalidation from transport timeout and retains installed-menu fallback. MenuService_MenuCacheFallbackTests.RefreshTransportTimeout_ReturnsInstalledMenu; shared query timeout fallback covered under F18. Favorites has no persisted read fallback to restore at tip. Earlier P0 standalone warning remains historical. |
| F02 | Superseded | Already fixed in Phase 5: ordered logout participants continue after individual cleanup failures; Authentication_LogoutCacheContextTests and Authentication_PublicationTests retain the regression coverage. |
| F03 | Addressed | Fixed — CacheContextCoordinator.Generation uses Volatile.Read; writes remain under the atomic coordinator. CachedRemoteQueryTests.GenerationRead_DoesNotWaitForAnUnrelatedCacheCommit holds an actual commit while another reader obtains generation. |
| F04 | Superseded | Already fixed in Phase 5: epoch/publication guarding blocks refresh resurrection after logout. Authentication_PublicationTests.SilentResponseAfterLogout_CannotRestoreTokenUserOrFlags. |
| F05 | No change — refuted | Caller-side contract documented in ICacheStore.cs:9-13; every non-test writer at the tip wraps the write in TryExecute with a pre-fetch generation. |
| F06 | Addressed | Fixed — Dynamic home feed and main warmup explicitly consume ContextInvalidatedException before the error/not-found branch. Existing generation rejection tests continue to cover producer behavior. |
| F07 | Addressed | Fixed: Favorites mutation publication is best-effort after server success and cannot repopulate an outgoing memo. TopNav and AppShell consume expected context changes. The transport preserves confirmed successful favorite HTTP mutation results while retaining pre-send guards. CacheContextSafetyTests addition/removal cases prove server success without outgoing memo publication; LogoutAfterServerCommitsFavorite_PreservesConfirmedMutationOutcome covers the transport boundary. |
| F08 | No change — refuted | Plan checkboxes are all unchecked; inventory documents the prose contract and defers other families to later phases; codecs exist at the tip. |
| F09 | No change — refuted | Failure scenario unreachable: non-refresh reads return the memo or persisted cache; the old flag was never reset and was the latent bug. |
| F10 | Addressed | Fixed: parameterized late-result coverage spans all registered cache partitions, with zero persistence or publication after invalidation. CacheWriteBoundaryTests.Raw_Api_Cache_Writes_Stay_In_Guarded_Owners rejects production raw cache writes outside the recognized captured-generation publication paths. |
| F11 | No change — refuted | No new DataManager exists; DI registers IConnectivityService; fallback never taken and deleted with DataManager in P7. |
| F12 | Addressed | Fixed: MauiProgram restores native service-layer request/resource timeouts to 30/60 seconds. Native cancellation timing remains a device acceptance check. |
| F13 | Addressed | Fixed: AuthenticatedRequestProvider allows one auth recovery independently of MaxRetries, within the original deadline. ZeroTransientRetries_StillAllowsOneAuthRecovery, TransientAttemptsAlreadyExhausted_StillPermitsOneIndependentAuthRecovery. |
| F14 | Addressed | Fixed: MauiProgram explicitly resolves validated IOptionsMonitor |
| F15 | Addressed | Fixed: refresh is accepted only after rereading a nonempty token different from the rejected token. A fresh request can retry a completed failed recovery instead of retaining that failure for the token lifetime. SuccessfulRefreshWithUnchangedToken_DoesNotReplayRejectedCredential, FreshRequestAfterFailedRecovery_CanRecoverAnUnchangedToken. |
| F16 | Addressed | Fixed — Foreground refresh replaces older non-refresh/background producer; explicit per-key invalidation retires a forced producer after mutations. Subscriptions toggle invalidates its query key. Concurrent equivalent forced requests still share one producer. ExplicitRefresh_ReplacesAnOlderBackgroundFetch_AndOldResultCannotOverwriteIt, KeyInvalidation_PreventsPreMutationProducerFromPublishing. |
| F17 | No change — refuted | Every forced-expiry path runs logout (advancing generation) before another member can sign in; CachedRemoteQuery had no production consumer in P1; SignInContextReset added in P7. |
| F18 | Addressed | Fixed — Bare OCE/TaskCanceled without an actually canceled token now follows transient fallback; explicit context changes and real canceled tokens still propagate. TransportTimeout_WithoutCancellation_ReturnsPersistedFallback; existing caller-wait cancellation and context tests retained. Full-suite MEC compatibility cancellation now supplies an actually canceled token, with a paired token-transport timeout test verifying stale fallback. |
| F19 | No change — refuted | AuthRestClient consumes IRawRequestProvider at the tip and AuthRestClientTests covers both bodies; P1 has RawNoRetry_PreservesStatusAndBody. |
| F20 | Addressed | Fixed for the corrected cumulative implementation: checked-in validation record pins the tested code tree and exact commands/counts; historical phase snapshots are explicit. Earlier phase results are historical and cannot authorize shipping an intermediate phase alone. |
| F21 | Addressed | Fixed: InvalidatedContext_DoesNotReturnLateToken keeps IsLoggedIn true, so only the generation guard can reject the old token. |
| F22 | Addressed | Fixed: automatic and supplied bearer attachment requires HTTPS plus the exact configured gateway origin (including port); unknown Optional requests remain anonymous, unknown Required requests fail before sending. UntrustedOrigin_NeverAcquiresOrLeaksBearer. Native redirect handling remains device validation. |
| F23 | Addressed | Fixed: gateway readiness, mobile-content API and fault-injection docs use endpoint options/configurator and current client owners. Legacy incident descriptions are labeled historical. |
| F24 | Addressed | Fixed: final transport and JSON contract failures produce value-free method/operation/type diagnostics; transport and JSON Error messages no longer echo raw exception payloads. RequestProvider and AuthenticatedRequestProvider. |
| F25 | No change — refuted | Stale-snapshot scenario cannot happen (both Settings paths publish); other items are planned P1 work. |
| F26 | No change — refuted | HttpError/DeserializationFailed fallback and Sentry reporting restored in P3 (MecService.DefaultOptions, LegacyCatalogFailure); 401-no-fallback is the plan's documented rule (line 333, 740, 1823). Refuted 2 of 3. |
| F27 | Addressed | Fixed — MyPilotGroupPageViewModel marshals Groups lookup and both bound status updates through the existing BannerPageViewModel main-thread dispatcher. MyPilotGroupEventReadinessTests.EventsReadyWork_FromPoolThread_ChangesBoundCountsOnlyThroughUiDispatcher. |
| F28 | Addressed | Fixed: MecNullableDecimalJsonConverter preserves null, empty string, number and numeric-string hotel coordinates. Hotels_NullableCoordinatesPreserveLegacyStringInputs. |
| F29 | Addressed | Fixed — CachedRemoteQuery accepts the owning service's captured expectedGeneration; all delegate-based services pass it, including Content's outer banner/config operations. The helper rejects a stale delegate before installation. RevokedExpectedGeneration_DoesNotInstallAnOldDelegateInTheCurrentContext. |
| F30 | Addressed | Fixed remaining tip gaps — MEC corrupt installed row eviction plus online recovery tested end-to-end through MecService. Event-count UI dispatch tested under F27. Aggregate forwarding/clear-memo evidence is superseded by aggregate removal at P7. |
| F31 | Addressed | Fixed: named route constants replace inline routes in MecApiClient, NotificationsApiClient, SubscriptionsApiClient and ContentApiClient. MecService event readiness scopes use nameof on the MEC/LEC enum members. |
| F32 | No change — refuted | Endpoints are identity-independent app config; legacy sent no bearer pre-login; pinned by ConfigAndUpdate_ArePublicAndNeverAcquireABearer; plan line 796 lists app configuration as guest-safe. Refuted 2 of 3. |
| F33 | Addressed | Fixed — Background sign-out marks pending guest-banner refresh; the existing delayed/auth-gated resume path replays it after releasing the background latch. No early network herd introduced. RejectedSessionWhileBackgrounded_ReplaysGuestBannerRefreshAfterResume. |
| F34 | Addressed | Fixed — Waiters record the current per-wave attempt; after the active attempt completes they share its outcome even on failure. A later trigger can retry. Canceled/context-revoked waves do not suppress their replacement. ConcurrentFailedBulkTriggers_ShareOneAttempt_AndLaterTriggerCanRetry; existing resume replacement tests retained. |
| F35 | Addressed | Fixed: ContentService and default-returning ContentApiClient operations report through LegacyCatalogFailure/Report before forwarding the stamped exception to crash reporting. This restores the ALPA event and shared report marker without duplicate reports. Existing content HTTP/deserialization reporting tests retain the compatibility evidence. |
| F36 | Addressed | Fixed — Sign-out cancels outgoing auth/connectivity sources before generation-reset flags are cleared. Wave core carries its original generation into step runner and checks between dispatches and image sources. GenerationChangeBetweenSteps_StopsOutgoingWaveWithoutAnAuthEvent plus background/resume orchestration. A follow-up audit also guarded config/bulk/image/member await boundaries and ICA dispatch, passed the original generation to member steps and dynamic feed, and added AccountSwitchDuringBulkTail_DoesNotDispatchIntoTheIncomingContext at both bulk and member completion with an uncanceled caller token. |
| F37 | Addressed | Fixed — UI readiness uses volatile state flags and a double generation check without entering the cache coordinator; stale snapshot returns false. Existing readiness tests retained. |
| F38 | Addressed | Fixed: notif/list, flight notification list and createupdate upsert explicitly opt into three total attempts with two/four-second backoff plus jitter; read/upsert POST can recover one 401. Other mutation methods do not opt in. SafePost_TransientFailureRecoversWithoutDuplicatingOrdinaryMutations, updated exhaustion tests. |
| F39 | No change — refuted | Deliberate and tested (GetMemberAsync_UnauthorizedRetainsProtectedTypedError, AdditionalAllowlistCannotOverrideAuthorizationGuard); plan lines 795-796, 1074, 1823. |
| F40 | Addressed | Fixed: generic catalog failures include the operation and error code. ExceptionDispatchInfo.SetCurrentStackTrace preserves the reporting origin before Report with the actual operation caller. LegacyCatalogFailureTests verifies the operation, stack and one ALPA event on repeated reporting. |
| F41 | Addressed | Fixed: getalpano reads raw response text before decoding JSON strings; bare alphanumeric/numeric text preserves leading zeros. MemberNumber_ReadsLegacyTextWithoutLosingLeadingZeros. |
| F42 | Addressed | Fixed: Jumpseat/KCM JToken parsing explicitly uses DateParseHandling.None. KcmPublicMapCatalogue_NeverSendsMemberBearer_AndPreservesDateLookingNotes. |
| F43 | No change — refuted | App still resolves CacheContentService, which injects IDocumentsQueries (registered as DataManager), so the subscription exists before any sign-in path. |
| F44 | Addressed | Fixed: normalized flight audience identity participates in shared operation selection while the persisted key stays unchanged. Input changes retire the previous producer/memo, and producer/memo boundaries recheck identity. AudienceChange_DoesNotJoinOrPublishThePreviousAudienceFetch. |
| F45 | Addressed | Fixed — Actual registered scaffold routers resolved through RealServiceGraph with focused live ports; behavioral calls assert routing. Page-banner tester switch is changed between calls to verify live/mock/live. ServiceLayerReviewIntegrationTests.RegisteredScaffoldRouters_UseTheirLivePorts_AndBannerSwitchRemainsPerCall. |
| F46 | Addressed | Fixed — Real production ContentPrefetchCatalog executes every one of seven registered key-to-query mappings; exact invoked method checked per key. ProductionPrefetchCatalog_InvokesEveryRegisteredTargetOnItsOwningPort. |
| F47 | Addressed | Fixed: Notifications, Subscriptions and Jumpseat clients observe live endpoint snapshots, preserve v2 routes and use the same snapshot for bearer-origin validation. Behavioral endpoint-change coverage is in NotificationsApiClientTests and JumpseatAndSubscriptionsApiClientTests. Orchestration assertions now exercise background cancellation, failed-wave coalescing, guest resume, readiness and successful retry rather than weakened source-text checks. |
| F48 | No change — refuted | Infrastructure cannot reference the head model; production uses ToCriteria(); parity test is a deliberate migration guard. |
| F49 | No change — refuted | Plan's Result-plus-diagnostic contract is implemented at the port level; both crossings go through Application ports. |
| F50 | Addressed | Fixed: document download is an explicit read-only POST policy with bounded retries and one auth recovery. DownloadFailure_UsesBoundedReadPostRetryOrOneAuthRecovery. Ordinary POST replay guards remain covered. |
| F51 | Addressed | Fixed — Downloaded-file reads and catalog/disk enumeration occur outside coordinator, bracketed by generation checks. File publications/deletions remain atomic. Existing DocumentCacheServiceTests cover real disk/cache behavior. |
| F52 | Addressed | Fixed — Null document catalog evicts old persisted key instead of writing corrupt null. NullCatalogue_EvictsOldPayload_InsteadOfPersistingCorruptNull. |
| F53 | No change — refuted | No OCE source reaches the loop: token path swallows exceptions and downloads convert timeouts to Result failures. |
| F54 | No change — refuted | DocumentLogoutParticipant is in the real logout path in that test; the assertion fails if the generation does not advance. |
| F55 | Addressed | Fixed: AuthServiceCompositionTests resolves real SettingsService, PrefetchTagOptionsConfigurator and its IDocumentPrefetchConfiguration alias, options monitors, and document services with only platform leaves replaced. |
| F56 | No change — refuted | Doc discloses the device walkthrough as not run (P4-A5 row, P7-A4 open); awaited viewer behaviour is documented as deliberate. |
| F57 | Addressed | Fixed: AuthRestClient permits two transport attempts (one retry) for JWT exchange only — fewer than legacy's three because a reply lost after the server rejected a password still counts toward account lockout; HTTP status retry remains owned by Authentication to prevent nested status retry multiplication. Existing status tests still assert one raw status send. FirstTransportFailure_RecoversInsideExchangeBeforeCallerSeesFailure, NetworkFailure_ExhaustsTwoTransportAttempts_AndRemainsTransportClassifiable. |
| F58 | Addressed | Fixed — SilentLoginAsync suppresses per-attempt 500/502/504 dialogs just like 503; exhaustion retains the existing outage policy. Authentication_PublicationTests.SilentServerFailure_DoesNotShowAnInteractiveErrorPerAttempt. |
| F59 | No change — refuted | SecureMsalCache.Register is never called and UseMSAL is false, so no MSAL key exists; base never removed the MSAL account either. |
| F60 | Addressed | Fixed — SecureTokenStore and SecureCredentialStore use bounded native-write/gate waits. A timed-out write keeps exclusive ownership until its native task is observed and its late value removed; deferred clear queues behind it, so a subsequent sign-in cannot be overwritten or erased by old completion. Logout no longer waits forever on a pending token/credential publication. SecureTokenStore_ConcurrencyTests.HungWriteAndClear_TimeOutWithoutReleasingNativeIoGate_ThenEraseLateWrite; SecureCredentialStoreTests.HungPairWriteAndClear_AreBounded_AndLateCompletionCannotOverwriteNewPair. A platform keystore that never completes still cannot accept a new persisted session safely; subsequent calls fail boundedly rather than falsely claiming success. |
| F61 | Addressed | Fixed — FTDT syncing flag releases in finally after context change only when that operation acquired ownership. Existing late-success/failure tests now re-sync the same duty-period instance with a bounded wait. |
| F62 | Addressed | Fixed — ThemeCoordinator consumes its own context-invalidated resolutions as non-fatal while keeping caller cancellation unchanged; no stale theme writes. Updated ThemeContextTests assert non-fatal completion, current theme/cache preservation, and failed old secure-write rollback. |
| F63 | No change — refuted | Fixed in P6 (push started inside the same TryExecute); stuck flag sits on an outgoing in-memory instance. |
| F64 | Addressed | Fixed — New AfterCompletion logout phase starts observed anonymous push after session gates/revocation counter release. Notification anonymous registration explicitly avoids token acquisition/bearer attachment. Shared PushTokenRegistration serializes anonymous/member updates from both lifecycle effects and native callbacks and checks the queued epoch before starting, so old signed-out registration cannot overwrite the newer member's update. Authentication_PublicationTests.SlowPostLogoutPush_DoesNotBlockLogoutOrTheNextSignIn plus NotificationsService anonymous-registration test and PushTokenRegistration_OrderingTests. |
| F65 | Addressed | Fixed — App startup does not start a second logout after the auth session already rejected/revoked it. Missing credentials now queue the same guarded Session Expired recovery; locked accounts preserve AccountLocked recovery. Testable native dispatch seam verifies missing/rejected/locked recovery and suppression after a newer sign-in. Authentication_PublicationTests.MissingOrRejectedCredentials_QueuesOneRecoveryAfterRevocation, LockedAccount_QueuesAccountRecoveryAfterLogout, RejectedRecovery_DoesNotShowAfterNewSignIn. |
| F66 | Addressed | Fixed — Import self-heal preserves locally calculated Results when the server's sync response omits them. ImportSelfHeal_PreservesCalculatedResults_WhenServerOmitsThem exercises real temporary FTDT database/import/sync. |
| F67 | Addressed | Fixed — Legacy login VM shows inactive-attempt alert when publication returns false. Both success analytics/event now occur only after true publication; retained prior session no longer causes a false success event in finally. LoginPageViewModel_PublicationTests.SupersededPublication_ShowsRecoveryAndNeverReportsLoginSuccess. |
| F68 | Retained guarded behavior | Retained: StartCurrent intentionally starts synchronous effect entry under the generation barrier, with awaits outside. Moving Task.Run/Task.Yield outside would let old sign-in work capture a new member generation at FTDT/push entry. The synchronous-prefix cost remains unmeasured; a future performance change requires expected-generation effect contracts before moving that start. |
| F69 | Addressed | Fixed: AuthServiceCompositionTests builds the actual authentication, effects and logout graph and verifies all four narrow ports plus the compatibility alias resolve the same singleton. RealServiceGraph supplies isolated platform storage/preferences/files/navigation leaves. |
| F70 | Superseded | Superseded at the cumulative tip: Phase 6 removed the temporary bearer bridge. P5-A5 now explicitly records this disposition; current adapters have bearer propagation and 401 regression coverage. No intermediate bridge/device acceptance is claimed. |
| F71 | Addressed | Fixed: AuthRestClient restores the AuthenticateUser transaction through ITracer and finishes it in finally. AuthRestClientTests covers transaction completion for successful and rejected exchanges. |
| F72 | Addressed | Fixed: source and IL guards permit IAuthentication only in the concrete Authentication implementation/logger and the composition alias; new native consumers fail too. |
| F73 | Addressed | Fixed: per-record FTDT mapping reports a value-free error and continues valid records; pagination uses raw page count. Get_UnmappableRecord_DoesNotLoseValidRowsOrStopPagination. |
| F74 | Addressed | Fixed: GetMenuItemsAsync/GetFavoriteItemTypesAsync/GetFavoritesAsync ITracer spans restored; opt-in MobileMenu retry observer restores existing snackbar and ALPA debug event. ILogger retry messages identify the static operation. |
| F75 | Addressed | Fixed: MobileMenu adapter catches cancellation before Report; context invalidation derives from cancellation. CallerCancellation_IsNotStampedAsAReportedFailure. |
| F76 | Addressed | Fixed: ExistingToken bearer policy reads IAuthTokenProvider.GetCurrentToken without refresh or 401 recovery. Authentication supplies the accepted, unexpired published-session token; DynamicContent and LogApiClient select this policy. PublicFeed_NeverWaitsForTokenRefresh, BackgroundLogFlush_NeverStartsTokenAcquisition. |
| F77 | No change — refuted | Documented single-send (implementation doc lines 254, 272), plan bans write retry without a server idempotency contract; local queue retry budget is retained. Refuted 2 of 3. |
| F78 | No change — refuted | Menu_EmptyWireResponseRemainsAFailureForDomainFallback covers [], null, "" at the adapter. |
| F79 | Addressed | Fixed test gap: actual RequestProvider send boundary now tests managed, socket, timeout, canceled-native, disposed upload content and non-transient failures through production PlatformTransportErrorClassifier. Historical table remains historical, not evidence for production transport. ProductionTransport_ClassifiesFailuresAtTheActualSendBoundary. |
| F80 | Addressed | Fixed: architecture tests reject FTDT/MobileMenu generated type references in Domain, Application, Presentation and the head. Infrastructure owns their wire mapping. |
| F81 | Addressed | Fixed: removed the assertion on a snapshot captured before the failing reload. InvalidReload_ThrowsBeforeAnyClientReceivesAnInvalidSnapshot retains assertions on the current monitor validation failure and zero invalid-snapshot publications. |
| F82 | Addressed | Fixed: FlightSearchAirportLookup and MenuService_MenuItemFallbackTests replace obsolete names; runtime missing-service diagnostics name their actual ports. Historical inventory and incident references remain explicitly historical. |
| F83 | Addressed | Fixed: JumpseatResultsPage documents the actual FlightSearchService rethrow/null-result contract. |
| F84 | Addressed | Fixed — Cache/journal publication failures have a distinct classification and revoke-only logout, preserving stored credentials. Actual secure-store failures retain the AB#2220 erase-credentials policy. Authentication_PublicationTests.CleanupFailureAfterGenerationAdvance_RevokesPartialIncomingSecureState now verifies preserved credential pair. |
| F85 | Addressed | Fixed: FileSignInPublicationJournal durably flushes a non-secret pending marker before incoming JWT/MSAL identity writes; only successful final guarded cleanup/publication removes it. Startup recovery runs before token hydration and app consumers, purging persisted private state after an interrupted switch. Marker failures fail closed. SignInPublicationRecoveryTests.RestartWithPendingIdentityPublication_PurgesPersistedPrivateRowsBeforeCompletingJournal exercises persisted restart recovery. |
| F86 | Addressed | Fixed — Hydration preference scope reads lazy ISessionState.CurrentUser; FlightSearchPushNotificationService uses published session identity; unused PushNotificationHandler MemberJson read removed. No pending token-store identity reaches these consumers. |
| F87 | Addressed | Fixed — Removed abandoned explicit-epoch reset heuristic. Explicit credential publication and interactive MSAL force context reset directly; same-member silent refresh after an abandoned explicit attempt preserves cache generation. Authentication_PublicationTests.AbandonedExplicitAttempt_DoesNotPurgeTheRetainedMemberOnSilentRefresh. |
| F88 | Addressed | Fixed: ServiceLayerReviewIntegrationTests.RealSignInGraph_ClearsOutgoingRowsBeforePublishingIncomingMember_AndRejectsLateFetch composes real Authentication, AuthSessionEffects, SignInContextReset and persisted API/document stores. It waits on the document mutation gate, verifies outgoing identity remains visible while waiting, publishes incoming identity only after purge and rejects a late outgoing fetch. Only unrelated FTDT side effects are mocked. |
| F89 | Addressed | Fixed: AuthSessionEffects resets favorite hearts, hotel search state, unscoped member preferences, notification filters/sort and shortcut selection during context publication. Device environment, installation and remember-me preferences stay preserved. The real reset clears cached/PDF state; startup recovery invokes IAuthSessionEffects before identity hydration to clear preferences too. AuthMemberContextTests.PendingIdentity_UsesPublishedPreferenceScope_AndSwitchClearsUnscopedMemberChoices verifies the preference boundary. |
| F90 | Addressed | Fixed: the real DI graph test resolves each participant and checks its Phase/Order against registration metadata, including the new AfterCompletion push phase. |
| F91 | Addressed | Fixed: SharedActionsService and both Flight log-event paths resolve registered IALPALogService rather than the unregistered concrete type. |
| F92 | Addressed | Fixed — ICredentialStore.SetCredentialsAsync writes the pair behind one gate with no epoch early return between halves. Readers/clear cannot see a mixed pair. Failed second write removes both values. Timed-out pair drains and erases before releasing gate. SecureCredentialStoreTests.PairWrite_KeepsReadersAndClearBehindBothWrites and FailedSecondWrite_RemovesBothValues. |
| F93 | Addressed | Fixed: raw Installation serialization and APNS/FCM token logging are removed, including MauiProgram token/prefix output. AppProperties no longer dumps property values at initialization, omits token/JSON values in setters and uses value-free error logs. |
| F94 | Addressed | Fixed: source alias discovery normalizes global:: and recognizes aliases of nested target types. Mutation fixtures cover ordinary/global/native/nested aliases while excluding strings/comments. |
| F95 | Addressed | Fixed: the Phase 7 ratchet now requires zero active aggregate inventory entries independently of scanner equality; expanding the JSON allowlist cannot authorize a new aggregate consumer. |
| F96 | Addressed | Fixed: RemoteRawBoundaryTests inspects remote-source IL for generic JSON decoders targeting Domain models, including collection elements. Explicit embedded-asset providers are exempt because they read checked-in assets, not external responses. |
| F97 | Addressed | Fixed: SERVICE-LAYER-TEST-MIGRATION.html records removed method identifiers, current executable replacements and deliberate behavior changes; Phase 0 inventory is explicitly historical. |
| F98 | Addressed | Fixed: catalog_check scans Infrastructure/Remote plus Domain/Helpers/Constants.cs, fails on missing source targets/Postman collection, and catalog source entries name current clients. Offline regression test proves missing sources/new routes fail. |
| F99 | Addressed | Fixed: active gateway/FTDT upgrade/fault-injection instructions identify current owners; remaining historical aggregate examples carry visible migration notices with a current ownership link. |
| F100 | Addressed | Fixed: affected component specifications carry visible service-layer migration notes and current Updated timestamps. Audited stamps were preserved; this is not a layout audit. |
| F101 | Addressed | Fixed documentation milestone: the compatibility composite remains only for implementation/DI and legacy fixtures; its next removal requires migrating FakeAuthentication/legacy auth tests, then deleting compatibility methods and alias. The new ratchet forbids production growth. |
| F102 | Addressed | Fixed — Authentication's native iOS error classification calls LegacyRestNetworkErrorClassifier.IsTransientIosErrorCode; central four-code policy retained. |
| F103 | Addressed | Fixed: legacy public KCM airport host explicitly uses Bearer.None. Combined host/no-token/date-note regression test above. |
| F104 | Addressed | Fixed — Both native and Blazor environment switches await revoke-only logout before publishing changed hosts. Invalid publication attempts restore prior environment flag/endpoints. ApiEndpointOptionsTests.EnvironmentSwitch_DoesNotPublishNewEndpointsUntilLogoutCompletes exercises delayed logout before URL change. |
| F105 | Addressed | Fixed: Member/PAC mapping errors report only operation plus exception type, with no original exception attached; result messages contain no payload value. MalformedPacMember_NeverReportsPayloadValues. |
| F106 | Addressed | Fixed: DocumentLogoutParticipant acquires the document mutation gate, clears downloaded files before deleting document rows and continues catalog cleanup if file purge fails. AuthLifecycleEffectsTests.DocumentLogout_WaitsForOutgoingMutationBeforePurgingDownloadsAndCatalog guards late writes. ClearCache includes orphan category downloads; SignInContextReset atomically removes catalog-owned files before identity publication using the shared validated leaf-path helper. Tests cover orphan files, unrelated-file retention, member-switch purge and startup recovery with missing cache directories. |
| F107 | No change — refuted | Recorded as plan Q6 "Phase 3 refinement" and in implementation doc lines 130-135; routes and bodies pinned by tests. Refuted 3 of 3. |
| F108 | Addressed | Fixed: plan and Phase 0 policy matrix consistently list the explicit legacy auth-fallback exceptions, including subscriptions and airport reference data. Cancellation/context invalidation still never fall back. |
| F109 | Addressed | Fixed: Phase 5 evidence uses the exact P5-A1 through P5-A5 meanings. Device lifecycle/account-lock checks are Not run; removed bridge criterion is Superseded at the cumulative tip. |
| F110 | No change — refuted | Doc says the device walkthrough is pending and no simulator run is claimed; deadline and bearer behaviour are covered by transport tests. Refuted 2 of 3. |
| F111 | No change — refuted | Every device-gated row says "not run" or "remains pending"; P7-A4 and P7-A5 marked Open. |
| F112 | Addressed | Fixed: retry documentation lists GET defaults plus explicitly safe read/upsert POST and DELETE exceptions, the independent one-401 recovery allowance, and single-send business writes/log sink. |
| F113 | No change — refuted | Documented deviation attributed to the implementation request; plan line 964 already permits shared fixtures. |
| F114 | No change — refuted | Refuted 3 of 3: plan line 327 says to verify branch policy and use explicit review if none exists; PR 2505's body says auto-complete is disabled; CI runs on the final PR into imp/blazor-hybrid. The fact itself stands and is recorded in section 7. |
| F115 | No change — refuted | Plan line 966 mandates every phase PR opens into the integration branch; refuted 2 of 3. |
| F116 | No change — refuted | Plan requires explicit completion when no policy exists; each PR body names the merge order; refuted 2 of 3. |
| F117 | Addressed | Fixed base integration: merged app snapshots 4774e079 and 5152a5c4 into the isolated correction branch. Hunk resolutions preserve HotelDirectorySearchState DI/logout cleanup and theme placeholders while retaining captured-generation guards. Both shared stylesheet blobs match 5152a5c4 exactly. Automated validation belongs to the linked review validation record; device gates remain open. |
| F118 | No change — refuted | Workspace housekeeping, not a defect; phase5-saved holds no unpushed commits; .agents/ and .codex/ do not show as untracked. |
1eedae91)An adversarial review of the correction itself, run 2026-09-21/22 against 1eedae91 with the hand-written fix isolated by git show --remerge-diff ee7e3417, produced eleven items. All are resolved on fix/AB2081-service-layer-review-fix-01 (stacked on codex/service-layer-review-fixes at 41ec2b28). IDs are R-prefixed to keep them distinct from the original 118. Pre-existing defects the review surfaced but that predate the correction are listed after the table and belong in separate work items.
| ID | Status | Remedy and evidence |
|---|---|---|
| R01 | Addressed | Startup recovery ran RecoverAsync().GetAwaiter().GetResult() in the composition root with no catch while the session-publication.pending marker was retained by design, so one purge failure crashed every launch until reinstall. SignInPublicationRecovery.TryRecoverAsync returns the failure; MauiProgram reports it once AppServices is up and revokes the token store instead of hydrating (credentials kept, marker kept), so the launch credential check re-runs the switch as a context publication. The four early exits that left the marker pending now complete the journal. SignInPublicationRecoveryTests, Authentication_PublicationTests (journal injected). b1644573. |
| R02 | Addressed | MobileMenuApiClient.ObserveRetry called DisplaySnackbar, undoing AB#2715 (630548b3) which gated "Network issue detected. Retrying..." behind Diagnostic Mode; the test asserted the regressed call. Now DisplayDiagnosticSnackbar; MenuRetry_RestoresValueFreeNotificationAndFinishesTrace asserts zero plain snackbars. d36202df. |
| R03 | Addressed | One 30 s TotalTimeout covered every attempt, backoff and body read with no per-attempt limit; legacy gave each of three attempts its own 30 s, so a stalled socket consumed the deadline and the retry branch never ran. RequestOptions.AttemptTimeout (15 s) bounds each send through a linked token and fails as a transient transport error; TotalTimeout 60 s; MaxRetries 2 (three sends, as legacy; the prior default sent four); RetryDelay 2 s (2 s then 4 s, as legacy; the prior 200 ms default is too short for a mobile radio to recover). AuthRestClient alone caps at one retry (two sends): a reply lost after a rejected password still counts toward lockout. DocumentsApiClient.Policy keeps 30 s / 90 s because getdocuments is known to take up to 30 s. Values are to be tuned against p95/p99 latency telemetry. RequestProvider_RetryPolicyTests, DocumentsApiClientTests.Policy_*. 26d0c8e9, f967335a. |
| R04 | Not reachable | SilentLoginAsync re-captures the current generation after the MSAL step, which could send the previous member's stored credentials over a completed explicit sign-in sharing its epoch. Without MSAL nothing awaits between the generation check after the password read and the re-capture; UseMSAL is false and never set. A comment at the re-capture names the window and the guard required before enabling MSAL. 41ec2b28. |
| R05 | Addressed | CachedRemoteQuery cleared memo and in-flight work on an operationIdentity change but the persisted row is keyed by registry key alone; a failed fetch for flight audience {B} promoted {A}'s persisted list into memory as fresh. A sibling <key>#identity row records the producing identity for identity-bearing queries; a different marker discards the row on first use per generation or on change, including after restart. Rows without a marker stay compatible. NotificationsServiceTests.AudienceChange*. ac9dcf19. |
| R06 | Addressed | A refresh:true call retired an in-flight operation and every refresh:false peer received OperationCanceledException although its own token was never cancelled. SharedOperation.Successor lets the retired producer complete its waiters with the refresh result or failure. Invalidate and generation changes keep their pinned cancellation. CachedRemoteQueryTests.RefreshThatSupersedes*. 9c112512. |
| R07 | Addressed | CompleteJwtSignInAsync refusals from a secure-storage or cleanup failure showed "This sign-in attempt is no longer active", true only for supersession. Constants.MessageSignInNotCompleted replaces the literal duplicated in three view models with wording true for all three causes. 38ff64d2. |
| R08 | Addressed (pre-existing) | Sign-in never cleared web-auth cookies; only logout did (legacy 4774e079 had the same shape). Explicit sign-in over a live session bypasses logout and the auto-login WebView autofills the web form, so a surviving A-session cookie would show A's web page to B. AuthSessionEffects now clears cookies inside every context publication; RealSignInGraph_* asserts one clear per publication. 2da3bfba. |
| R09 | Addressed | Startup recovery purged caches but hydrated the secure store, so a kill after SetUserInfoJsonAsync(B) themed the logged-out UI with B's MEC and left B's token. TryRecoverAsync returns RecoveryOutcome(Interrupted, Failure); any interrupted switch revokes rather than hydrates, and the stored credentials complete the switch on the next silent refresh. a7df955c. |
| R10 | Addressed | A Retry-After beyond ~49.7 days made Task.Delay throw ArgumentOutOfRangeException out of SendRawAsync. A wait past the total deadline is now an infinite wait on the deadline token, ending as Timeout as documented. RequestProvider_RetryPolicyTests.RetryAfterBeyondTaskDelayCeiling_*. e78beb42. |
| R11 | Addressed | The real DI graph built without ValidateOnBuild/ValidateScopes; nine tests present at 6633bb59 were renamed or removed without a migration-map entry. RealServiceGraph now validates on build (five presentation/Blazor-dependent head adapters excluded by name; everything else validates clean) and the map lists the nine with their replacements. b31eb6b8. |
Pre-existing defects surfaced by the same review, outside this correction's scope:
AppProperties.Clear() leaves flightSearchPushTags and menuItemViewPreferences populated in memory because init() assigns them only when the stored string is non-empty; a logged-out notification read or push-token callback can re-send the outgoing member's tags until the next sign-in or restart.ThemeCoordinator guards on generation and cache epoch but not navigation order, so a slow EnsureThemeAsync("GLOBAL") can paint over a newer MEC page theme once per mecId per generation. Present in both merge parents of d2e6a211.Constants.cs or LoginPageViewModel.cs needs SKIP_SECRET_SCAN=1 for lines it did not introduce.The test migration map names the focused successors of removed aggregate fixtures. Architecture tests now enforce zero aggregate consumers, narrow auth consumers, raw representation mapping, generated-client containment, and guarded raw cache writes. Active runbooks use endpoint options and the current FTDT adapter; historical service names in design/spec examples are visibly labeled.
Correction cd390aee51e92219ac693bf57cbc58c367b4f26a moves explicit Blazor logout to anonymous Home after synchronous identity revocation and before background cache cleanup. The publication barrier remains closed until cleanup ends. Sixteen unit regressions (including four captured-live-menu cases) and four browser regressions cover the transition and navigation isolation; focused iOS timing and tab checks are recorded at the top of the validation record. The blank tabs observed in the synthetic run were traced to its menu fixture. Four subsequent live UAL/DAL cycles matched actual API responses without an empty bar; legitimate empty server menus retain their existing semantics. This correction remains under review; the earlier acceptance results do not automatically validate this new revision.