docs mobile p13 t05a shared auth - AlexandreZanata/Abastevo GitHub Wiki
P13-T05A — Shared portable auth (login flows + ports)
Status: LOCAL_DONE on codex/phase-13-free-accounts (phase PR #27,
draft). Issue: #26 (slice 1 of P13-T05; slices per ROADMAP rules).
G12-basic satisfied; device evidence stays deferred to release per
owner decision. No live-provider contact.
Slice acceptance (frozen before coding)
- T05A (this commit) — shared portable auth core:
PortableAuthdomain values (providers/issuers/audience, code shape, session liveness, nonce bind, strict callback parse) +AuthFlowuse cases (email request/consume, refresh, logout-everywhere, rehydrate, provider begin/complete, self-delete) behind narrow ports (AuthSessionStore,AuthWallClock,AuthAccountApi, reusedPortableNonceSource); server verdicts pass through verbatim for UI mapping. Swift 1:1 transcription of the pure core + XCTest vectors (implemented-unverified, P12 practice). - T05B (next) — Android Keystore session adapter + HTTP API adapter (+ dep license review) + app wiring.
- Later — screens, Keychain adapter + macOS run (release horizon).
What changed
domain/.../portable/PortableAuth.kt— frozen backend mirrors (P13-T01): google/apple allowlist + issuers,anpfuel-backendaudience, 6-digit shape (hint only), 900s/30d liveness,anpfuel://auth/callbackstrict parse (scheme/host/path, no blanks, no duplicated keys), exact nonce/state/provider bind refusing substitution (proof never sent on mismatch).application/.../portable/PortableAuthFlow.kt—AuthFlowoverAuthPorts: email hint validation, session persist, refresh-before-expiry, local-first logout (storage always clears, even offline), rehydrate (Active/NeedsRefresh/LoggedOut, corrupt blobs refuse), provider begin (fresh nonce+state) / complete (spent-nonce replay refusal + mismatch refusal without API touch; servernonce-reusedmarks spent), self-delete.iosApp/.../PortableAuth.swift+PortableAuthTests.swift— transcription with NOT COMPILED/NOT RUN banners; no new toolchain claims.- Tests:
PortableAuthTest(5) +PortableAuthFlowTest(11): allowlist, shape, liveness edges, bind/substitution matrix, strict parse matrix, signup persist, malformed-local, verbatim verdicts, rotation, dead-session relogin, offline logout, process-death rehydrate, corrupt blob, link-once + replay, substitution-never-sends, delete-clears.
RED → GREEN
- RED proven by neutering the spent-nonce replay guard:
providerLinkBindsNonceAndSendsOncefails (replay reaches the API); GREEN on restore. - Baseline import-ban guard (
kotlinx.coroutinesetc.) holds: portable stays sync, coroutines remain native-side.
Validation (exact commands, this host)
./gradlew :domain:test :application:test :data:testDebugUnitTest :app:testDebugUnitTest :app:assembleDebug --no-daemon
make quick-verify
git diff --check
Outcome: domain+application 491 tests (475 baseline + 16 new),
0 failures/errors/skips; data/app suites + assembleDebug
SUCCESS; quick-verify selection=full ok; diff --check clean;
secrets scan clean. Swift transcription statically reviewed
against the Kotlin vectors only — never claimed compiled.
Limits (not claimed)
- No Keystore/Keychain adapters, no HTTP adapter, no screens; API/storage/clock/nonce ports are faked in tests.
- Swift runs on macOS only (release horizon); flow-class adoption in the shell likewise.
- Live providers stay P13-T05/G13 device evidence (deferred).
Rollback
Pure addition under portable/ + iosApp: deleting the four
Kotlin/Swift files restores the tree. No migration, no flag.
Next
P13-T05B Android adapters (#26, same branch). Issue #26 stays open until the phase PR merges.