Service-layer review validation

Logout correction verified — 2026-09-23

Implemented in d30a8d907700b5f7f10280430ae01ea744e0f0dd and follow-up 342d355e33f57673721dbc10207e67845806e0fb. The confirmed theme-network wait is removed. Logged-out Home resolves through the existing orchestrator using cached/embedded styling, renders its content and Login action, then refreshes live theming after render. Baseline → CMS page-theme ordering remains intact. Member changes, disposal and accepted content replacement cancel the background work; theme publication checks cancellation even after a cache write. Final logout cleanup retires the interim cache generation, so its same-anonymous-context completion notification now restarts theme/content reconciliation without clearing the visible Home.

The first corrected device probe exposed that final-cleanup edge case: Home was fast but one live theme request never started. That run stopped, and the additional regression failed before the follow-up. The final candidate passed 108 focused tests, including six added cases covering pending live I/O, theme ordering, member change, disposal, cancellation during baseline/page cache writes, and cleanup completion. Normal code-commit hooks passed without bypasses. The original red TRXs and stopped device evidence are retained.

Matrix on the final code candidate

Revision 342d355e33f57673721dbc10207e67845806e0fb; source tree 70f3869ad040cbf9af5dbd7c0c40ec3d8d54726b. Target remains 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32.

Suite Passed Failed / skipped TRX SHA-256
Debug 2,985 0 / 0 7dfda93c23916c426fb2cf5f67c7c14e1117f99aaa03f32ee4966de3d2951d2b
Release 2,969 0 / 0 596104be46f8670727883d283cc38d4860e85a649161453e73d5e9e17e85fba3
DocsTests 4 0 / 0 c6b3278cba2486e975a22cf8b838b838d139cc22039e60c0830e6a50e4678b84

TRXs: theme38-matrix-debug.trx, theme38-matrix-release.trx, theme38-matrix-docs.trx. iOS Debug/Release builds: 0 errors, 650/653 warnings; Android Debug/Release: 0 errors, 676/679 warnings. Navigation is current; gateway catalog 75 routes / 0 gaps; catalog regression and 4 logout browser tests passed. The signed, nonincremental iOS acceptance build had 0 errors / 676 warnings. Installed head, executable, Presentation and Application hashes/mtimes and signature were verified before launch; the preserved signed bundle was independent of subsequent matrix build outputs.

Focused iOS device verification

Dedicated iPhone 17 Pro Max / iOS 26.5, LogoutTheme38, UDID 5F88D795-9BD2-47E1-9E28-3AA37CBA98D1. All inputs were native taps. Timing starts at the trusted click; Home means the logged-out content/Login DOM is available, not completion of separately loaded remote images. No logging-out message or visible Blazor error appeared.

Controlled GLOBAL response Home before correction (run 35) Home now Anonymous tabs now
Normal 75 ms 57 ms 69 ms
Site HTTP 200 delayed 3 s 3,057 ms 61 ms 70 ms
Theme HTTP 200 delayed 3 s 3,705 ms 54 ms 67 ms
Site HTTP 401 delayed 3 s 3,215 ms 54 ms 61 ms
Normal restored 533 ms 74 ms 88 ms

The delayed replies were recorded after Home appeared. Distinct fixture-only color values proved successful live themes actually applied after cleanup. A separate logout → DAL login → MEC navigation reached the DAL theme in 11.473 s; both old GLOBAL responses, delayed 12 s, then returned HTTP 200 without changing the DAL theme. An earlier 30 s fixture attempt hit the existing 15 s client deadline and was correctly cancelled; it was not used as evidence of a late successful response. A helper initially missed the MEC tab because it searched button,a while the actual control is a div[role=button]; the corrected driver used its real geometry/native tap. Both stopped driver attempts remain in the evidence.

Fresh live simulator AB2081-ServiceLayerIntegration01-LogoutLive37, UDID D2803ADA-1761-4B85-9DAF-4956B98FD988, used the same signed candidate with no fixture override and the approved vault accounts. Actual HTTP 200 menu responses were compared with the rendered tabs for both signed-in members and their post-logout anonymous menus:

Account Live signed-in tabs Home after logout Anonymous tabs after logout
UAL HOME, SUBMIT, JUMPSEAT, KCM, UAL MEC 24 ms 29 ms
DAL HOME, DART, JUMPSEAT, STS, DAL MEC 24 ms 33 ms

No empty bar was observed. Cold anonymous startup used the local fallback and issued no menu request in that capture; it is not claimed as a live API comparison. The first live UAL probe recorded Home at 31 ms and anonymous tabs at 36 ms, failing an old same-DOM-mutation assertion. The final checks measured both independently against the existing 250 ms paint budget, preserving that original trace. The older 1,363 ms route-navigation outlier remains unattributed; this correction specifically removes the confirmed theme dependency.

The diagnostic simulator was deleted and its fixture/automation stopped. The new live DAL simulator remains on /alpa with a settled feed, correct five-item menu and no Blazor error; its Appium/log collectors are stopped. Existing review simulators were untouched.

Evidence and review status

This run rechecked the affected iOS Home/theme/member flows. The earlier full iOS and Android walkthroughs below retain their original revisions; they were not all repeated in this correction run. Android Debug/Release builds and shared regressions passed, but this run adds no Android-device result. PR 2543 remains open for human review with auto-complete off; no votes were cast. Do not treat this record as a merge approval.

Local evidence (not uploaded CI artifacts):

Record-only DocsTests: 4 passed, zero failures/skips; theme38-record-docs.trx, SHA-256 98f285a70c7b9649f3d991872f869642ec6a425ee3c0704b5c15b9add46f3a47.

Logout content-paint investigation — 2026-09-23

Historical finding, corrected in the section above. Functional acceptance below remains recorded; at this investigation revision, complete logged-out Home was delayed when GLOBAL theme requests are slow. PR 2543 remains open with auto-complete disabled. No application code was changed in this investigation.

Candidate 8f2d6c4f5a10b7d86da87aff75080980fef24f21 differs from the full-matrix candidate f277bd9bf959e41656f2bf3fbbeab60bfb8b75d5 only in documentation. A fresh owned iPhone 17 Pro Max / iOS 26.5, AB2081-ServiceLayerIntegration01-LogoutTheme35, UDID D09DF536-2AC2-4AB7-B3C4-EC09EFB0090F, ran a signed nonincremental Debug build: 0 errors / 676 warnings. Installed head, executable and Presentation hashes/mtimes and signature matched before launch. All accounts and delayed responses were local synthetic fixtures; the live DAL review simulator was untouched.

Cause and controlled reproduction

AlpaIHomePage.LoadLoggedOutFeedAsync reads the embedded page locally, then awaits DynamicPageOrchestrator.ResolveAsync before assigning components. The orchestrator awaits ThemeCoordinator.EnsureThemeAsync, followed by the page theme when present. EnsureThemeAsync applies a local placeholder but still awaits its live resolution task. ThemeApiClient.FetchAsync resolves the GLOBAL site and its active theme through the live-first clients. Logout invalidates the memoized resolution's context, so visiting Profile beforehand does not guarantee a warm theme for the new anonymous context.

The result is a network dependency in the supposedly local-first Home paint. Navigation and anonymous tabs can already be correct while components remains null and HomeSkeleton stays visible. The 250 ms paint-wait timeout releases cleanup; it does not make the blocked content resolution complete.

Only GLOBAL site/theme response delay/status changed between these five native-tap cases:

Case Route Anonymous tabs Complete Home Largest 50 ms JS timer gap
Normal fixture responses 19 ms 23 ms 75 ms 53 ms
GLOBAL site HTTP 200 delayed 3 s 17 ms 22 ms 3,057 ms 55 ms
GLOBAL theme HTTP 200 delayed 3 s 222 ms 266 ms 3,705 ms 97 ms
GLOBAL site HTTP 401 delayed 3 s 82 ms 101 ms 3,215 ms 64 ms
Normal responses restored 94 ms 110 ms 533 ms 66 ms

In the delayed-site case, the request started 21 ms after the trusted click, returned at 3,030 ms, and Home appeared 27 ms later. CacheDatabase had already reported its security-trimmed index purge complete at 292 ms. In the delayed-theme case, the theme response arrived at 3,622 ms, 83 ms before Home. Screenshots show the skeleton and anonymous three-tab bar during the wait. No visible Blazor error or logging-out message appeared. The sampled WebView event loop continued throughout the waits; these reproductions did not show a multi-second UI-thread freeze.

This confirms a mechanism capable of producing the original live 3.5–4 s content delays. Those original cycles did not retain stage-level managed/HTTP timing, so their exact time breakdown is not reconstructed. The separate 1,363 ms UAL route-navigation outlier is not attributed by this probe; route time here was 17–222 ms.

Keep the existing orchestrator and theme coordinator as the owners. Give the logged-out initial render a genuinely local theme path using cached/embedded public styling, publish the embedded Home content immediately, and reconcile the live theme/content afterwards. Retain the current session/generation guards so a late anonymous response cannot overwrite a newly signed-in member's theme. Do not globally remove theme ordering from MEC pages.

Add a component regression that holds GLOBAL theme resolution pending and asserts that the logged-out Home and Login action render before that task is released, plus a late-result member-switch check. Existing Profile tests verify navigation/cleanup ordering and the orchestrator tests use an immediately completed theme fake; neither proves initial Home content is independent of theme I/O. After correction, repeat the delayed-site, delayed-theme and unauthorized-response cases and live UAL/DAL logout checks before clearing this concern.

Evidence: /private/tmp/AB2081-ServiceLayerIntegration01-logout-theme35/, including probe-results.json, diagnostic-summary.json, pending/complete screenshots, native logs, HTTP events, signed-bundle proof, build log and copied driver scripts. Manifest SHA-256: 9d6ca7a36db9d08fc4fb9814ca9af9ee0d7547a83dfe92d432c65531c2bc4275. The diagnostic simulator was deleted and its owned fixture, Appium and log processes stopped. These are local artifacts, not uploaded CI evidence. Documentation validation: 4 passed, zero failures/skips; logout-theme35-docs.trx, SHA-256 ccf349ada359e3fe695b1b418b301f052f234ab26a503cbcd70e86e8b8bc0c49.

Acceptance continuation completed — 2026-09-23

The user verified that Profile works and authorized continuing acceptance. Live native taps now reached Profile for both UAL and DAL (trusted click to route: 36 / 33 ms). The earlier run-32 timeout remains preserved below; its initial input delivery was not recorded, so no root cause or application correction is claimed. It is not carried forward as an unresolved walkthrough after the user's verification and this instrumented continuation.

Application candidate f277bd9bf959e41656f2bf3fbbeab60bfb8b75d5 is unchanged. Continuation branch revision b19774039a1fdb828f3e29d3cb70c42210ae9a80 adds only the previous evidence record. Target remains 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32. The full matrix recorded below remains valid: 2,979 Debug / 2,963 Release / 4 Docs, four builds with 0 errors, current navigation and 75 gateway routes / 0 gaps. No device result is inferred from a build. All applicable runbook walkthroughs are now complete on this application candidate; PR 2543 still requires human approval. No votes were cast and auto-complete remains disabled for review.

iOS completion and live menu verification

Fresh owned iPhone 17 Pro Max / iOS 26.5 MockAcceptance33, UDID C41F45E9-35B8-4FEF-ADEF-02CAF6CE6B66, completed the remaining expired-rejected-session case: exactly one refresh, one Session Expired alert, both stored credential entries removed after positive presence baselines, and no visible Blazor error. Installed signed head/executable/Presentation hashes and mtimes were checked before launch and resume. Together with controlled run 30 below, this completes the iOS runbook cases.

Live continuation 34 used the owned LiveMenu32 simulator, UDID 69C9BAC9-993F-4F64-8033-FF2D18B542E2, after rechecking its installed build. It used production API responses and approved Key Vault UAL/DAL accounts, with no fixture override. Both returned HTTP 200 menu responses (37 records), rendered the exact applicable rows, and returned to the three anonymous tabs after logout. No sampled bar was empty.

Context API-backed rendered tabs Menu HTTP duration
UAL Home, Submit, Jumpseat, KCM, UAL MEC 1,148 ms
DAL Home, DART, Jumpseat, STS, DAL MEC 1,046 ms
Anonymous after UAL / DAL Home, Jumpseat, KCM 442 / 367 ms

The four-item fallback transitioned to the authoritative five-item live menu for each MEC. The DAL bar in the controlled fixture is artificial and is not used as menu-correctness evidence. Response-body SHA-256s: UAL 7b15c9c2e5f649243ae81ddfca2e1d8f636364264d0f16655a7d439b23f14510; DAL b1f98c01c342563a6ee44ac91b05ae7d849f05ebdbf7899863726ed133f6a402; anonymous b3d67fb371f5aa2e0560b875198b4a6aa8523b6cd97fe46c8ffbd9a4e5d1a8f7.

Logout timing qualification: live UAL/DAL content paint took 4,009 / 3,514 ms. These are retained observations, not replaced by the faster diagnostic. Route/tab transition was separate: UAL 1,363 / 1,417 ms, DAL 13 / 45 ms. A standalone DAL diagnostic then showed route 15 ms, anonymous tabs 18 ms, complete anonymous Home 178 ms, with video and DOM trace retained. No lockup or logging-out message was observed. The device checks establish functional recovery; they do not establish consistently subsecond live Home content paint. The original slow samples remain available for performance review.

Both iOS drivers initially found the rendered app while the CDP bridge was not ready; relaunching the same verified bundles restored it. The controlled Appium session also needed its startup retry. These happened before the walkthroughs, required no application edits, and are retained in the driver logs.

Fresh Android acceptance

Owned Pixel 9 / API 36 AB2081-ServiceLayerIntegration01-AndroidAcceptance31, with a private ADB server and WebView 133.0.6943.137. The signed nonincremental APK was pulled back and hash-matched; its embedded ALPADocs.dll bytes/hash and build mtime were verified. Every launch/resume rechecked the installed APK. APK SHA-256: 104c35d8eb39d2a7d2c63f8bcfc191f76264dd95bd2a876b214fa7400dec6d79; embedded head DLL SHA-256: 0582147e98c54804993122ed69783a81b21c1bf12629d4d8f7952acafc74da9d. Only synthetic accounts reached the local HTTPS fixture; its CA was installed only in this disposable emulator, retaining system roots and normal TLS validation. Interactions used native taps.

Walkthrough Result
Locked / rejected sign-in One authentication request and inline error each; successful UAL recovery.
UAL → DAL / DAL → UAL isolation Outgoing menu, favorites, documents and native cookies absent; positive cookie baselines retained.
Home / theme / feed UAL #12233e → neutral placeholder → DAL #002a50, no stale outgoing theme.
Document cache Live updates, budget-one backfill, exactly two downloads, hidden AppContractLink category.
Catalogue / PDF HTTP 200 after 29.010 s; positive rendered canvas and screenshot.
FTDT Synced duty period rendered; real cumulative/duty tab taps responsive. Outage: three HTTP attempts, one native error report.
Slow logout / push Pending catalogue canceled; anonymous registration HTTP 200 with native token, not a seeded token.
Disconnected logout Connectivity positively changed Internet → None; anonymous Home returned. Remembered credentials preserved per Profile's ClearStoredCredentials=false; network restored.
Interrupted sign-in Intentional process stop during pending authentication; recovered without outgoing DAL identity or crash.
Expired success One silent refresh, Home recovered, no native session alert.
Expired locked / rejected One refresh and one appropriate native alert each; both credentials removed after positive presence baselines.
Stalled native request Attempts 14.928 / 14.929 / 14.940 s, total 51.087 s; inside 15 s / 60 s envelope.
No-logout switching N/A, confirmed by user; not an application flow.

Android trusted logout-click to anonymous-Home observations ranged 262–397 ms. No logging-out label or empty anonymous tab bar was observed. Final native crash buffer was empty; the process stayed unchanged after the one intentional interrupted-login restart. The FTDT driver initially rejected .NET seven-digit fractional timestamps. Its preserved events were read with normalized fractional precision. The streaming log repeated identical timestamped entries three times; the native log snapshot independently contained exactly one exception. The outage was not rerun. Both failed driver checks and raw records remain. The controlled iOS and Android devices and their owned fixture/driver processes were removed. The live iOS simulator remains on settled DAL Home for user review; Appium is stopped. Protected worktrees and the user's original simulator were untouched.

Continuation evidence

The final documentation record passed 4 DocsTests, zero failures/skips; acceptance34-final-docs.trx, SHA-256 95a1e97c24d04c0c2ab4ccad0f7aa684a5327a4c5c04286898a32e44ad51f25c.

Full matrix commands, counts, build results and TRX SHA-256s remain in the next section. Evidence is retained locally, not uploaded CI artifacts:

Evidence manifest SHA-256
iOS rejected expiry bd5f2a866085a4595b966db07d5baab9fe8895188baceec9458ab08eea7a55f1
Live UAL/DAL continuation 109bd0a503939836021df387e006e4d1d92bb10ff27f4a92cc2712c5823cd5fe
Android d2ee252962018f2fe2f973ae51acd65d00317cec3c0c3af6c4e48e4265c7d77d

Prior matrix and iOS acceptance pause — 2026-09-23

Historical snapshot: the continuation above supersedes this section’s remaining-work list.

Candidate f277bd9bf959e41656f2bf3fbbeab60bfb8b75d5, target 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32. Application source stayed clean and unchanged. This record supersedes earlier acceptance claims for the current candidate. PR 2543 remains gated; auto-complete stays disabled.

Full validation matrix

All Reproduction commands ran sequentially with one MSBuild worker and node reuse disabled. Full logs and unique TRXs were retained. No tests failed or were skipped.

Suite Passed TRX SHA-256
Debug 2979 candidate30-matrix-debug.trx 0c0badf251948ce8f5c3e65ab3a714c37cd84e8be60a42687680eb7d0ee15029
Release 2963 candidate30-matrix-release.trx 9038e962993bcb6271ffeb159f040daed8d4e9f7bc8fe2a27823f4d4c309c53d
Docs 4 candidate30-matrix-docs.trx 16a52623e5f9ffea26ac757e768eb61e4edaa64ad269ac221b9efe8df3a6dc8c
Build Errors Warnings Wall time
ios-debug 0 650 8.18 s
android-debug 0 676 44.2 s
ios-release 0 653 16.33 s
android-release 0 679 83.73 s

Navigation regions are current. Gateway catalog: 75 routes / 0 gaps; its regression passed (1 test). Browser logout-paint regressions: 4 passed. Additional signed iOS Debug and embedded-assembly Android Debug device builds used --no-incremental; both had 0 errors. The Android APK was built, but no Android acceptance device was launched after the iOS stop.

Controlled iOS checks completed

Dedicated iPhone 17 Pro Max / iOS 26.5 MockAcceptance30, UDID 81A41C83-448D-4D43-9BAF-C63ED69B6C31. Installed head, executable and Presentation DLL hashes/mtimes matched the signed build before launch. Installed proofs were rechecked before each explicit relaunch/resume. Only synthetic UAL/DAL accounts reached the approved local HTTPS fixture. Appium native taps, screenshots/trees and fixture requests provide evidence.

Walkthrough Result
Initial locked / rejected sign-in Passed: one request and one inline error for each; successful UAL sign-in afterwards.
UAL → DAL and DAL → UAL isolation Passed: outgoing menu, favorites, cached documents and native cookies absent after positive baselines.
Home / theme / feed recovery Passed: 20 sampled states, UAL #12233e → ALPA placeholder → DAL #002a50; no outgoing UAL brand after switch.
Document cache Passed: live cache updates, budget-one backfill, exactly two downloads, AppContractLink category hidden.
Catalogue / viewer HTTP 200 after 29.012 s; PDF visibly rendered on an 880 × 1138 canvas.
FTDT Fixture duty period rendered; native duty/cumulative taps responsive. Controlled outage: three attempts, exactly one native error report.
Interrupted sign-in Passed: killed during pending authentication; recovered to anonymous Home without outgoing identity.
Slow logout / anonymous push Passed: pending catalogue canceled, anonymous registration HTTP 200. Home DOM appeared 90 ms after the trusted click with anonymous tabs and no logging-out message.
Expired-session success Passed: one silent refresh, no alert; signed-in Home and remembered credentials retained.
Expired locked session Passed: one Login Issue alert/refresh; both credential entries removed after positive presence baselines.
Stalled request / cancellation Three native cancellations at 14.987 / 14.983 / 14.990 s, total 51.071 s.
iOS cross-host redirect Passed: initial request carried authorization; approved sink received none.
Expired rejected-session resume Not run after acceptance stopped.
No-logout switching N/A, per the user's confirmed app flow.
Android device acceptance Not started; iOS acceptance did not complete.

The slow-online case covers the runbook's slow-or-offline alternative on iOS; no disconnected iOS result is claimed. Controlled logout click-to-Home times were 64–118 ms. Secure-storage probes recorded presence booleans only. Two harness pauses were diagnosed: the expected DAL cache opt-in dialog blocked the menu hit-test, and the catalogue repaint briefly blocked the document hit-test. The visible Not Now button dismissed the dialog; the document tap waited for a reachable control. Original driver logs remain preserved.

Live API check and unresolved failure

Fresh LiveMenu32, UDID 69C9BAC9-993F-4F64-8033-FF2D18B542E2, used the same candidate with no endpoint override. Installed hashes/mtimes and signing were verified. Approved UAL credentials came from Key Vault; no vault credentials reached the fixture. Anonymous and UAL HTTP 200 responses matched the rendered bars. UAL rendered Home, Submit, Jumpseat, KCM, UAL MEC. Observed tabs changed from three anonymous items to the four-item UAL seed and then five live items, with no empty sample recorded.

At 12:39:28 UTC, the native Profile tap at (292, 89) returned success from Appium, but the app remained at /alpa; Profile did not appear within the 35-second wait. The native screenshot showed Home without an alert or visible Blazor error. The first tap had no DOM input recorder, so delivery to Blazor is unverified. A later diagnostic tap at the same coordinates recorded trusted pointerdown, pointerup and click events and reached /profile. That success does not explain or clear the initial failure. No native crash or permanent freeze is established. Cause remains unresolved; acceptance stopped rather than retrying to green. No application fix was made.

Fresh live DAL menu/logout acceptance is therefore unverified. The DAL bar seen in MockAcceptance30 (Home, Jumpseat, KCM, DAL MEC, PDR) was diagnostic fixture data, not a live DAL response or menu-correctness pass. The previous live DAL result below is historical. Remaining: diagnose the initial Profile-tap timeout, then resume live UAL/DAL cycles, expired rejected-session recovery and Android walkthroughs.

Evidence and cleanup

The documentation record passed 4 DocsTests, zero failures/skips; candidate30-acceptance-record.trx, SHA-256 7cb844256d77662c998b47524149271da0757167782b869103d32ef6d93d6917.

These are retained local artifacts, not uploaded CI evidence. The controlled simulator and fixture were deleted/stopped. The live failure simulator remains on UAL Profile for investigation, with its test driver stopped. Original review simulators and protected worktrees were untouched.

Manifest SHA-256
Matrix 6796c4939d77cbd094908ea304ee8f3530b76fe1e2f74ba996ab56d6319f7c5e
Controlled iOS a96884c6edfd24eeba02f260a5d2412243ae1ef7b0ffc59ad2aedf2338961308
Live iOS 4c0716293314f1b40fe0ea071a8ac89279d933058761f7e8d64cbf9b7ba932ac

Four-item signed-in seed — 2026-09-23

Correction bea087e699575d74902a877e1a5574390415e265 removes the disabled PDR seed slot. The fallback order is Home, Jumpseat, KCM, member MEC; the last slot retains alpa-nav-icon--mec-alpa / nav-mec-alpa.svg. Live menu responses continue to replace this fallback. Tests cover UAL, DAL and unknown-MEC labels, exact route order and the glyph.

This explicitly requested seed preview uses a synthetic UAL identity with the local menu endpoint returning 503, so a successful API response cannot replace the fallback during review. It is not a live API acceptance result. The earlier live UAL simulator/session was preserved. The narrow test simulator was deleted after verification; the wide preview AB2081-ServiceLayerIntegration01-SeedMenu28, UDID 58858044-14B9-4FB7-860C-A36FF1950EA3, remains running with the four-item bar visible.

Evidence: /private/tmp/AB2081-ServiceLayerIntegration01-seed-menu28/, including seed-393.png, seed-440.png, both geometry JSON files, installed-bundle proofs, source patch and fixture state. TRXs: /private/tmp/AB2081-seed-menu28-tests/. The unchanged application source matched the pre-commit candidate based on 30fd7e07. Normal code hooks passed; PR 2543 auto-complete remains disabled pending review.

Immediate Blazor logout and tab population — 2026-09-23

Correction cd390aee51e92219ac693bf57cbc58c367b4f26a implements the requested immediate logged-out Home transition, without a logging-out message. Live-response regressions are committed in af2d527957083354bf76b12b98442789b0f7539c. Identity, token delivery and the outgoing cache generation are revoked synchronously. Profile then navigates to anonymous Home; a bounded local paint acknowledgement precedes background cache/file cleanup. New session publication remains blocked until cleanup finishes. Native cookie work is dispatched to the UI thread; forced recovery retains its existing eager purge. The browser wait ends after two Home animation frames, backgrounding, or 250 ms; the interop call has a one-second cancellation budget. A failed transition is recorded and cannot cancel cleanup.

The bottom bar recomposes at the immediate navigation, the drawer removes outgoing rows and unread state, and late drawer responses are rejected by session epoch. Cleanup's final notification cannot redirect someone who already navigated while signed out in that epoch.

Live API verification (the acceptance reference)

At the user's request, the synthetic checks below were followed by real gateway validation with the approved UAL/DAL Key Vault test accounts. A fresh install removed synthetic state, all synthetic secure-storage entries and the endpoint override. Before launch, installed assembly mtimes/hashes and code signing matched the tested correction. The app called https://gatewayapi.alpa.org/v2/api/mobilecontent/menuitems/getallforuser directly.

The anonymous and both member responses each contained 37 top-level records. The actual server-selected bars, in order, were:

Identity Live API / rendered tabs
Anonymous Home, Jumpseat, KCM
UAL Home, Submit, Jumpseat, KCM, UAL MEC
DAL Home, DART, Jumpseat, STS, DAL MEC

Four native cycles, UAL → DAL → UAL → DAL, matched the captured HTTP 200 response for that session and the subsequent anonymous response. Logged-out Home rendered at 128 / 128 / 143 / 141 ms after trusted clicks, already with the three anonymous tabs. No empty bar was observed. The member-menu requests took 1398 / 1445 / 1282 / 1296 ms; the existing startup seed is temporary while that request completes, not the expected final tab set. The application seed behavior was not added or expanded by this correction.

Four additional regressions replay sanitized captures through the production SDK, shared transport, mapper and tab composer, including repeated logout/member cycles. They preserve every record and mapped field, assert no record is discarded, and reject anonymous-seed fallback. Wire response hashes and provenance are in UnitTest/Fixtures/LiveMenu/. The live device checks above establish current network behavior; deterministic replay alone does not. Request headers, bearer tokens and account identifiers are excluded from captures.

Live artifacts: /private/tmp/AB2081-live-menu27/, including provenance.json, live-anonymous-device.json, live-cycles.json, verified installed bundle proof, and live-review-ready-profile.png. The simulator remains signed in on the approved live UAL account, with Log Out visible. The obsolete mock server was stopped. PR auto-complete remains disabled. A harness response-parsing error stopped before submitting credentials; its failed driver log is preserved. Azure Key Vault's expired login was refreshed interactively by the user; no credential-cache inspection was performed.

Synthetic diagnostic checks (historical, not live API acceptance)

The earlier mock-menu setup returned diagnostic rows with showOnTabBar:false, replacing the startup seed with a valid empty tab set. Its first attempted tab fix also used embedded seed items instead of the SDK wire model's required children; the mapper rejected those rows. The corrected local fixture supplies three anonymous tabs and five member tabs with children:[]. These are fixture defects, not evidence that production menus intermittently return empty tabs. A legitimately empty server-selected tab set remains respected.

Dedicated iPhone 17 Pro Max / iOS 26.5, simulator 115E963D-B03F-4AB6-A7BC-FAE1E81D32C5, name AB2081-ServiceLayerIntegration01-LogoutFeedback21. The user's simulator was not changed. The signed Debug candidate was built with --no-incremental; head, executable and Presentation SHA-256/mtime matched the installed bundle before launch. Application sources were unchanged between that build and the correction commit; the source patch/manifest records the pre-commit candidate based on c1b3a990.

Check Observed result
Three one-document real-tap logouts Anonymous Home DOM at 78 / 84 / 69 ms after trusted click; next animation frame 80 / 85 / 69 ms
Three 2,048-document real-tap logouts Anonymous Home DOM at 77 / 112 / 77 ms; next animation frame 81 / 115 / 81 ms
Logout presentation No logging-out label in any run; all three anonymous tabs present at first Home render; real Login tap worked after every logout
Native video Captured and visually inspected Profile → public Home transitions, including the large-catalogue run; no persistent busy screen
Delayed menu / rapid member cycles DAL → UAL → DAL → UAL, three-second menu delay each time; initial seed populated with the incoming MEC, then five server tabs; zero empty-bar samples; three tabs after each logout
Circuit health No visible Blazor error in the measured logout or role-cycle checks
Initial mock handoff Subsequently replaced by the live-API installation and review state above

These are focused iOS checks on this correction, not a new full device-acceptance claim. Android runtime and both Release platform builds were not rerun for this correction. The exact cause of the user's originally reported intermittent freeze remains unconfirmed; this change removes the measured cleanup-dependent navigation delay. PR 2543 auto-complete remains disabled pending review and acceptance on the resulting revision. No-logout member switching remains N/A, as agreed with the user.

Regression and build evidence

Check Result Evidence
Debug unit + architecture 2,977 passed, 0 failed/skipped logout-live-final-debug.trx, SHA-256 05ce095a812ffa0e8cf188f55706df40d9f4c06382e5bbf1a157c7dc3991f540
Release unit + architecture 2,961 passed, 0 failed/skipped logout-live-final-release.trx, SHA-256 4923f2687fd5cdb365b6b2a1f93e8621970f14ae87facb69ac2384772bfe8888
Documentation 4 passed, 0 failed/skipped logout-live-final-docs.trx, SHA-256 6518f5c1650dceb372738093edee5e11b2d3161c4f290b35671b7e25ce812e3f
Browser paint regression 4 passed node --test scripts/presentation-tests/logout-navigation.test.mjs
Signed iOS Debug 0 errors ios-build.log, normal simulator signing, no incremental build
Android Debug 0 errors /private/tmp/AB2081-logout-final-android-debug.log; build only

Sixteen added unit cases include four captured-live-response regressions. The other twelve cover revoked identity before navigation, blocked session publication, background synchronous disk work, transition failure, duplicate taps, observed cleanup, epoch-scoped late navigation, retained drawer state, stale responses and native cookie dispatch. Browser tests cover paint ordering, missing render timeout and background release. An intermediate attempt moved forced recovery's purge too late and failed its existing before-await isolation test; that attempt was corrected without weakening the test. The late-navigation regression failed before the epoch guard. Unique failed TRXs remain in the local test directory. No hook bypass was used for the code commit.

Local evidence: /private/tmp/AB2081-logout-feedback-tests/ (TRXs), /private/tmp/AB2081-ios-logout26/ (fixture and driver scripts), and /private/tmp/AB2081-ServiceLayerIntegration01-mock-logout26/ (installed proof, source manifest, trusted-click timings, per-cycle logs/screenshots, role-tabs.json, logout-feedback.mp4, and review-ready-profile.png). These are local artifacts, not CI uploads. Installed head SHA-256: 6a62f57512a6211c9cbaca349f9fc008d91991fca0ed7b851b8bc9835b3e1a21; Presentation: 1645a106ecc900e86e0749963497dcff3ac20887b7f4d2e98f1b426a523c1122.

iOS Debug logout stall: bulk-cleanup correction — 2026-09-22

Correction aa9bf7829ac75afc2ee7edf69c26fa5161e9b245 follows the user's report of intermittent logout freezes on an iPhone 17 Pro Max simulator running the integration branch. PR 2543 auto-complete is disabled pending correction review and acceptance follow-up. The earlier complete device record below describes 8fb3181f, not this changed application revision.

Evidence and scope

Read-only diagnostics from the user's simulator preserved the running process (PID 35908) and installed assembly hashes. Logout began at 2026-09-23T02:20:35.954979Z; private API/search cleanup finished at 02:20:37.5458Z, clearing 2,031 security-trimmed rows. A five-second native sample at 02:22:54 found the main thread executing interpreted managed code throughout, with allocations/GC rather than a network wait. Native sampling cannot name the interpreted C# caller; no managed debugger stack was supplied, so this is not a claim that the exact user hang has been conclusively attributed to one method.

Code inspection and regression tests confirmed a matching bottleneck: ClearCacheAsync loaded the document catalogue, then called an unindexed GetDocumentByFileId for every row, even when no file was cached. This synchronous work runs before logout yields when its mutation gate is free. The 2,048-row test made 2,048 redundant queries and took 4.115 s on the desktop runtime. Reusing the captured records reduced it to 0 queries / 0.022 s. These timings are diagnostic observations, not timing-sensitive test thresholds.

Bulk and category eviction now use each snapshot row inside the existing generation guard. The public single-file operation still resolves its file ID inside that guard. No logout ordering, credential policy, publication barrier or native-cookie behavior changed. The same correction removes every catalogued publication path when multiple rows share a file ID; the old first-by-ID query could leave another publication's file behind.

Three regressions cover a large catalogue without downloads, repeated file IDs with distinct publication dates, and context invalidation before deletion. The two original regression failures were inspected before implementation; both are preserved in ios-logout-bulk-red.trx.

Validation

Check Result / SHA-256
Focused document/logout suite 260 passed before the third regression was added; ios-logout-bulk-green.trx / d567201696c077396e7ba22ad64e5f33f75bd7e32e8e671b8be30dc839e70ce5
Full Debug 2961 passed, 0 failed, 0 skipped; ios-logout-full-debug.trx / a243f937e20c4d036c335f458639a9844e14532b97b5252d0ebf37b0acd18430
Full Release 2945 passed, 0 failed, 0 skipped; ios-logout-full-release.trx / 4c1fd900097ca2bd6d86d610bd465071f4b825bd95bb1f3df1233ab2f7539bd1
iOS Debug simulator build Signed --no-incremental build, 676 warnings / 0 errors.
iPhone 17 Pro Max / iOS 26.5 Three successive 2,048-document logout runs: 1.211 / 1.299 / 1.208 s. Each showed anonymous Home, no Blazor error, and accepted a real Login tap afterwards.

Native run AB2081-ServiceLayerIntegration01-LogoutFreeze19 used a fresh owned simulator and synthetic fixture accounts only. Confirmed hydration logs establish all 2,048 rows before each logout. Installed head assembly mtime/hash and signing verified; the corrected Infrastructure assembly also matched the build: d976c7097a82bf39e9f01acfa10793e8685712f9998725f160acbe71c8b531aa. The installed binaries came from the same application source committed above; the base revision and patch are retained in the run directory. The user's simulator was neither reinstalled nor restarted. The owned simulator, fixture and Appium process were removed.

Evidence paths: /private/tmp/AB2081-ios-logout-freeze/ (live sample, bounded logs, TRXs metadata) and /private/tmp/AB2081-ServiceLayerIntegration01-mock-logout19/ (installed proof, synthetic state, native screenshots, timing results and scripts). Large-catalogue result SHA-256: 1578eac94395f005a6e076b87d581be6c6649419a47f0258d6b0b1f5f65097d9; native manifest SHA-256: bccada13322da33e372d1ee3028def5ad01752213bbf3f384b90995b42213b54. These are local artifacts, not uploaded CI evidence.

Harness setup corrections: run 18's copied fixture expected an existing endpoint and stopped before app launch; its owned simulator was deleted. Run 19 selected its listener by PID/port, because the broker shares identities between builds of the same project. The hydration-log parser was corrected for variable timestamp precision before logout measurements began.

The documentation update passed 4 DocsTests, zero failures/skips; ios-logout-correction-docs.trx SHA-256 bd6a2cd307f3e157e009a3346a6c9c2ca03afa521cf9cde3d4cb21c62c74182a. Normal code-commit hooks passed 52 architecture checks and all 2,961 Debug tests.

This focused verification does not replace the full integration acceptance matrix on the new revision. Keep auto-complete disabled while the correction is reviewed and the user's reported scenario is retested; the exact managed stack remains useful if a freeze recurs.

Reconciled device acceptance passed — 2026-09-22

All applicable runbook walkthroughs passed on application 8fb3181f1cefe66018305ac5dda917a0ec6fddfb, with documentation-only branch tip c10e6ed76ec48137e21696f9f8a3d138506949bd. iOS ran first on dedicated iPhone 15 Pro / iOS 26.5 simulator run 16; Android followed on Pixel 9 / API 36 / WebView 133 emulator run 17. These results supersede the open acceptance gates in the historical records below. No application code changed during either run.

The user-approved TLS fixture used synthetic UAL/DAL accounts only. Real native taps drove Blazor controls; native screenshots/trees verified foreground pages and alerts. No vault credentials were entered into the fixture. No-logout member switching remains N/A, as confirmed by the user. The full matrix below remains 2,958 Debug / 2,942 Release / 4 Docs, four platform builds with 0 errors, and 75 gateway routes / 0 gaps.

Walkthrough iOS run 16 Android run 17
Initial locked / rejected credentials One inline error and one authentication request for each attempt; successful UAL login afterwards. Same; requests 44 / 46 for locked / rejected.
Account switch and isolation UAL → DAL and DAL → UAL; outgoing menu, favorites and documents absent. Cookie request 272 positive, 347 absent after switch. Same; cookie request 246 positive, 331 absent after switch. Previous crash sequence passed in PID 4264.
Home / theme / feed recovery 21 captured states: UAL #12233e, ALPA placeholder, DAL #002a50; no outgoing brand retained. 17 states, same transition; delayed DAL content recovered.
Interrupted sign-in Terminated during pending authentication request 470; installed-build proof before relaunch; anonymous with no outgoing member data. Terminated during request 559; recovered without outgoing DAL identity or native crash.
Slow logout / anonymous push 0.647 s; pending catalogue request 621 canceled; anonymous registration 632 returned 200. 0.988 s; pending request 463 canceled; anonymous registration 471 returned 200. Native registration baseline established on both platforms.
Disconnected logout Slow-online alternative above fulfills the runbook; no disconnected iOS result claimed. Connectivity changed from Internet to None; logout completed in 0.899 s and showed the anonymous landing. Remembered credentials preserved by the existing Blazor policy. Network restored.
Expired-session success One silent refresh, request 703; no alert; authenticated home and credentials retained. One silent refresh, request 836; authenticated home, no Blazor error.
Expired locked / rejected session One native Login Issue / Session Expired alert, requests 810 / 911. Both stored credential entries removed after positive presence baselines. One native alert each, requests 945 / 1060; both stored credential entries removed.
Stalled request envelope Three native cancellations: 14.989 / 14.988 / 14.988 s; total 51.041 s. Three cancellations: 14.914 / 14.943 / 14.942 s; total 50.992 s.
Catalogue / document viewer Catalogue HTTP 200 after 29.008 s; downloaded PDF visibly rendered on a 786 × 1017 canvas. HTTP 200 after 29.015 s; rendered PDF canvas 824 × 1066.
Cache backfill / coalescing / live refresh Cache page updated without revisiting; budget-one backfilled the second uncached file; exactly two downloads; AppContractLink row hidden. Same behavior and exactly two downloads.
FTDT synchronization / error reporting Fixture duty period rendered; real duty/cumulative tab taps responsive. Controlled 503: three attempts, exactly one native error report. Same; no freeze or native crash.
iOS cancellation / cross-host redirect Native cancellation proved above. Request 458 carried authorization; approved sink request 460 received none. iOS-specific redirect requirement; no Android redirect claim.

Anonymous push delivery is evidenced by the slow-online case, not claimed while the network was disconnected. Secure-storage probes persisted only presence booleans. Android's final native crash buffer was empty. Its sole process restart was the intentional interrupted-login force-stop; earlier JNI-crash replay and repeated member changes completed without a crash.

Installed-artifact proof and evidence

Both device builds used --no-incremental. iOS source/installed ALPADocs.dll mtime matched at 1790126087958275286 ns and the installed signature verified. Android's pulled-back APK matched the source; the embedded DLL matched at ELF offset 16,384, source mtime 1790125809966806961 ns. Proof was checked before each explicit launch/resume.

Artifact SHA-256
iOS ALPADocs.dll c16febc8cf2779ccc7cea933efebe84db9616ccc87ae360b30ea1709c8cb2fe4
Android APK 1cafeedc688f78d8486d88e86170bbc305c21c1a2cc4721b28dedc319150b468
Android embedded ALPADocs.dll f1fdede4417e54864ca4979b1e87a3808ce9af1d02b386bf1c31c12c400ef573
iOS acceptance-summary.json 0c01e6af78705c4b791f39f0f0dcbda6478fe19cd1f021df3d7622604f2152cb
iOS hash-manifest.json 35f520c14012466da2bde7ee7a81f9978cc7341714bc90c6fe5975192123d555
Android acceptance-summary.json 8488831bdb5207419a8406e7743a99fdfe8bafa48062c1d310fc66ff6f9ddaa7
Android hash-manifest.json d71da8ca2936597d735f8b99cf09744e7c6f3cfac10799854f38f3687543cc28

Full screenshots, native trees, request/cancellation timings, logs, result JSON, scripts and hash manifests remain local under /private/tmp/AB2081-ServiceLayerIntegration01-mock-acceptance16/ and /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance17/; these are not claimed as uploaded CI artifacts. The owned simulator and emulator/AVD were deleted; fixture, capture and private ADB process exits were verified. Shared devices, shared ADB, and the protected worktrees were untouched.

Harness corrections are retained in the evidence, not counted as product failures: the iOS cookie setter was restored before proving positive/negative isolation; document category and opt-in steps were handled; native overlays were closed before underlying taps; startup waited for the existing WebView. Android's initial offline assertion incorrectly expected credential deletion: ProfilePage.razor.cs explicitly passes ClearStoredCredentials=false. The corrected check proved logout and preserved remembered credentials. Locked/rejected refresh tests separately proved deletion. Chrome's first-run overlay after help was closed only on the owned emulator, without accepting terms or adding an account.

The target remained 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32 at the final acceptance check. The acceptance-record documentation passed 4 DocsTests, with zero failures/skips: reconciled-device-acceptance-record.trx SHA-256 b33837d39ecdbfb77a015235823d3e051ec693cd0e16b22f9107240c2842fb5a.

Step 4 is complete; the final integration PR may now use default-merge auto-complete, subject to the target's required human approver. No votes were cast.

PR 2537 reconciled into service owners — 2026-09-22

Application merge 8fb3181f1cefe66018305ac5dda917a0ec6fddfb combines integration parent 719f6a8dab7670ca2a6b787164c3a4904aecedba and target 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32. The user authorized porting the new target logic after the run-15 stop. This supersedes the target-drift blocker below; the reconciled device acceptance subsequently passed as recorded above.

Resolution and correction review

Conflict / incoming behavior Resolution
Deleted DataManager.cs, changed by target Kept deleted. Ported its functional changes to the existing document services. Whitespace-only changes to removed concerns need no replacement.
Deleted DataManager_PrefetchDocumentsTests.cs, changed by target Kept deleted. Ported backfill into DocumentPrefetchService_SelectionTests and completion behavior into DocumentPrefetchCompletionTests.
Prefetch budget backfill Filter cached files before applying each category's count, preserving catalogue order and opt-out rules.
Duplicate downloads DocumentCacheService shares a lazy producer for the same file path, generation and cancellation scope. Lazy execution prevents multiple factories starting I/O under contention; conditional removal preserves newer retries. Distinct cancellation scopes remain independent.
Member isolation Retained generation checks around token acquisition, download, file publication and every joined result. A new member never joins the outgoing producer.
Tag-only cache row Exclude AppContractLink case-insensitively from visible cache groups, retaining its catalogue entry and mandatory prefetch.
Live cache refresh DocumentCatalogHydrator waits for both independently observed passes, then sends one completion through the existing messenger only if the member generation is current. Kept the incoming page subscription, renderer dispatch and dialog guards.
Retired debug tag seeding Preserved the target's disabled call by making configuration preparation inert; backend options remain authoritative.
Auto-merged cache tests Replaced legacy DataManager / CreateDataManager references with DocumentCacheService / CreateService. Kept incoming cache-view-model and page-refresh tests.
PR 2536 hotel icons / CSS Retained all four SVGs and the hotel markup/styles. CSS blob 1fff23a76b30ba857ba98d6fc64d52e1ddf7dd1a exactly matches the target; no whole-file conflict replacement was used.

Review covered retry eviction, simultaneous callers, cancellation isolation, old/new member producers, and completion timing across both pass orders. Seven expected red failures (246 passing) were recorded before the port; all 253 document-focused checks passed after. The final simultaneous-caller regression and full pre-commit run passed 2,958 tests. Normal hooks ran with no bypass: 52 architecture checks and 2,958 unit checks passed.

Reconciled validation matrix

Suite Result TRX / SHA-256
Debug 2958 passed, 0 failed, 0 skipped pr2537-matrix-debug.trx / 6ecf43d88d67fdc5f5e244e559135ed0d59d6c29c39eabdd447de444302f4e22
Release 2942 passed, 0 failed, 0 skipped pr2537-matrix-release.trx / 4aeda684797138268f71ed676142c1fc92016355e336352e97ed7043449c5590
Docs 4 passed, 0 failed, 0 skipped pr2537-matrix-docs.trx / 069e983a9fd670ea3bc1bde3b726d9be63db8ff627c17dcbeaf9f47d87cf9f10
Build Result Wall time
ios-debug 650 warnings, 0 errors 8.93 s
android-debug 702 warnings, 0 errors 151.12 s
ios-release 653 warnings, 0 errors 17.19 s
android-release 679 warnings, 0 errors 81.8 s

Android Debug used --no-incremental and embedded assemblies for installed-artifact proof. Navigation is current; gateway catalog reports 75 routes / 0 gaps, with its regression check passing. Full logs, command arrays, TRX hashes and review evidence are local artifacts under /private/tmp/AB2081-pr2537-validation/; they are not claimed as uploaded CI artifacts. The new candidate subsequently passed iOS-first and Android acceptance, recorded above. Historical device runs below are retained for traceability.

Android crash replay passed; target drift blocks integration — 2026-09-22

Application c323ac801f9d522c995c6a124384ca38d01e1e14, validation documentation eff216458cb29f065da34fc320b3bf1a1eb19842, dedicated API-36/WebView-133 run 15. The previously failing sequence now passes: UAL sign-in, live Blazor FTDT, logout, DAL sign-in and DAL home. The app remained in PID 4727 through the completed walkthroughs, with an empty native crash buffer. No new app crash was observed. All accounts/data were synthetic fixture data; no vault credentials were entered on this emulator.

Completed device evidence

Walkthrough Result
Initial locked / rejected sign-in Passed: one inline error per attempted sign-in; no Blazor error.
UAL → DAL crash replay Passed: live FTDT duty-period card, logout in 0.920 s, DAL home rendered with no outgoing UAL home text.
DAL → UAL isolation Passed: outgoing menu, favorites and document baselines established; incoming UAL menu/favorites/documents present and DAL entries absent. Native cookie check request 213 proved a stored cookie; request 310 after logout/login proved it absent. The fixture's fixed cookie label is UAL even when set during the DAL session.
MEC theme / feed recovery Passed: outgoing UAL brand #12233e, ALPA placeholder, then DAL #002a50; five captured states, no retained UAL brand. Delayed DAL site/theme responses recovered visible MEC content.
Document catalogue / viewer Passed: request 343 returned HTTP 200 after 29.009 s. The synthetic PDF downloaded and visibly rendered through the Blazor PDF canvas (824 × 1066 backing pixels), with no Blazor error.
Expired-session resume Passed: one silent successful refresh (request 537), authenticated DAL home, no sign-in prompt. Installed package proof checked before resume.
Locked refresh Passed: one Login Issue native alert, request 648; credential-presence probes were positive before and both absent after. Only presence booleans were recorded.
Rejected refresh Passed: one Session Expired native alert, request 769; both stored credential entries removed. Installed package proof checked before resume.
FTDT Sync/live card and responsive tabs passed; the duplicate-error-report assertion remains unverified in this Android run.

Two automation attempts were invalid and were not counted as product failures or passes: a favorites tap was sent during the native browser's close transition (the route remained Home); after the native screenshot proved Home was visible, a real tap opened Favorites and passed. The locked-account help action opened Chrome's first-run screen over ALPA; that obscured the next login attempt. Chrome was stopped only on this owned emulator, ALPA's native foreground was verified, and the rejected-session test then ran successfully. No Chrome account was added or terms accepted.

Stop condition and remaining work

A read-only remote check found target 2887cfb4a20c3fc4f8d2d02f4bb06cf68003db32, ahead of the already merged target 883339121ad38552980e559b10c257d0bf208c42:

git merge-tree --write-tree HEAD 2887cfb4 reports modify/delete conflicts in ALPAMobile/Services/DataManager.cs and UnitTest/DataManager_PrefetchDocumentsTests.cs. The preview did not alter the working tree or merge the target. These are new logic-porting conflicts, beyond the anticipated namespace reconciliation; further acceptance and final PR creation stopped rather than inventing a service-layer resolution.

Recommended reconciliation: compare and port PR 2537's behavior into DocumentPrefetchService (budget backfill), DocumentCacheService (download coalescing), and DocumentCatalogHydrator / catalogue projections (completion notification and tag-only category handling), preserving member-generation/cancellation boundaries. Adapt its tests to the existing service tests, retain the incoming presentation changes, and record each resolution. Restore neither the deleted DataManager nor its obsolete tests wholesale. Validate the reconciled tip before resuming device acceptance.

Still unverified on Android: interrupted sign-in after logout; the stalled-request 15-second attempt / 60-second total envelope; slow/offline logout with pending-request cancellation and anonymous push; FTDT duplicate-error-report behavior. The iOS results remain historical evidence, not a validation claim for a future reconciled candidate. No final integration PR or auto-complete was created.

Provenance and cleanup

The installed APK was pulled back and matched the --no-incremental Debug build. The embedded ALPADocs.dll matched at ELF offset 16,384, with source mtime 1790121811661383923 ns. Before each explicit launch/resume, the remote installed APK hash was checked against this proof.

Artifact SHA-256
Installed APK a4de350abad7190c85101dcbeb04cd9efcfb8dd18aba2b1ae8aad9b3cbcaf7c9
Embedded ALPADocs.dll 37bba2df89ce6c11749fe389e0fb715f61ba4bd154a98dfde4d319249f36f904
acceptance-summary.json 56eda937aa30f154409afbe66df970b314c781dfd1ed51ac7ffe145d5d128019
crash-verification-results.json 2bd6fa66058f31a15bccd3ceb9c9cf4bb51bde99000b0670c213a282fa043138
isolation-results.json 907f90da3359a324b016da17e323cf7472b01af665137e23f063e9334277fb86
delayed-catalogue-result.json 93fc58d115489dae6f400f33da85fdb38c33a8038aee7bd37b135f4370f7ca5b
theme-recovery-result.json 7870a3ac12b5487f30619ed445ba01776a763edea919d19044fddbe2471a584a
expired-session-result.json 31ded56f58153827cc631915c168c9605f560e35a87e4b7650977ea278539288
locked-session-result.json b16e051ea278aedf151da8db73f08d250195c27865727a4e995b6b60dafa739e
rejected-session-result.json 5d5d3ad37bdb4a509d0527ff836cf272a6c867954e14ec43785e8026b3d4f5a0
target-drift-merge-preview.txt 84eceb4fa63d1f0a07ea4686ba4c70fa44a9fbf60efc38dccb3a41386ac6c284
sentry-jni-replay-record-docs.trx 28ec5ab4fd522350f9a97ba70460b802076cc14dec472cc8ea2e2421f8518a0f

The acceptance-record update passed all 4 DocsTests.

Full logs, screenshots, native trees, fixture request timings, scripts and hashes are under /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance15/. The owned emulator/AVD, fixture, logcat and private ADB server were deleted; their process exits were verified. Protected worktrees and the shared ADB server were untouched.

Android post-login JNI battery race — 2026-09-22

Application correction: c323ac801f9d522c995c6a124384ca38d01e1e14.

Run 14 used display correction b29b0f9d51fa1266b6dd668c156f605c101fcf05 (docs-only tip 8fe15267fc81a2dce8b5e755584ee94772c9e351). Initial locked/rejected sign-in, UAL home and the Blazor FTDT LIVE duty-period card passed. After UAL logout, DAL sign-in crashed before DAL home appeared. The first JNI error was at 2026-09-22T23:42:50.476Z; SIGABRT followed at 23:42:51.289Z. PID 4922's .NET worker 5513 tried to delete stale JNI global reference 0x12fb2 in DeleteGlobalRef. Acceptance stopped. This disproves the earlier claim that the display fix alone cleared all post-login native crashes.

Isolation and correction

Reference traces show Sentry failed-HTTP-request enrichment calling MAUI battery reads. MAUI 10.0.60 disposes the sticky battery Intent on each read. Sentry 6.0.0 serializes its display/idiom reads but leaves battery reads concurrent.

On the dedicated API-36 device, a separate diagnostic package reproduced deleted-reference aborts with concurrent battery reads and with the actual Sentry MAUI processor. The SDK baseline also reported Intent.getIntExtra against a deleted/null reference. The production wrapper completed 16,000 calls across eight threads, asserting battery metadata and the MAUI SDK identity were retained on every call. The diagnostic process sent no events or member credentials. The run-14 tombstone has no managed owner stack; its specific stale handle cannot be mapped retrospectively, so the native reproduction and app replay are recorded separately.

The head composition applies an Android-only options post-configuration that decorates the existing SDK MAUI processor with a process-wide metadata lock. Event filtering, metadata, other processors and reporting remain enabled. The SDK processor type is internal, so the adapter uses its runtime type with Sentry's public generic removal API, without modifying private fields. A test against the installed SDK verifies replacement and idempotence; review this compatibility assumption when upgrading Sentry. iOS registration is unchanged.

The four regression tests cover concurrent calls across instances, retained/replaced/dropped events, exception recovery and actual SDK processor replacement. Before correction, 2 failed / 2 passed (255 overlapping calls, unsafe SDK processor retained); afterward, 4 passed / 0 failed. Manual review checked option-configuration order, process-wide locking, exception release, preserved SDK behavior, and Android-only registration. No independent human approval is claimed.

Evidence

Run-14 logs, tombstone, launcher screenshot, installed-build proof and failed walkthrough record are under /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance14/. That run's owned emulator/AVD, fixture, private ADB and logcat processes were deleted and exit-verified. Native diagnostic source, APK proofs, baseline/corrected logs and results are under /private/tmp/AB2081-jni-investigation/; the diagnostic imports the production wrapper source directly. sentry-evidence-hashes.json records their SHA-256s.

Evidence SHA-256
sdk-probe-logcat.log c45b8031bd147298d206d5f237d5e98154f73617dfb7b5229ab7cccceb60328b
guarded-probe-logcat.log bfef94e4fc660bb15753d7a045cf2c8be7ef8514d093f2ef0b590ab8b64c2e01
guarded-probe-result.json d7c4725b54629cac3387fbc3a75a84dea137e0a04bbc34562ff2efc1bc453bbb
sentry-jni-red.trx ef494ef09c158ab63c73d4ce09acf89371d7ce7056a8011c814b4acfad6e1dc1
sentry-jni-green.trx 1965083d62b667a65fbb0df1f48fb5f8f9cba32bb3e1c8521fcb70903e419cae

Correction validation

Debug 2,943 / Release 2,927 / Docs 4, all passed with zero failed/skipped. The normal code-commit hook also passed 2,943 tests with no bypasses.

Build Result Elapsed
ios-debug 0 errors / 676 warnings 00:00:11.69
android-debug 0 errors / 702 warnings 00:03:04.25
ios-release 0 errors / 653 warnings 00:00:16.04
android-release 0 errors / 679 warnings 00:01:36.47

Navigation generation is current; gateway catalog 75 routes / 0 gaps and its regression script passed. Full logs and command records are under /private/tmp/AB2081-jni-investigation/sentry-validation/. Android Debug was built with --no-incremental -p:EmbedAssembliesIntoApk=true before the code commit; its reviewed source is identical to that commit. The installed package and embedded DLL are checked before launch.

TRX SHA-256
sentry-jni-debug.trx b4e7cd56cea8a4ee6d47b7697d13e0a8bc96810a406a34ce6f56826e82f62508
sentry-jni-release.trx b9b9c70b185ba7b6721ecfd8c305872cb392e7440dd11978bc1516d9e0f8cd04
sentry-jni-docs.trx d03cc19f96f4b55527f50148acd25a21d4c2034007a42987b3bd2c6cc810661d

Device acceptance remains open. Run 15 is a fresh committed-candidate replay of the post-login failure; no successful walkthrough or final PR approval is claimed yet.

Android JNI display race corrected — 2026-09-22

Application correction: b29b0f9d51fa1266b6dd668c156f605c101fcf05. This corrects the reproduced display race. Run 14 exposed a second native race during post-login loading; see the newer battery-race record above. Android acceptance remains open.

Trace, reproduction and correction

Run 13 retained JNI global-reference creation/deletion stacks from the exact run-12 APK. They show both ALPA log-event creation and background Sentry event enrichment entering MAUI display reads and disposing WindowManager proxies. Ordinary sign-in replay with verbose reference tracing did not reproduce the abort; a focused concurrent-read probe did.

On the dedicated API-36 emulator, eight workers reading the original DeviceDisplay.MainDisplayInfo reproduced SIGABRT / deleted JNI global reference / GetObjectClass at 2026-09-22T23:21:12Z (PID 6293). This matches the run-12 native failure signature. The original run-12 tombstone itself has no managed method or reference-owner identity, so its individual deleted handle cannot be symbolicated retrospectively.

MAUI 10.0.60's reader disposes a shared window-service proxy on every read. Sentry 6.0.0 locks its own display reads, which does not serialize ALPA's UI-thread logging against them. A managed exception handler cannot recover from ART's native abort.

The existing head display adapter now reads Android display metadata through DisplayManager, retaining borrowed service/display wrappers and disposing only the DisplayMetrics object it allocates. Logging takes one snapshot per event; the adapter and Jumpseat sizing use the same reader. iOS retains its MAUI reader. No SDK version, Sentry reporting policy, service-layer behavior, or TLS validation was changed.

The corrected native probe completed 16,000 ALPA reads across eight workers concurrently with 2,000 original MAUI reads on a ninth worker. All 18,000 reads checked 1080 × 2424, density 2.625, portrait; all nine workers passed and the app remained alive (PID 6566). The instrumented builds used --no-incremental, had 702 warnings / 0 errors, and had installed APK / embedded DLL hashes verified before launch. Diagnostic intent handling was removed before the application commit; it is absent from the acceptance candidate.

The regression source guard failed against all four unsafe app reads before correction. Its committed Debug and Release cases prohibit reintroducing that API on Android. The normal code-commit hook passed 2,939 tests without bypasses. Manual review checked native ownership, all head display callers, unchanged dimension/orientation semantics, and removal of temporary instrumentation. No independent human approval is claimed.

Committed-code validation

Debug 2,939 / Release 2,923 / Docs 4, all passed with zero failed/skipped. These counts include both Android source-guard cases; the host suite does not execute ART/JNI.

Build Result Elapsed
ios-debug 0 errors / 650 warnings 9.66 s
android-debug 0 errors / 702 warnings 203.86 s
ios-release 0 errors / 653 warnings 17.83 s
android-release 0 errors / 679 warnings 89.7 s

Navigation generation is current; the gateway catalog remains 75 routes / 0 gaps. The gateway regression script passed. Commands are recorded in /private/tmp/AB2081-jni-investigation/matrix.json; they follow the reproduction matrix below, with unique TRXs and --no-incremental -p:EmbedAssembliesIntoApk=true for the Android Debug acceptance package. Full logs were preserved and each matrix command returned zero.

TRX SHA-256
jni-fix-final-debug.trx f3e5133ae06c6ff789073b35a268ea57b65037945cfdd3ba1a45318212cdb389
jni-fix-release.trx d051f2dbf15566bd8628157cca62d9d342257cc58ee1a08a65d4c8bd3c6c58d9
jni-fix-docs.trx bd3a582f709ac26f3457ed01a3ca35cdf32800777c3c31981b757db02e4793ed

Diagnostic evidence and reproduction

Reference traces, APK/DLL provenance, original and corrected probe patches, native abort logs, nine-worker results, and a hash manifest are preserved under /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance13/. Build/test logs, exact-version upstream sources and the corrected probe injection are under /private/tmp/AB2081-jni-investigation/.

For a diagnostic reproduction only, use an isolated checkout and disposable API-36 device: apply run 13's probe.patch to ec324a19 for the failing case. For the correction, use b29b0f9d and temporarily insert fixed-probe-injection.txt after base.OnNewIntent(intent). Build/install with the recorded commands and verify the installed APK/DLL before launching; then send the ab2081-display-probe=true intent extra to the existing activity. The baseline aborts; the corrected probe must emit nine PASS records and retain its process. These patches are diagnostics, not a production feature or an acceptance substitute.

Evidence SHA-256
probe-native-crash.txt 62833d921c768869558ab69e809b4bed84e2a6ee31ab2878e5ff45c5f0a704b4
fixed-probe-results.log c886f2c1caa623fd2ae1580ca90fb41c97234b0044ec0e47392d70cca1f8bf79
final-grefs.txt.gz 0b7677d7e63b71ed2169e100b807236f11bb00e7cb5e018a430b7dd9b7bf122d

Run 13's owned emulator/AVD, fixture, logcat and private ADB server were removed and their process exits verified. Final integration PR creation remains gated on remaining device acceptance. A fresh committed-candidate Blazor replay follows this validation record.

Fixture TLS corrected; Android stopped on native abort — 2026-09-22

Tested and pushed revision d2138bea41b17a8f3054d5f7ec205c9c5748e9f7 fixes only the Python acceptance fixture and its tests. Application code remains at correction 9089afb364b69ba670a320241e69d1fee4473203.

TLS regression and correction

The pre-fix regression reproduced starvation on both HTTPS listeners (two healthy-client handshake timeouts) and blocked shutdown (one failed assertion). All eight existing tests remained green. TLS negotiation now occurs in a dispatched request worker with a five-second handshake timeout; the listener accepts raw TCP immediately. After negotiation, the timeout is cleared so delayed HTTP acceptance scenarios retain their own timing.

13 fixture tests passed, including concurrent healthy/idle clients on both listeners, idle-handshake expiry, malformed TLS, prompt shutdown, and an HTTP body sent after the handshake timeout interval. Manual review checked socket ownership/cleanup on handshake failure and restoration of normal HTTP timing. No certificate-validation bypass was added. The full Debug unit/architecture suite passed 2,937 / 0 failed / 0 skipped; fixture-tls-regression.trx SHA-256: 6235bd87c675f7e3acfb228e12e775e8f01d8e6e88f540f853d2b0c67374405b. The fixture commit ran the normal pre-commit hook without bypasses.

Documentation verification: 4 passed / 0 failed / 0 skipped from DocsTests/DocsTests.csproj; android-acceptance12-docs.trx SHA-256: 1677506d13c5b3b11d2d6e90ff95def739a2d6cd3e949c4b98e62a99bc7cd0ac. The legacy hook's empty UnitTest Docs filter is not counted.

Android run 12

Dedicated Pixel 9 / API 36 Google APIs emulator AB2081-ServiceLayerIntegration01-AndroidAcceptance12, emulator-5590, WebView 133.0.6943.137. An owned ADB server listened only on 127.0.0.1:58744; the shared desktop server was untouched. The Debug build used --no-incremental -p:EmbedAssembliesIntoApk=true and passed with 702 warnings / 0 errors, 187.76 s. An initial ADB incremental installation could not be verified by APK pull-back; before any launch it was replaced with a full installation using --no-incremental --no-streaming. The pulled APK then matched the build byte for byte. Its embedded ALPADocs.dll matched the rebuilt DLL at ELF offset 16,384; source DLL mtime was 1790112280449435620 ns. The installed APK hash was checked again immediately before launch. The local fixture certificate was trusted only in this disposable device, retaining original roots and normal app TLS validation.

Check Result
Initial locked / rejected Blazor sign-in Passed. Requests 32 / 37 each returned one HTTP 401; one corresponding inline error, no Blazor error. Native screenshots/XML preserved.
Successful Blazor sign-in UAL home visibly rendered after request 39 returned HTTP 200. The post-login HTTP burst and ADB remained responsive. This observation is limited by the later process abort below.
FTDT import with cold airports One duty period imported: Patched(0) Inserted(1) Deleted(0) Skipped(0). Airport requests 54 / 81 / 83 returned the controlled HTTP 503. FTDT screen responsiveness was not tested before the abort.
Continued Android acceptance Stopped / incomplete after a native app abort. Account isolation, interrupted login, refresh/expiry, slow logout/push, delayed documents/viewer and FTDT UI checks remain unverified on Android.

At 21:29:46.033 UTC, Android reported JNI DETECTED ERROR IN APPLICATION: jobject is an invalid global reference (deleted reference, index 1692), in GetObjectClass on a .NET TP Worker. At 21:29:46.424 UTC the app process received SIGABRT. The stack contains ART CheckJNI and Mono runtime frames; it does not identify an application method. The process exited to the Android launcher before the next FTDT navigation command. Post-login background requests, including controlled airport failures and unconfigured catalogue routes returning 501, preceded the abort. That timing does not establish which operation owns the invalid JNI reference or whether the defect is in app, instrumentation, or runtime code. No FTDT freeze recurrence is claimed.

After the crash, the fixture health endpoint still returned HTTP 200 with normal TLS validation and the private ADB server still listed the device immediately. Thus the run 11 fixture/ADB stall did not recur. Acceptance stopped per the runbook; there was no relaunch, application patch, or retry past the native failure. Next work is to isolate the invalid JNI reference during post-login background work and review a correction before resuming. The final integration PR remains gated by incomplete Android acceptance.

Evidence, scripts, full logs, native tombstone, screenshots and SHA-256 manifest are in /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance12/. The owned emulator/AVD, fixture, logcat reader and private ADB server were removed; process termination was independently verified.

Artifact SHA-256
Installed APK 8b1fb82ee466eecd13ba7b964fc55734681e6bdf720ea7040218a5c50889b693
Embedded ALPADocs.dll 9bf9698f372e341b8d07ce7f76c1def8f30b193c928cbe61783ed2fc7bc8c56b
Pre-fix fixture regression log 1c5c184483136bcf4fb8206189255f9b746f24f8285dd07274abec01d10498b2
Passing fixture regression log 76455b20f3aabbdc8130fe33a7fe3a0a531ed501cbdcf4d023c4dc56b94d9997
Native crash buffer 104979559421793c606ab29f9f4db14c5067f4e0b49f315688e7e7f8a44399d6
Native tombstone 86fdfb5990f807a7cf82ca520862d371409bb3b9f364f93efa6296a4a0b47a11
Visible signed-in UAL home 88d916bc27b799020178fac9cbf7d9bac6611f4048d6213993ad9717fb40c7a5
Launcher after app crash b313ec18d15e0a4564ddaa3cc0c7bfd3870f91badaa7f8c52dee25f6aaea8e50

Android resumed after iOS — fixture/ADB blocker, 2026-09-22

The iOS completion below was committed first as 2706eafceb60302b5292b7ca5424e9242d459d20. A fresh Android run then used that documentation tip and unchanged application correction 9089afb364b69ba670a320241e69d1fee4473203. Per the stop rule, this run stopped at the infrastructure failure below; no application or fixture code was patched to retry it.

Dedicated emulator: AB2081-ServiceLayerIntegration01-AndroidAcceptance11, Pixel 9, API 36 Google APIs, emulator-5560. Android System WebView 133.0.6943.137 rendered the Blazor application successfully, resolving run 09's obsolete-WebView startup blocker. The self-contained Debug build used --no-incremental -p:EmbedAssembliesIntoApk=true: 702 warnings, 0 errors, 187.60 s. The installed APK was pulled back and matched byte for byte, and the embedded DLL matched the rebuilt DLL at ELF payload offset 16,384. The APK hash was checked again immediately before launch.

The local fixture CA was added only to this disposable emulator's Conscrypt trust store, retaining the original roots and app certificate validation. The Zygote mount namespace was verified before app launch. Initial HTTPS fixture requests returned HTTP 200.

Check Result
Blazor startup / native notification permission Passed. Visible anonymous Blazor home; real Allow tap. A native registration reached the mock endpoint with HTTP 200. This is not post-logout push evidence.
Initially locked credentials Passed. One POST (request 44), HTTP 401, one visible inline message advising account unlock/password reset. No native dialog or Blazor error.
Initially rejected credentials Passed. One POST (request 49), HTTP 401, one visible invalid-credentials message.
First successful sign-in / later walkthroughs Not verified. Auth request 54 returned HTTP 200; the debug bridge and reverse-forwarded HTTP traffic then stalled before the signed-in home could be verified. No FTDT navigation, account isolation, logout, expiry, interrupted sign-in or document-viewer pass is claimed for Android.

Even host-level adb devices timed out after 8 seconds, so the missing bridge response cannot establish an app freeze. A three-second read-only sample of the existing shared ADB server (PID 3642) places its main event loop in handle_packet → service_to_fd → socket_spec_connect → network_loopback_client → __connect. Its sockets show six established connections to fixture port 56572 and another SYN_SENT connection. The app and fixture logs stop at the same sign-in prefetch burst.

The fixture wraps its listening socket with TLS before ThreadingHTTPServer dispatches accepted requests. That accept-time handshake plus the backed-up reverse-connection queue is the suspected cause; it requires a focused fixture regression to prove the mechanism. Stopping only this run's mock server restored adb devices immediately, without restarting the shared ADB server. A diagnostic screenshot taken after that stop showed the signed-in UAL Blazor home. It is not a completed acceptance walkthrough or proof of its timing before the fixture stopped. No app crash or FTDT regression was established.

Recommended next work: reproduce the accept/handshake stall in the fixture, move TLS handshakes into bounded worker handling with a handshake timeout, and add a concurrent-client regression. Then resume Android on a fresh emulator, preferably with an isolated ADB server. Do not change service-layer behavior to compensate for this test infrastructure failure.

The owned emulator/AVD, mock server, log readers and blocked diagnostic client were removed; process termination was independently verified. The shared ADB server was left running. Evidence, scripts, screenshots, logs and hash manifest: /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance11/.

Artifact SHA-256
Installed APK e684d0d53f1f1410b6be69cc1516ce4a27cee51a0480e8f82afd61aa7c41c30e
Embedded ALPADocs.dll d9ca365245bbab5ea5c6d62efa8f9790e81ab9e0cb41ff724aaac3fbcc6b9912
adb-server-sample.txt 6eb4ea02e87efa6368ee0fb3481206b0a6a13e7c09ffebfcad5a29cc5b8d998a
adb-sockets.txt 5694f2a40a3346735b66ce10cd941c3f5dd3492a24e88f795c66273b71d43640
adb-after-fixture-stop.txt 439917f3fb0acdd0b46d5399817f193fe97e4f5729ff6a16e4d2072729764510

Documentation verification on 2706eafc: 4 passed, 0 failed, 0 skipped from DocsTests/DocsTests.csproj; TRX SHA-256 183b31246638ce46e50ca4c7af6dd4225b120277982c2f42b14d91e7e4b7d6e3. The legacy hook's UnitTest Docs-category filter selects zero tests and is not counted as that result. Both logs/TRXs are preserved in the iOS run 10 evidence directory. The final integration PR remains gated by unfinished Android acceptance.

Remaining iOS acceptance passed — 2026-09-22

Per the iOS-first acceptance order, the remaining isolation, theme/recovery and anonymous push checks ran on revision 5aa435f6b8fb4d4b40c73824de27c1f34330898a, application correction 9089afb364b69ba670a320241e69d1fee4473203. No application code changed. The dedicated iPhone 15 Pro / iOS 26.5 simulator was AB2081-ServiceLayerIntegration01-MockAcceptance10 (5F433A88-1F56-47FB-A372-8DC89299266A). The normal signed Debug build used --no-incremental: 676 warnings, 0 errors, 19.98 s. DLL/executable SHA-256 and nanosecond mtime matched the installed bundle before launch; strict signature verification passed. Provenance was checked again before each relaunch.

All authentication used the local HTTPS fixture's synthetic UAL/DAL identities through the Blazor login and profile/logout controls. The web-cookie probe used the app's native web viewer, opened by a real tap in the Blazor drawer. No real member data was seeded.

Check Result and evidence
Menu isolation UAL ACCEPTANCE MENU visibly present before logout; DAL ACCEPTANCE MENU replaced it after DAL login and a five-second menu response delay. No UAL row remained.
Favorites isolation UAL ACCEPTANCE FAVORITE visibly present before logout; DAL ACCEPTANCE FAVORITE only after DAL login. The fixtures reuse the favorite/menu ids to expose retained cached identity.
Document isolation UAL ACCEPTANCE DOCUMENT visibly present in the UAL category; DAL ACCEPTANCE DOCUMENT only in the DAL category after switching.
Web-cookie isolation The local viewer set a UAL cookie, then a separate request and visible page proved PRESENT. Opening only the check page after DAL login proved ABSENT. Server probe sequences 258 and 361 independently confirm present then absent.
Home/feed recovery Six distinct animation-frame states captured anonymous home, login, signing in, empty incoming home and the DAL feed. Zero states contained UAL text; no Blazor error appeared.
MEC theme recovery UAL baseline brand/accent #12233e / #f7bb0d. Delayed DAL site/theme responses produced an empty incoming MEC page with the ALPA placeholder theme, then DAL brand/accent #002a50 / #c01933 and DAL content. Four distinct captured states; zero UAL theme states. No claim about the separately filed late GLOBAL-theme race (AB#2859).
Native push prerequisite Debug skips the startup permission prompt. On the synthetic anonymous device, a fixture flight audience exposed the existing Blazor notification test page. Its real local-notification control requested permission; a native Allow tap produced NotificationPermission Authorized and Push token received. No APNS token or installation id was injected.
Slow logout and anonymous push With an actual signed-in registration (request 748, HTTP 200), document request 734 was held by the fixture's 60-second delay. Logout began 2.796 s into that request and completed in 0.656 s. The server recorded cancellation after logout began, followed by anonymous registration request 772: HTTP 200, authorization absent. The app logged registration completion.

The first push observation also proved anonymous registration, but its document request had already reached the 30-second timeout before logout; that observation is preserved separately and is not counted as the slow-logout result. The final observation above requires the request to remain within its deadline at logout and correlates its later cancellation. Actual offline logout was not separately exercised: the runbook's slow or offline alternative is satisfied by the pending-request case. This checks registration, not remote push delivery. The earlier iOS run 07 covers interrupted sign-in, rejected/locked credentials, expired-session resume, document download/open and native cancellation/redirect; run 08 covers corrected FTDT. No-logout account switching remains N/A per the user. Android acceptance remains outstanding.

iOS run 10 provenance and evidence

Installed DLL SHA-256: 58cbbd64d167c691e0f395ba55d5cb91e5eaca853ddc8dd363f8ef42ea4b5701; source/installed mtime: 1790108869598426464 ns. Executable SHA-256: 15032f9b35c4d9ad2d3fec095f56feb2de9f5c5ec162a88529e5ca7063fb29d1.

Evidence file SHA-256
switch-visible-frames.json 1f150a11e5a5d4b7bb8b72580d1c393f7abbb78bd707a6d1c833ef799464598a
cookie-isolation-result.json 8b1fe91864e3f8ed924a9e1bab5488d5627a6f638ba14d10b9b0b44cb77de048
dal-theme-transition.json 7ea0f50b9c149347dcdd438f2cf24165dc1d6df604aa941055651ca16ca92a92
slow-logout-push-result.json cc6c8d24c47114993d31c8657569eac70a9b904aebf181844ee46949ffbb8661

Screenshots, native accessibility/CDP captures, server/app logs, fixture scripts and complete SHA-256 manifest are in /private/tmp/AB2081-ServiceLayerIntegration01-mock-acceptance10/. Fixture preparation corrected missing blazor-hybrid menu metadata; unknown ancillary routes remain explicit HTTP 501 fixture gaps and are not claimed as successful service checks. The simulator was shut down and deleted; all owned server, Appium and log processes were independently verified stopped. No final PR or auto-complete was created.

Corrected FTDT acceptance — iOS passed; Android setup blocked, 2026-09-22

Acceptance resumed after review and the green matrix on branch revision 66b7af649afb9923657c4738ddd5a68012c644bb, application correction 9089afb364b69ba670a320241e69d1fee4473203. The FTDT regression and correction review are recorded in the next section.

iOS FTDT results

Dedicated simulator AB2081-ServiceLayerIntegration01-MockAcceptance08 (3F9BBC12-3AD4-4DBD-9F9B-F6732581A9F2), iPhone 15 Pro / iOS 26.5. The normal signed Debug build used --no-incremental and completed with 676 warnings / 0 errors in 20.62 s. Before launch, strict signature verification and source/installed SHA-256 and nanosecond mtime comparisons passed for the DLL and executable. All sign-ins used the local HTTPS fixture's synthetic accounts through the Blazor login form.

Walkthrough Result Evidence
FTDT import with unavailable airport metadata Passed Airport warm-up received three controlled HTTP 503 responses. FTDT independently imported one valid duty period: Patched(0) Inserted(1) Deleted(0) Skipped(0), then synchronization complete.
Cold-cache FTDT page Passed /ftdt/dashboard?tab=dp rendered the imported one-hour duty period; navigation plus screenshot/state capture took 0.975 s, no Blazor error or native alert.
Cold-cache UI responsiveness Passed Three real Appium taps expanded details, selected Cumulative Limitations and returned to Duty Periods. 190 animation frames; maximum frame gap 33 ms. No synthetic DOM click was used.
FTDT sync failure reporting Passed Controlled FTDT 503 on the next supported logout/login flow: exactly three HTTP attempts and one native System.Exception report for GetDutyPeriodsUpdatedAtAsync. No duplicate outer-layer error report, dialog or frozen page.
FTDT recovery with warm airports Passed Restored HTTP 200 airport baseline and FTDT record; supported logout/login resynchronized and rendered the duty period. A real tap opened the Blazor edit page without error.

Installed ALPADocs.dll SHA-256: 1bb1e05d1ed9b2fb84cc737df75e35ca9dd1388a702366d58134d941f55fb027; source and installed mtime: 1790107371300162488 ns. Visible cold-cache screenshot SHA-256: d9891a5798b665a5c30cdd96a2bd4c0f11655938cf517ce41ff958a9980b8e34. Error-event evidence SHA-256: a96f95b0031d9d86327c56d098cfac4d51a8cb06842365c8896f7c2e360be958.

Full screenshots, native/CDP state, request log, app log and hash manifest: /private/tmp/AB2081-ServiceLayerIntegration01-mock-acceptance08/. The simulator was shut down and deleted; its mock, Appium and log processes were independently verified stopped.

Android startup blocker — no walkthrough pass claimed

A dedicated Pixel 4 / API 30 Google APIs emulator was created as AB2081-ServiceLayerIntegration01-AndroidAcceptance09 (emulator-5560). Its self-contained Debug APK used --no-incremental -p:EmbedAssembliesIntoApk=true; 702 warnings / 0 errors, 169.16 s. The installed APK was pulled back and matched the built APK byte for byte before launch. The provenance check initially expected loose DLL entries; inspection identified .NET's ELF-wrapped lib/arm64-v8a/lib_ALPADocs.dll.so. Its payload at offset 16,384 exactly matched the rebuilt DLL; source mtime and package timestamp/hash were recorded before launch. No application or certificate-validation bypass was introduced for this packaging check.

The selected API 30 image ships Android System WebView 91.0.4472.114. Startup logcat shows Uncaught SyntaxError: Unexpected token '{' in _framework/blazor.webview.js, followed by Blazor is not defined. The visible app remains on its loading placeholder; its native process and debug HTTP server are alive, but CDP is not ready. This is a failed acceptance setup, not evidence that the FTDT correction regressed Android. No Android walkthrough ran. Per the stop rule, no application patch or repeated launch was attempted.

Next Android run must use a fresh image with a current supported WebView (the installed API 36 image is available), reestablish normal local-fixture certificate trust, and verify the installed candidate before launch. Do not count the API 30 attempt as Android acceptance.

Installed APK SHA-256: 73f97063aaf364dc5b5bcd29de610a67dae59b62f3a45d1a68b9c7d8830d0f92. Android final screenshot SHA-256: d883a05e92c62ade29e351ab736cd7191196b7f722ddcedf52accc412d7a1ac5. Startup logcat SHA-256: fc032c278767ee891ea238730dabff69b1ad84f26fccf0352cf78a294136e665. Evidence: /private/tmp/AB2081-ServiceLayerIntegration01-android-acceptance09/. The owned emulator, AVD and mock server were removed and their termination verified.

Overall acceptance remains incomplete. Android, remaining member-data/cookie isolation, and anonymous push-registration evidence still gate the final integration PR. Earlier walkthrough evidence below is historical; no-logout switching remains N/A per the user. No final integration PR or auto-complete was created.

FTDT freeze correction reviewed and validated — 2026-09-22

Application revision 9089afb364b69ba670a320241e69d1fee4473203. The user authorized isolating and correcting the FTDT freeze, reviewing the change, and then resuming acceptance. The bounded regression reproduced the blocking path before the fix: an incomplete airport request held FlightSearchAirportLookup.TryGet for the full two-second assertion window. The test releases the request in finally; the preserved red TRX reports one failure rather than leaving a hung test host. This confirms a blocking lookup, while the historical native sample still does not identify the precise managed continuation in the original device wait.

The correction adds a synchronous cache-only read to the existing IFlightSearchQueries port. The head lookup consumes the flight service's current-generation memory; it performs no authentication, persistence read or HTTP request. A cold cache follows the documented IAirportLookup absent-metadata behavior. Login warm-up remains asynchronous. Later calculations observe successful warm-up/refresh; they do not reuse a permanently empty or outgoing-member dictionary. The change does not automatically recalculate an already rendered page when warm-up finishes; ordinary subsequent calculation reads the newly available data.

Review checked the existing Application boundary, context lock/generation race, metadata mapping, null/city/code behavior, and absence of hidden background work. No blocking review finding remains. Six regressions cover cold nonblocking reads, no I/O, persisted metadata, failed-warm-up recovery, refresh and invalidation including late publication. All six pass; ten existing flight-service tests also pass. The synthetic HTTPS fixture now supplies a valid ATL airport baseline, with an explicit override for controlled failure/delay. Its eight tests pass. All code-commit hooks ran without bypass: architecture and 2,937 unit tests passed.

Correction validation matrix

The reproduction commands below ran on that committed revision with unique TRX filenames. All tests passed with zero failures/skips. All four platform builds have zero errors. Nav is current; gateway catalogue is 75 routes / 0 gaps, and its regression passed.

Check Passed / total TRX SHA-256
Debug 2937 / 2937 576b02961f228e1babfd4e7d2ca1b153510a6d83147f4363da5441e571255b75
Release 2921 / 2921 5782c12ece9b8739d243beb3fc2cd669e293b54696db87763b432444ef4b5ba4
Docs 4 / 4 415636b16f9bc8356c2c3edbe3f9051dc6acebdf2b5dbca6e5f2b0b338c59cc0
Build Warnings Errors Seconds
ios-debug 650 0 7.22
android-debug 676 0 38.4
ios-release 653 0 15.19
android-release 679 0 78.63

Full commands, logs, TRX hashes and review regression evidence are retained in /private/tmp/AB2081-ftdt-freeze/. Matrix TRXs are named ftdt-freeze-matrix-{debug,release,docs}.trx.

Device acceptance resumes on a fresh dedicated Blazor simulator after this validation record is committed. The prior acceptance tables below are historical evidence, not passes on the corrected revision. Remaining Android/isolation/push/cookie gates still block the final PR.

Continued iOS acceptance — stopped on FTDT UI freeze, 2026-09-22

Tested branch revision 3875fa5ded8861f5b81ef7a2aa20b488212489e5, with application code from e908d04ae8b228f43b824aafeb81691a248a9892. The full matrix above the historical records is green: 2,931 Debug / 2,915 Release / 4 Docs, four builds with zero errors, 75 gateway routes / 0 gaps. The mock endpoint has seven passing HTTPS fixture tests.

Acceptance is incomplete. FTDT imported one synthetic record, then the Blazor FTDT screen froze. Per the runbook, the run stopped; no service, transport or navigation fix was made. Android acceptance and the final integration PR were not started.

Walkthrough results

Walkthrough Result Device evidence / limitation
Normal Blazor UAL logout → DAL login Passed measured states Real vault roles, separate normal-endpoint device. Logout click → first anonymous frame 366 ms; Appium call 0.504 s; final DAL home present, UAL absent; no Blazor error. This is not a new frame-by-frame DAL visibility claim.
Earlier 40-second logout observation Unresolved historical observation Did not recur. Current probe recorded 691 frames, maximum gap 175 ms. The earlier delay's cause is not established.
Initial rejected / locked Blazor sign-in Passed Synthetic identities only; one auth request for each tap, one corresponding inline error, no native dialog and no Blazor error.
Expired-session resume Passed One-minute synthetic session; app backgrounded past expiry, then one successful refresh; signed-in home retained, no dialog. Native log records refresh on attempt 1.
Default stalled socket / native iOS cancellation Passed PAC GET: three canceled attempts of 14.993 / 14.988 / 14.980 s; 51.171 s total, within the 15 s / 60 s policy. No native dialog or Blazor error.
Cross-host redirect bearer handling Passed Native iOS request to fixture PAC route carried Authorization; redirected request to the second local HTTPS host did not. Both requests are in the server log.
Locked refresh recovery Passed Exactly one native Login Issue dialog; anonymous home; both synthetic secure credential entries absent after recovery.
Rejected refresh recovery Passed Exactly one native Session Expired dialog; anonymous home. Both synthetic credential entries were positively observed present before the attempt and absent afterwards; values were not recorded.
Interrupted Blazor sign-in Passed Killed after the delayed synthetic auth POST began and before any response; server observed cancellation after 0.395 s. Installed hashes/mtimes rechecked before relaunch. Settled app showed anonymous Blazor home without error.
Logout while a document request stalls Passed logout behavior 0.642 s to anonymous home; no Blazor error. Native document requests honored their separate 30 s attempt limit. Actual airplane-mode/offline behavior remains unrun.
Anonymous push re-registration Unverified No device push-token registration evidence was captured; logout completion alone does not prove this gate.
Web-cookie cleanup Unverified The synthetic document.cookie probe could not establish a nonempty baseline; no cleanup result is inferred from its empty reading.
Delayed document catalogue and viewer Passed Catalogue responded after 29.004 s (app logged 29,080 ms), hydrated one document, and displayed it in Blazor. One authenticated download returned the synthetic PDF; its text rendered in the viewer. Optional automatic downloads were declined with a real tap.
FTDT synchronization and UI Failed / stopped Import logged Patched(0) Inserted(1) Deleted(0) Skipped(0), followed by synchronization complete. Navigating to /ftdt/dashboard?tab=dp left blank content and a blocked main thread. No FTDT UI or duplicate-error-reporting pass is claimed.
No-logout switching N/A User confirmed it is not a supported app flow.
Remaining isolation / recovery and Android Not completed Remaining menu/favorites/document/cookie isolation, applicable recovery cases and Android walkthroughs remain gated after the FTDT stop.

FTDT stop: evidence and diagnosis boundary

The synthetic FTDT record was generated from the passing adapter test's Wire factory, then given current start/end timestamps, a synthetic member and a synthetic note. It was served through the real HTTP adapter, not inserted directly into a member database. At 19:40:46.832 UTC the importer logged one record; at 19:40:46.850 UTC it logged one insert and no skips. At 19:40:48.095 UTC, while entering the FTDT route, the last forward progress logs were GetCacheJSON / GetCache for GetFlightSearchAirportsAsync.

The fixture had not configured /api/FlightSearchV2/GetAirportAndCityCodes, so the earlier warm-up received its explicit 501 fixture-gap response. This missing airport baseline is a material setup limitation. The app then remained alive with a blank FTDT content area; CDP status timed out after five seconds. A five-second native process sample recorded all 4,172 main-thread samples waiting in System.Threading.Monitor / __psynch_cvwait.

ALPAMobile/Services/FlightSearchAirportLookup.cs:30 calls queries.GetAirportsAsync(false).GetAwaiter().GetResult() during cache construction. That is a plausible cold-cache deadlock trigger, consistent with the logs and native wait, not a confirmed managed stack attribution. Git blame traces the synchronous wait to bbe527426 (2026-06-22), before this integration; this run does not establish a new service-layer regression. No fix or retry past the freeze was attempted.

Next review should supply the missing airport fixture baseline and isolate the cold-cache failure path with a regression. If confirmed, airport acquisition should be asynchronous; the synchronous lookup should consume ready data without blocking the UI thread. Resume FTDT and the remaining platform gates only after the failure is reviewed and resolved.

Devices, provenance and cleanup

Both dedicated iPhone 15 Pro / iOS 26.5 simulators ran normally signed iOS Debug builds with --no-incremental, 676 warnings and zero errors. Strict signature checks and source/installed DLL plus executable hashes and mtimes passed before launch. The interruption relaunch repeated the installed-artifact check. The mock opt-in was written only to its dedicated app container; its temporary HTTPS certificate was trusted only by that simulator. No vault credentials were entered on the mock device, and the mock never proxied traffic.

Run Simulator UDID Installed ALPADocs.dll SHA-256 Matched mtime (ns)
Normal endpoints, acceptance06 0645562F-9C49-407B-9109-3F17DD128791 f9633b3c8ed099b8fe4fc9c1a579546ae55374cd888fc8d898d5b7403418cb1b 1790104591514472057
Synthetic HTTPS, acceptance07 09343244-395E-402F-BB24-46C00378AF68 2407e3fd2cf559abede91084d39a9f823a350ff995a3bc75ff198bb814c24d27 1790104887525256394

Owned Appium sessions/servers, log streams and the mock server were stopped; both dedicated simulators were deleted. Process exit and simulator deletion were verified. Other agents' devices and the three protected worktrees were untouched.

Capture setup notes: initial native navigation was unnecessary because Blazor was already mounted; the locked-account help page opened a native browser overlay that had to be closed before another login; the first post-interruption CDP read preceded WebView readiness and was replaced by a settled capture. None of those setup observations is counted as a device pass.

Local evidence directories (not uploaded CI artifacts):

Each contains evidence-sha256.json, installed-build proof, screenshots and logs. Selected failure and acceptance artifact hashes:

Evidence (acceptance07) SHA-256
server/requests.jsonl 9f149f41e7d87b66a483b86f626647e42f6a0537b3e896d0761c7afc33c5b3d0
ftdt-visible-screen.png 1a7c04062e66f82e6da7404eb0fe9e6afdf95f4255285dad8ef827f6c7dd7d65
ftdt-unresponsive-process-sample.txt f32b7e28437663b839f015f4799ba91e9f5ce9c5358eabb6a0e2e260c38b0ca9
ftdt-cdp-status.log 11234b936d01c5238b76da0f943a2a2e32e1e39696ef96d16d39561ca8d8cc64
stalled-pac-result.json 96c8f20cdf2cb89b2596198a5ccacc91609620bb7b4f358afb274d4c3b468d0b
cross-host-result.json 2145183b0302045174de8510fbd1652fcb750360545758c6a8213b160f4dc69d
locked-session-result.json ef28adf48ae61653a202c293f02b0326c1209c1543b307ad96b36fd41adb5000
rejected-session-result.json 9133578ee967210abf71e006e812784ef2a1c954788b76e9c90e758f8e3b0516
interrupted-login-result.json 5f984e91fc38f9e4eba2e44dc8a408b6b172dd905881f5b7a202fa06c87df157
delayed-catalogue-result.json 3c43f27a3868227f8161a71fcc52f5356d2653fb1ead33e68be85309af093d77
fixture-document-open-visible.png a989bf5be152045f03b611c14e7f39a7d06d75380d05b92ac7c8b320476c219b
teardown.log 92e8926be675ea691ca7a077eb45729be600e6cd90bb1f994d05855a3d608847

Controlled acceptance fixture and matrix — 2026-09-22

The user requested a mock endpoint for locked/rejected credentials, session expiry, delayed responses and cross-host redirects. Candidate e908d04ae8b228f43b824aafeb81691a248a9892 adds a loopback HTTPS fixture and an opt-in mobile Debug endpoint override through the existing ApiEndpointOptionsConfigurator. All six configured origins change together. Release has no override; a regression test checks the type is absent. Normal Debug launches with no opt-in file retain existing endpoint selection. No authentication, logout or transport implementation was changed. The no-logout UI scenario is N/A by the user's scope decision.

Fixture evidence: 7 HTTPS tests passed, including exact locked/rejected response bodies, expiry lifetime, actual delay, client disconnect detection, separate redirect sink, credential refusal/redaction, and unknown-route reporting. These validate the fixture, not device behavior. The 11 focused Debug configuration tests passed; all commit hooks ran without bypass. Setup and controls: fixture README.

Full matrix on the committed candidate (0 failures/skips):

Check Result
debug 2931 passed; acceptance-fixture-matrix-debug.trx; SHA-256 ac5c6c863de82eaf8570d499997aed311da5de46ff2f8ab0dcf02cd9a650b7f7
release 2915 passed; acceptance-fixture-matrix-release.trx; SHA-256 24c8c379ce40cb9699d6fd584de77f236005bf879ce0daa889b2d4080cabae05
docs 4 passed; acceptance-fixture-matrix-docs.trx; SHA-256 10d565e2ea3cbacbc6cabd7b41f39d040522bc8e6062abdd62257eb74ac57d27
ios-debug 0 errors, 650 warnings; 8.32 s
android-debug 0 errors, 676 warnings; 40.96 s
ios-release 0 errors, 653 warnings; 16.22 s
android-release 0 errors, 679 warnings; 83.88 s
Navigation / gateway Nav regions current; 75 routes, 0 gaps; catalogue regression 1 passed

Full logs, command records and fixture test output are retained locally under /private/tmp/AB2081-acceptance-fixture/. Matrix iOS builds disabled signing only for compilation; device deployment must rebuild normally signed with --no-incremental and prove installed SHA-256/mtime before launch. Device acceptance remains pending below.

Blazor visibility verification — logout/login passed, 2026-09-22

Tested revision: ea98fc62a2eeeeb337875d41ab5f0a065c1b3e99, with unchanged application and test sources from correction 6c729bb7f29a1143606eeb1faa3cc498302679fb. The user requested visibility verification through Blazor, then also requested no-logout verification. Those are separate results:

Scenario Result Evidence / limit
UAL → Blazor Profile → Log Out → Blazor Login → DAL Visibility passed for this recorded run Razor login → skeleton with DAL navigation → DAL home; no retained UAL content during DAL sign-in
DAL sign-in frame samples 338 callbacks; 0 UAL, 0 mixed-member, 0 Blazor errors Includes login, skeleton, and rendered DAL states
After first anonymous-home frame through DAL home 673 callbacks; 0 UAL Full probe: 793 frame callbacks and 16 mutation samples; visible UAL baseline proved the probe records outgoing content
No-logout Blazor member switch N/A — user confirmed The app requires logout before signing in as another member; signed-in /login redirects to /alpa

Device and installed-build proof

Created iPhone 15 Pro / iOS 26.5 simulator AB2081-ServiceLayerIntegration01-BlazorVisibility05, UDID 55D91888-8AA8-4096-87C8-C7D2A929417D. Normal signed iOS Debug build used --no-incremental, RuntimeIdentifier=iossimulator-arm64, MauiDevFlowPort=65036, -m:1, and -nr:false: 0 errors, 676 warnings, 20.93 seconds. Before its single launch, strict signature verification passed; both source/installed artifacts matched by SHA-256 and mtime:

Artifact SHA-256 Source and installed mtime (ns)
ALPADocs.dll f7917ef0a7dfbac2cc2bf9e67ca29d5830cf6927dee22d1a4e9efc3533aef368 1790100959043687260
ALPADocs 351cc06d646b84f11bb694abac50d855648f761344b0109b45ee36df52347f72 1790100965682419259

Walkthrough and visibility observations

UAL signed in through the actual Razor /login form using the approved vault role. After its home initialized, real Appium touches opened the Blazor Profile and activated its profile.logOutButton9. The anonymous home then opened the Razor login form, and a real login.membersLoginButton4 touch submitted DAL. No native LoginPage was invoked. The read-only DOM/frame probe remained in the same webview across this entire flow.

The logout recording contains 15 decoded frames over 40.887001 seconds. The real logout Appium call took 40.091 seconds to return. The outgoing Profile remained visible while the operation was pending, then gave way to a skeleton and anonymous home. One callback still contained outgoing Profile/navigation while the route had changed to /alpa, before the clear; it was not a DAL-session frame. The first anonymous-home callback was at 18:19:37.183 UTC; no later callback contained UAL. Sparse video and the callback gap do not establish smooth logout responsiveness or exact authentication-event timing. That delay is preserved as an observation, not retried away or asserted to be network latency.

The DAL sign-in recording contains 164 decoded frames over 4.204200 seconds. All frame contact sheets were inspected, along with the DOM trace. The first skeleton/DAL-navigation callback arrived at 18:19:43.819 UTC, followed by DAL home at 18:19:46.667 UTC. No UAL pixels were observed in the recorded DAL transition, and no Blazor error indicator was visible. These are measured results for this run, not a guarantee for every scheduling condition or a substitute for cookie, favorites, document-isolation, or Android acceptance. Credential fields and the Profile member number were masked in the videos before inspection; private unredacted recordings were deleted.

No-logout gate

On the same signed-in DAL candidate, Blazor.navigateTo('/login') was used only to check the existing route guard. Before and after: /alpa, DAL present, no login form. No logout or credential submission occurred in this guard check. Source inspection finds the existing LoginModal/ILoginModalPresenter.Open() components, but no current signed-in UI trigger.

The user subsequently confirmed no-logout switching is not applicable to this app. The gate is N/A, not a pass. No route bypass or artificial account-switch trigger is required. The supported acceptance flow is Blazor Profile logout followed by Blazor login; interrupted sign-in after logout remains applicable.

Evidence and disposition

Only this run's Appium session/server and dedicated simulator were removed; server exit and simulator deletion were verified. Local evidence directory: /private/tmp/AB2081-ServiceLayerIntegration01-blazor-visibility05/. Full frame timestamps, probe source/trace, decoded frames/contact sheets, redacted videos, installed-build proof, logs, and selected-file SHA-256 manifest are retained. No application/test source changed. Automated correction counts remain 2,920 / 2,914 / 4, all four matrix builds with zero errors, and 75 gateway routes / 0 gaps. The final PR remains gated on incomplete acceptance.

Evidence SHA-256
ios-installed-build.json 3e481438664abb3f7337f7c4af7d40f5930ef6615fe49a20df2cb0b4447118f2
visibility-trace.json 0463bf19c63f34637a466af9b2cf8ddc9deb6e0b2f042fb17cff91bfeaae4865
blazor-logout-redacted.mp4 4521f1a9fdf341966e76e6f1e3f030d00893df8d125ba109e11478624b1a69ff
blazor-dal-login-redacted.mp4 93b06122ef6edc792b9b1c794dc512719da28e9fe087191f16a58681ffb2f152
no-logout-route-guard.json 22bd3a660b2d803d417a9c5328c70feedda8fddfe7ff017775fc982e2ccc57ce
teardown.log b967b8d652f7f638db40afb522c9762c55c8dec0d7c4ff7669d1c8170b23b030

Acceptance scope correction — Blazor UI only, 2026-09-22

The user clarified that acceptance must exercise the Blazor-hybrid implementation, not legacy XAML sign-in. The earlier no-logout device reproduction invoked the registered native LoginPage through MauiDevFlow because Blazor /login redirects authenticated members home. That was an inappropriate substitution for the intended UI flow.

The visibility recording below is valid evidence of a legacy native sign-in return exposing outgoing content, but it does not establish a failure of the Blazor sign-in transition. Its prior classification as a Blazor acceptance blocker is withdrawn. The suggested neutral native cover is not an approved or required correction for this Blazor-focused task. Historical measurements remain intact, clearly scoped to the path actually exercised.

Source inspection confirms that Main.OnLocationChanged redirects authenticated /login arrivals to /alpa. The supported Profile action calls LogOutAsync, then navigates to the Blazor home; its LOGIN action opens the Razor login form. No user-facing no-logout account switch was found in that Blazor flow. Therefore:

No application code was changed or reverted for this scope correction.

Legacy native-path visibility verification — failed, 2026-09-22

Tested revision: db19d810e094a9f8dc6d20a29f977afab8ea9048. Its application/test sources are identical to correction 6c729bb7f29a1143606eeb1faa3cc498302679fb; only documentation changed after that correction. The user explicitly requested verification of the previously unresolved transient visibility. No application code or test data was modified for this run.

Legacy native-path failure: native sign-in return briefly exposes the outgoing UAL home before the skeleton is rendered. This was incorrectly treated as a Blazor acceptance result; see the scope correction above. The measurement is retained as native-path evidence only. Blazor device acceptance remains incomplete.

Build and capture identity

Created dedicated iPhone 15 Pro / iOS 26.5 simulator AB2081-ServiceLayerIntegration01-Visibility04, UDID CC14AA0B-F775-48B8-89EE-74CEEECBF1D8. The normal signed iOS Debug build used --no-incremental, RuntimeIdentifier=iossimulator-arm64, MauiDevFlowPort=61792, -m:1, and -nr:false. Result: 0 errors, 676 warnings, 26.58 s. Before its single launch, strict signature verification passed and source/installed DLL and executable hashes and nanosecond mtimes matched:

Artifact SHA-256 Source and installed mtime (ns)
ALPADocs.dll 4d1ea4c490ea47ae286a75999677969c7ab6a407a6afa2674762583429ba9c34 1790099492729417919
ALPADocs cc9acd0f7b2778c5449f4e18a22a7b59e2a56c54c0e6828730ba6eac2090bf46 1790099499395395994

UAL and DAL credentials came privately from the previously approved vault test roles. A read-only JavaScript probe recorded MutationObserver events, requestAnimationFrame samples, and Page Visibility events. A visible UAL home provided a positive control, then native LoginPage covered it. The native login was submitted through a real Appium/XCUITest touch. One setup locator failed before submission and was replaced with a verified native touch; no failed authentication was retried. The probe did not alter DOM, application state, or timing with intentional delays. Its measurement overhead is not claimed to be zero.

The native simulator recording contains 119 decoded frames over 4.741714 seconds. Credential-field bands were masked before media inspection; the unredacted raw recording was deleted. This mask leaves the native header, outgoing home heading and bottom navigation visible throughout. The recording's actual frame timestamps are retained; it is not a claimed 60 fps or exhaustive display-frame capture.

Observed transition

All clock times below are UTC from the browser trace on 2026-09-22.

Time Observation
17:57:19.068 Webview becomes visible. Its first frame callback still contains UAL feed/menu; no DAL and no skeleton.
17:57:19.117 Mutation callback contains UAL home plus DAL navigation, with visibility visible.
17:57:19.119 Outgoing feed has been cleared; DAL navigation and home skeleton are in the DOM.
17:57:19.125 First subsequent frame callback contains the skeleton and no UAL.
17:57:20.882 Frame callback contains DAL home, with no UAL and no skeleton.

The original 2 ms mixed DOM overlap was reproduced. No animation-frame callback contained both UAL and DAL, but that did not prove isolation: one callback after return still contained UAL alone. Of 330 total frame callbacks, 79 were visible UAL positive controls before re-entering native login. Of the 251 after return, 1 contained UAL, 92 the skeleton, and 158 DAL. The page was hidden between native entry and return.

Video frame 25, presentation timestamp 1.606914 s, visibly exposes a strip of the outgoing UAL page at the left edge of the native pop animation. The old welcome/contract content and PDR / SUBMIT tab are visible. Frame 26, timestamp 1.633257 s, replaces that strip with the neutral skeleton and seed navigation; DAL content arrives later. The 26.343 ms between these recorded frames is sampling evidence, not a precise bound on the stale content's total display duration. Video and frame callbacks independently confirm a visible outgoing frame, rather than merely a hidden DOM mutation.

Legacy native cause boundary and superseded recommendation

Source inspection supports a native-navigation/render ordering gap:

Earlier native-path recommendation, now outside this task's clarified scope: coordinate native return with Presentation invalidation. Keep an opaque neutral native cover over the returning webview until the outgoing member's rendered frame has been replaced by a neutral skeleton (or verified incoming-member frame), then uncover it. Do not treat Changed, StateHasChanged, authentication completion, or a fixed sleep as proof that the outgoing pixels are gone. A render acknowledgement must account for hidden-webview frame callbacks being suspended. Reuse the existing navigation/presentation boundaries, review the design, and add a transition-level regression before another device run. No service-layer patch or navigation workaround was applied during this verification.

Disposition and evidence

Legacy native-path visibility failed; Blazor account-switch visibility is unverified. Remaining controlled failure scenarios, FTDT correctness, cookie/favorites isolation, and Android acceptance were not advanced after this failure. Automated correction results remain Debug 2,920 / Release 2,914 / Docs 4, four matrix builds with zero errors, and 75 routes / 0 gaps; no source change justified rerunning that completed matrix.

Only this run's Appium session/server and dedicated simulator were torn down. Simulator removal and server exit were verified. Evidence is local under /private/tmp/AB2081-ServiceLayerIntegration01-visibility04/, with a selected-file manifest in evidence-sha256.json. The probe, complete trace, recording, frame timestamps, decoded frames, contact sheets, logs, installed-build proof, and teardown remain available locally.

Evidence SHA-256
ios-installed-build.json 71d6213848934903980b930551be43289fdab0442f80464f25c5fa0adc86006e
probe.js bd121849d212b9de5652c5a5ba13c3351cb627a19b419cc01318273b331096dd
visibility-trace.json faded0c5c1ad7a94186403560791b034d05074e62e0696ddd16cadcc89601625
visibility-transition-redacted.mp4 1ed3547f11b4b3d73139c5ee5b169b5935374121bd0a4bad8fc3a69818853fd8
video-frame-timestamps.json 70fd72515f31cc19faec4519287f06fc823ee86cfd530eb7bdc8c916661e5cd8
frames/frame-025.png 5612bf295b606e713662a53bb39f1c3eb1c564af9d3eabbc33e6b566c6ef1cf2
frames/frame-026.png 70485dff3340008ab1fb3734d862ad1f77703d42b9dd94d2988a31983183a168
teardown.log e155b3a48578c87ee294a6610bc2d94ced3012637b8920a95828fc3a020f7bf8

Member-change correction and resumed acceptance — 2026-09-22

Current application revision: 6c729bb7f29a1143606eeb1faa3cc498302679fb on imp/blazor-hybrid-service-layer-decoupling. The user approved implementing the correction and validating it before resuming acceptance. The code commit passed all applicable hooks without bypasses. This record's subsequent documentation commit changes no application code.

The retained home listened only for a boolean login transition; A-to-B sign-in publishes ISessionState.Changed while keeping IsLoggedIn true. The Presentation correction observes the published member context, clears outgoing home/menu/contract state, and prevents late outgoing async work from replacing incoming content. Same-member token refresh preserves presentation. See the investigation and regression evidence.

The persistent UAL-home reproduction was corrected through the native sign-in test path. The later native visibility failure does not establish a Blazor UI failure. Full Blazor device acceptance and the final integration PR remain gated on uncompleted walkthroughs. Historical failures and their original evidence remain below; they are not results for this corrected revision.

Correction validation matrix

The complete matrix ran before resuming acceptance. It tested staged tree 56952313552ca638d883a5da5b68ccee4b608005, based on 0cc67515d24994ef439252453caac37f51d876a0; its application and test sources match 6c729bb7. Only the investigation document differs. Fifteen added tests raise the earlier Debug/Release baselines from 2,905 / 2,899 to 2,920 / 2,914.

Check Result
Debug unit + architecture 2,920 passed, 0 failed, 0 skipped
Release unit + architecture 2,914 passed, 0 failed, 0 skipped
DocsTests 4 passed, 0 failed, 0 skipped
ios-debug 0 errors, 650 warnings; 7.56 seconds
android-debug 0 errors, 676 warnings; 37.91 seconds
ios-release 0 errors, 653 warnings; 16.38 seconds
android-release 0 errors, 679 warnings; 79.88 seconds
Navigation freshness Current
Gateway catalog 75 routes, 0 gaps; catalog regression passed
TRX SHA-256
correction-full-debug02.trx 2246b49df381e0b541bf34acb7263ef31185a0651acf3b4c774649b2ce341484
member-correction-matrix-release.trx d5d69b3502b63f9f2bb831bf8a4b4f569928767d67535b0a354422d3260912fc
member-correction-matrix-docs.trx f2a9fc8232b4aad69009827ec173a2a8cc9c7384cef6fb94ab66388106eea7b9

Commands follow the Reproduction commands section with unique TRX names. Full logs, TRXs, command metadata, and intermediate failures are preserved locally under /private/tmp/AB2081-home-member-regression/, with remaining matrix output in matrix/. The code commit's hooks independently passed the 50-test architecture subset and full 2,920-test suite. Compilation-only iOS matrix artifacts have signing disabled and were not installed for acceptance.

Corrected iOS acceptance candidate

Created dedicated iPhone 15 Pro / iOS 26.5 simulator AB2081-ServiceLayerIntegration01-iOS03, UDID EB89EAAC-A013-4CFD-8AEF-A8BB32325FA4. Built revision 6c729bb7 with normal simulator signing:

dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Debug --no-incremental \
  -p:RuntimeIdentifier=iossimulator-arm64 -p:MauiDevFlowPort=57477 -m:1 -nr:false

Before its single app launch, source and installed DLL/executable SHA-256s and nanosecond mtimes matched, and strict signature verification succeeded. Installed ALPADocs.dll: SHA-256 4333e3b022e52a70388f447f87bac0cf9cf940b4e144bd1a6a025b4b882b4c5b, source/installed mtime 1790097272649101478 ns. Installed executable: SHA-256 65c744e4d0b7ddce917c0412a5204c869d75ba0d2430128f9434ec09c40e54da, source/installed mtime 1790097278991743735 ns. No crash occurred during this walkthrough.

The approved UAL and DAL UI-test roles were read privately from . UAL signed in and initialized its home, MEC content, and United Pilot Contract (UPA23.3). The existing native LoginPage allowed DAL sign-in without logout while retaining the Blazor home. Submission and subsequent UI interactions used real Appium/XCUITest touches. On return, the visible home showed DAL MEC, DAL resources, Delta imagery, Delta PAN, and DAL navigation. Profile confirmed DAL. The drawer and MEC page showed DAL content. Opening the same AppContractLink query tag rendered the Delta Pilot Working Agreement, visually confirmed after dismissing the optional offline-download prompt. Four PDF canvases were present. No Blazor error indicator was visible in the captured pages.

A DOM mutation trace recorded a 2 ms overlap of UAL home text and DAL navigation during the native sign-in transition, followed by DAL-only content. That trace does not prove whether the underlying webview was visible for those mutations. The final visible home is correct, but this run does not establish the stricter account-isolation requirement that B never sees A, even transiently. Favorites were empty, and cookie isolation was not exercised. No synthetic member data was seeded.

Walkthrough Result on corrected revision Evidence / remaining limit
Signed iOS launch Passed Installed identity/signature verified; stable throughout walkthrough
Retained home after A → B, no logout Passed for original reproduction Returned visible home, drawer, MEC and contract all DAL; profile confirms DAL
Complete account isolation Partial 2 ms DOM overlap visibility unresolved; empty favorites and cookies do not prove isolation
Interrupted switch Not run Controlled mid-request setup not supplied
Rejected / locked credentials Not run Approved failure fixture/operator procedure pending
Slow / offline logout Not run Approved scoped network setup pending
Expired-session resume Not run Approved expiry/stalled-request setup pending
Home / theme / feed recovery Partial Correct DAL home/images observed; placeholder timing and failure recovery not fully exercised
Document viewer Partial UAL and DAL PDFs rendered; controlled 30-second catalogue delay not exercised
FTDT synchronization Not accepted Duty-period correctness and duplicate-error behavior not walked through
iOS cancellation / cross-host redirect Not run Approved controlled request/redirect setup pending
Android acceptance Not run Full cross-platform device acceptance remains open

The user was asked to identify approved backend/network fixtures or operator procedures for the remaining controlled scenarios. Normal UAL/DAL credentials do not supply those conditions. No account lockout, shared network disruption, backend mutation, or fabricated passing result was used. No final integration PR was opened.

The run's Appium session was deleted, its own server was stopped, and its dedicated simulator was shut down and deleted with teardown-sim.sh; removal was verified. No other simulator, agent, or worktree was modified. Evidence remains local under /private/tmp/AB2081-ServiceLayerIntegration01-acceptance03/; it is not an uploaded CI artifact. The complete selected-file manifest is evidence-sha256.json.

Evidence SHA-256
ios-installed-build.json 82c2251f2c626ec71b7d4dc5fce6694577fba3f7183df05ed16dd88d3e63f69d
ios-ual-switch-baseline.png 44851a2b53380da2407e384260ef6fd6f643b101d59fbb048765cbd503065e10
ios-dal-after-switch.json 9b69f3241018c3ad90c75c1f973bc20de385559ae2f01dac489a5661ef5dd012
ios-dal-after-switch.png 1351f7a983bacd6a536357ee48ad71e88d710c30638978ba5c0b30a02f2839c5
ios-dal-contract-rendered.png 772fcc27d0b1f372e2950c3cf95618d913144080eb7a4d639b658e0b9edaf0c6
ios-switch-transitions.json 0a80b8b9da4adaaee0f7d997652cd833afabdd92730d1f8a370922f3ae399c3f
teardown.log 41d5ac5a879d5afc2b97e98e41a938f6d45c2266ccf0c35950c755d8bb3857ac

Historical integration candidate validation — 2026-09-22

Tested code revision: f8f875d0bba1a5c3993c7a8b8fdbbdd126136808 on imp/blazor-hybrid-service-layer-decoupling, with SDK/workload set 10.0.400. The documentation commit carrying this record changes no application code. Automated validation passed. Corrected simulator signing now permits launch, but device acceptance failed the UAL-to-DAL account-switch check recorded below. The final PR remains blocked.

Ordered PR completion

All nine PRs completed in the required order using noFastForward merge commits, without squash, rebase, votes, policy bypasses, or source-branch deletion. After each completion the integration worktree pulled the merge and ran the full Debug suite. Every resulting tree matched that PR’s source tree exactly.

PR Merge revision Debug passed Failed Skipped
2505 92cfaec8d2e4698ff5a092862de9f7820286c08d 2080 0 0
2509 04ac24630a6a6fa3c6a8b0eaa76f55dbcaf2c02b 2177 0 0
2510 ced89ec7fa54de279ed4e98c024ce8627b691a91 2234 0 0
2511 c6291ffa245d81da1790558bb0c8d3699d2486c0 2375 0 0
2512 f4380bf95b0abfc29c69a9535f831ff56bffd9ad 2422 0 0
2513 e4660346dcdaa5c81aa85f20cb30834f2beb60f8 2473 0 0
2514 a23761a3c2cc2e7a8fef7e04fab507028ac43c7a 2587 0 0
2515 77f1a15d6ede2d91fafc5f4150855fbee4b6f8dd 2607 0 0
2527 42187343601aad7cc19bb7827b97b7ef57e53673 2905 0 0

PR 2515’s corrected baseline is 2,607, as its description and implementation record state at 6633bb59c692e81fad19fd48286bc7cf48c1fe55. The hand-off had incorrectly attributed the later review revision d2e6a211f56ce7a1808807e1f46074054c494759’s 2,887 tests to PR 2515. The user approved this correction before completion resumed. PR 2534 is already contained in PR 2527’s source ce46a36a781231503e45ebef0b43b21f49fb18cf; no extra merge was performed for it.

Reconciliation and resolutions

Reconciled matrix

Suite Passed Failed Skipped TRX
debug 2905 0 0 integration01-matrix-debug.trx
release 2899 0 0 integration01-matrix-release.trx
docs 4 0 0 integration01-matrix-docs.trx
Build Result Errors Warnings Elapsed
ios-debug Passed 0 650 14.9 s
android-debug Passed 0 676 48.5 s
ios-release Passed 0 653 20.06 s
android-release Passed 0 679 90.07 s

Navigation regions are current. Gateway catalog: 75 routes, 0 gaps; the catalog regression test passed. Full logs are retained locally under /private/tmp/AB2081-ServiceLayerIntegration01-evidence/; the first phase’s log is /private/tmp/AB2081-ServiceLayerIntegration01-pr2505-debug.log. TRXs remain in the worktree’s ignored UnitTest/TestResults/ and DocsTests/TestResults/ directories. These are local evidence files, not uploaded CI artifacts.

iOS targets iossimulator-arm64 with signing disabled; Release also disables archiving. These builds do not establish signed-device/AOT behavior or complete trimming safety.

Integration reproduction commands

Commands ran sequentially at the tested revision with one MSBuild worker and node reuse disabled, preserving complete output.

dotnet test UnitTest/UnitTest.csproj -c Debug -m:1 -nr:false --logger 'trx;LogFileName=integration01-matrix-debug.trx'
dotnet test UnitTest/UnitTest.csproj -c Release -m:1 -nr:false --logger 'trx;LogFileName=integration01-matrix-release.trx'
dotnet test DocsTests/DocsTests.csproj -c Debug -m:1 -nr:false --logger 'trx;LogFileName=integration01-matrix-docs.trx'
dotnet run docs/build-nav.cs -- --check
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Debug -m:1 -nr:false -p:RuntimeIdentifier=iossimulator-arm64 -p:EnableCodeSigning=false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-android -c Debug -m:1 -nr:false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Release -m:1 -nr:false -p:RuntimeIdentifier=iossimulator-arm64 -p:EnableCodeSigning=false -p:ArchiveOnBuild=false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-android -c Release -m:1 -nr:false
python3 scripts/gateway-readiness-check.py --catalog-check
python3 scripts/gateway-readiness/test_catalog_check.py

Integration TRX hashes

TRX SHA-256
integration01-pr2505-debug.trx 62bef3ffc10d7dda126b344655fb35158f41cda8e4794903be7591b39530ed7e
integration01-pr2509-debug.trx d11c06e9de5b5a70c11133923436d7ddc4c342924d7e3152286168f08e2a4118
integration01-pr2510-debug.trx 0d71255f553a61e892b14992891fb3169e0a1bb235c062634e001e34a8aa4638
integration01-pr2511-debug.trx 473027c8cc8fb19355c88deb88a88548e12cec9ccca5e33300bcb921d4b8f414
integration01-pr2512-debug.trx 9f80c1568aaa6221226f4ee73395514b53315dc1321e483d4f9a280f50a882bb
integration01-pr2513-debug.trx a5a49fcbc56ce071b019c0add29515b93d55b9c9705c30eda01c1dfbe2308644
integration01-pr2514-debug.trx 85ba841a97a0493c24aa9cbde0992565372cfb496b47ed81c557eaa979d7ed55
integration01-pr2515-debug.trx afba1ce4b03c0ecdaec8837b6f754e1c53c264a0299a569cd6c0529f6e9a4df8
integration01-pr2527-debug.trx ce40ab4d6f70ddc7f185593be88231e4a5752d609719083290060075df1960c5
integration01-matrix-debug.trx 6c8b03097b53cacd42c8211b2ee69daf69dc8da8e75442485ce5e2ce3cbb9e75
integration01-matrix-release.trx 1337a68df5b58929b582e96b805045f430f585955340334aed5bb0b80a9a9190
integration01-matrix-docs.trx 21a0337f02787e7271c50c52c0199ce21da2f6a2c577748d6325c177ebfdd651

Device acceptance — blocked at initial iOS launch

Candidate: 557610c9c207a5a22a0c4eaad2850cc628a23186 (documentation-only child of validated code revision f8f875d0bba1a5c3993c7a8b8fdbbdd126136808). The dedicated simulator was AB2081-ServiceLayerIntegration01-iOS, iPhone 15 Pro / iOS 26.5, UDID 351E79AF-6803-4B38-8DC8-5492D99BF557.

A fresh --no-incremental Debug simulator build succeeded with zero errors. Before launch, the installed ALPADocs.dll and native executable matched their source SHA-256s and nanosecond modification times. DLL SHA-256: 49b47a57700d9693b755cbcaaf4f6f434e78521645a7cb5b5466964898cfea6c.

Launch failed. At 12:12:04 ET on 2026-09-22, process 2428 was terminated with SIGKILL (Code Signature Invalid), termination namespace CODESIGNING, code 2, Invalid Page. The matching crash report names this simulator and installed bundle. The stack is in the native loader; no MauiDevFlow agent registered. The simulator remained booted and the screenshot shows SpringBoard. Read-only codesign --verify --deep --strict returned exit 1: code has no resources but signature indicates they must be present.

The launch build incorrectly retained -p:EnableCodeSigning=false from the compilation-only matrix. Simulator deployment signing must be corrected before a further acceptance attempt. No service-layer code was patched, no relaunch was attempted, and no test-account sign-in occurred. The UAL/DAL production UI-test account roles were identified in Key Vault, but credential values were not retrieved. Only the owned simulator was torn down after evidence capture. Android acceptance was not started because the runbook requires stopping on failure.

Walkthrough Result Evidence / reason
Initial iOS launch Failed Invalid code signature; crash report and signature check below
Account switch A → B Not run App terminated before initial sign-in
Interrupted switch Not run Stopped at launch failure
Rejected / locked credentials Not run Stopped at launch failure
Slow / offline logout Not run Stopped at launch failure
Expired-session resume Not run Stopped at launch failure
Home / theme / feed recovery Not run Stopped at launch failure
Document viewer Not run Stopped at launch failure
FTDT synchronization Not run Stopped at launch failure
iOS cancellation / cross-host redirect Not run Stopped at launch failure

Evidence is retained locally under /private/tmp/AB2081-ServiceLayerIntegration01-evidence/:

Evidence SHA-256
ALPADocs-2026-09-22-121205.ips b5c75472ec107f15fc80ae9fabcffa7eddf56608ce41e2ea3e241e8399269606
device-ios-after-crash.png 9b675b09a1b53a3a15a709539f0e416f91f67361fd616486604df6292b085f0b
device-ios-codesign-verification.log 0e28b2113f7c896d993ce4e1e3eb9b107f3d2c5521fefc4af944ffdb5e33df72
device-ios-installed-build.json 6994f1b4de2d54a968ed7bf6b405f607f8f43c2e41d408fcfb44210d59b6b648
device-ios-build.log c4749f930b60de47fd4d032a30f749ffcf8b0198ebac5d10e6c5336c0b9ad2e7

Step 4 has not passed. The final integration PR was not opened, and auto-complete was not enabled.

Previous review validation

Validated on 2026-09-22 with the repository-pinned .NET SDK/workload set 10.0.400.

Tested code revision: be3c7a102e4b7aedf15f97e6e9ce44b8ff77a84e on fix/AB2081-service-layer-review-fix-01. This includes Phase 7 6633bb59, the PR 2522 corrections, app branch snapshots 4774e079 and 5152a5c4, and the second-pass remedies R01–R11 recorded in the finding ledger (b1644573 through b31eb6b8) and the transport tuning in be3c7a10 (2 s retry base; JWT exchange capped at one retry). Every suite and build below ran at this commit from a clean worktree. The follow-up evidence commit changes documentation only. The previous record, for d2e6a211f56ce7a1808807e1f46074054c494759, is superseded by this one. PR 2534 (af15a0bc, merged into this branch as ce46a36a on 2026-09-22) is not part of this exact-revision run; its evidence is the pre-commit hook suite (Debug 2,905 passed) and the reconciliation branch's own matrix in the integration hand-off.

These are cumulative-tip results. Earlier phase counts in the implementation history remain historical and do not certify those earlier revisions for independent release. See the finding ledger for all 118 dispositions and the test migration map for removed fixture replacements.

Automated test results

Suite Passed Failed Skipped Local TRX filename
Debug unit + architecture 2904 0 0 fix01b-debug.trx
Release unit + architecture 2898 0 0 fix01b-release.trx
Documentation 4 0 0 fix01b-docs.trx

The 50-test architecture subset is included in both full suites and also ran, via the pre-commit hook, on each of the eleven remedy commits; no separate TRX is retained for it. The six-test Debug/Release difference is MockThemeApiClientTests under #if DEBUG (the mock theme client ships only in Debug); neither run skipped tests. Relative to the superseded record, Debug gained 17 tests and Release 17: the R01–R11 regression cases. The documentation result comes from DocsTests/DocsTests.csproj, independently of the legacy pre-commit Docs filter on UnitTest.

Intermediate failures were inspected in uniquely named TRX files before correction: missing-cache-directory deletion, persisted-document fixtures, an FTDT self-heal fixture, cancellation fixtures, and a composition fixture that reached portable native version tracking. The final suites above include the corrections and all new regression cases. No failing suite was bypassed or rerun without diagnosis.

The second pass had its own intermediate failures, each diagnosed before the commit that carries the fix: the first cut of the R05 identity marker discarded rows that had no marker and added a store read to ordinary keys (10 failures; the marker is now identity-bearing-only and a missing marker is compatible); R08's cookie clear tripped the throwing platform leaf in two real-graph tests (a recording port replaces it); R10's first cap raced the deadline timer (2 failures; the wait is now infinite on the token); R11's ValidateOnBuild surfaced five head adapters that depend on AddPresentation() or the Blazor host, which the graph does not compose and which are excluded by name. One commit (R07) used SKIP_SECRET_SCAN=1 because the scan flags pre-existing non-secret lines in whole staged files; the reason is in its message.

Native builds and documentation checks

Build Result Errors Warnings Elapsed
ios-debug Passed 0 650 6.6 s
android-debug Passed 0 676 39.6 s
ios-release Passed 0 653 15.1 s
android-release Passed 0 679 78.8 s

Build success is compilation/package evidence, not an on-device execution result. Both iOS builds target iossimulator-arm64 with code signing disabled; Release also disables archive creation. Android Release retains the repository's existing PublishTrimmed=false setting. These checks do not establish signed device/AOT behavior or complete trimming safety.

Additional checks:

Device acceptance resumed — account-switch failure

Resumed with user authorization on candidate 31b25f09de0a3babfb55800815a80b18758a38c7, whose application code is identical to validated revision f8f875d0bba1a5c3993c7a8b8fdbbdd126136808. The earlier signing failure above is historical; it was corrected by using normal simulator signing for deployment:

dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Debug --no-incremental \
  -p:RuntimeIdentifier=iossimulator-arm64 -p:MauiDevFlowPort=50419 -m:1 -nr:false

Result: 0 errors, 676 warnings, 16.72 seconds. The dedicated iPhone 15 Pro / iOS 26.5 simulator was AB2081-ServiceLayerIntegration01-iOS02, UDID 00912D34-2F44-429E-86BC-286263B57DD8. Before its single app launch, source and installed DLL/executable hashes and nanosecond mtimes matched; strict signature verification passed. Installed ALPADocs.dll SHA-256: 862ee8a7400f3e775c7de7d42295fc46757557c200175d80834ef73cacec71a3; source and installed mtime: 1790093815075674386 ns. No service-layer code was changed.

The user approved the UAL and DAL production UI-test roles from . Credential values were consumed privately and are excluded from this record. UAL signed in, loaded its home and MEC content, and downloaded/opened United Pilot Contract (UPA23.3). The screenshot shows the PDF rendered, not merely an opening indicator. The first-run optional automatic-download prompt was dismissed with Not Now.

Account switch failed at 12:32 ET on 2026-09-22. Reproduction and evidence:

  1. Keep UAL signed in with its home feed initialized. Do not log out.
  2. The Blazor /login route redirects an authenticated member home. Open the existing, registered native LoginPage route using MauiDevFlow, select ALPA Members, fill the approved DAL test credentials, and submit through a real Appium/XCUITest touch. This native form invokes BeginSignInAttempt and CompleteJwtSignInAsync.
  3. The log records LoginSuccessful at 16:32:07.106543Z, and native navigation returns to the existing Blazor home. The resulting visible screen still shows UAL MEC, Access UAL documents, resources, and information, and UAL home content. The DOM capture agrees with the screenshot; the Blazor error indicator is not visible.
  4. Open Profile only to identify the active session. It shows pilot group DAL and the bottom bar now shows DAL MEC, confirming that DAL authentication succeeded.

The observed failure is stale UAL presentation after successful DAL sign-in. It does not establish that DAL read UAL's persistent document store or cookies. Favorites were empty for UAL, so their isolation was not proven. Read-only source inspection identifies AlpaIHomePage.OnLoggedInChanged returning when _feedInitialized is true as a likely investigation point; root cause has not been established. The recommended owner follow-up is to trace member/session change propagation into retained home/feed/menu state, clear prior-member presentation before rendering the new member, and add a regression covering an already-mounted home during A-to-B sign-in. Do not classify this as the excluded AB#2859 late-theme race without evidence; this run observed retained UAL content.

Walkthrough Result Evidence / limit
Signed iOS launch Passed Installed identity and strict signature verified; app rendered and signed in
Account switch A → B, no logout Failed DAL session confirmed; UAL home remained visible after sign-in
Interrupted switch Not run Stopped after account-switch failure
Rejected / locked credentials Not run Stopped after account-switch failure
Slow / offline logout Not run Stopped after account-switch failure
Expired-session resume Not run Stopped after account-switch failure
Home / theme / feed recovery Failed / incomplete Stale UAL home observed; remaining recovery variants not run
Document viewer Partial UAL contract downloaded and rendered; controlled 30-second catalogue delay not exercised
FTDT synchronization Not accepted Completion message observed in sign-in logs; duty-period correctness not walked through
iOS cancellation / cross-host redirect Not run Stopped after account-switch failure
Android acceptance Not run Stopped after iOS failure

Acceptance stopped after diagnosis and evidence capture. Only this run's Appium session, server, and dedicated simulator were torn down. No service-layer patch was made and no final integration PR was opened. Automated counts remain Debug 2,905 / Release 2,899 / Docs 4, all four builds with zero errors, and 75 gateway routes / 0 gaps; no application code changed after that matrix.

Evidence is retained locally under /private/tmp/AB2081-ServiceLayerIntegration01-acceptance02/:

Evidence SHA-256
ios-installed-build.json ee35534b564830107b62b49c0c309e563c9ffcabf2d589588f00702c4f2d2678
ios-installed-signature.log 3c4068a2d7e4d7a8680e40df124b42044a2efda0c6fd9e32da7b8a344d0e629c
ios-ual-contract-open.png 8a700852625c4ea067d76e2133f4b2da6c1c8cce5710f9023801185163dec9eb
ios-dal-after-switch.json 988a567aee1a87f233d1f16dda7c17620360d2763efb8881b0a417be9466c3d8
ios-dal-after-switch.png a5ed0943bbb87fbfb04f1640e6aecdb847945b3d7c076dd99e577bc26316d6bc
ios-switch-profile.json d35c21c1ab4087b3edaf6eedc9eb973e8bcc8df37c17d4bb467e0d3d62c76ca9
ios-switch-profile.png f0a45e5c1414937803280e40a87b0ad5a65b8ff4a7396860a763388ac0858ed4
ios-switch-logs.json be1a5be9ff56b98fe9b026e4635091874a42f1590587f80b616c931823028c2a
ios-switch-transitions.json 3a8e47bda7a31e094380b7534e0a8135f70ead9711f3f4942c918942611c8528
teardown.log e86203ce6d111d085af13e6ca4acf96d6935ff17eab873426bd0e2f9d4fffa89

Reproduction commands

All commands ran in sequence from one script against the checked-out revision. They use a single MSBuild worker and disable node reuse to avoid local shared-build contention. Full logs were retained, not reduced to summary output.

dotnet test UnitTest/UnitTest.csproj -c Debug -m:1 -nr:false --logger "trx;LogFileName=fix01b-debug.trx"
dotnet test UnitTest/UnitTest.csproj -c Release -m:1 -nr:false --logger "trx;LogFileName=fix01b-release.trx"
dotnet test DocsTests/DocsTests.csproj -c Debug -m:1 -nr:false --logger "trx;LogFileName=fix01b-docs.trx"
dotnet run docs/build-nav.cs -- --check
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Debug -p:RuntimeIdentifier=iossimulator-arm64 -p:EnableCodeSigning=false -m:1 -nr:false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-android -c Debug -m:1 -nr:false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-ios -c Release -p:RuntimeIdentifier=iossimulator-arm64 -p:EnableCodeSigning=false -p:ArchiveOnBuild=false -m:1 -nr:false
dotnet build ALPAMobile/ALPAMobile.csproj -f net10.0-android -c Release -m:1 -nr:false
python3 scripts/gateway-readiness-check.py --catalog-check
python3 scripts/gateway-readiness/test_catalog_check.py

Raw logs are local files under the reviewing session's scratch directory; TRXs are local ignored UnitTest/TestResults/ and DocsTests/TestResults/ artifacts. They are not claimed as uploaded CI artifacts. The compact summaries above and hashes below are checked in so the executed artifacts are distinguishable from historical runs.

TRX SHA-256
fix01b-debug.trx 77dfa0e50ac55f86067c086b15cdfe49581c91011549fb8029f561f16268a502
fix01b-release.trx ddc8087edcdec66ac06782b3c11d4216fa5c7c01d9fa7972fd1be316bd3764e3
fix01b-docs.trx b6f1886c3eec7ad4ad1d21b430eea0d4a3210d822520fb46b4914cf944f2e76d

Historical open integration acceptance at review hand-off

This subsection describes the original review hand-off. Current correction and device results are recorded at the top of this file. At hand-off, no device walkthrough or Appium run was claimed. P7-A4/P7-A5 remain open. Exercise both platforms for account switch, rejected/interrupted sign-in, slow/offline logout, resume with an expired session, home/theme/feed recovery, document download/viewer and FTDT synchronization. Verify native iOS cancellation timing and cross-host redirect bearer handling on device. F68 retains guarded synchronous effect startup; no device contention measurement is claimed.

Implementation and this correction PR target imp/blazor-hybrid-service-layer-decoupling. Complete the phase PRs in order, then this correction, with explicit human review. Do not merge the integration branch into imp/blazor-hybrid until the device gates pass. Automatic completion remains disabled for this correction PR.