Persistence + wiring the offers screen needs, per the product decisions:
- SocialSettings (keystore-backed, no plaintext): coarse area geohash +
configurable relay URLs, both empty by default (no bundled public relays —
don't leak metadata to third parties). Registered in DI.
- createOffersCubit(): opens a SocialSession on the first configured relay when
online, else a null-transport cubit that degrades gracefully. OffersCubit now
closes the owning session on dispose.
4 settings tests green; offers/social suites still green.
The testable core of the offers UI slice, transport-agnostic:
- OfferMapper: pure app-sharing-intent (OfferStatus) -> network Offer/OfferType
mapping; keeps price only for sales, refuses to publish private lots.
- OffersCubit: discover(geohash) streams results; publish() reports the verdict;
depends on the OfferTransport interface (fake in tests) and degrades
gracefully offline (null transport = social layer unavailable, never throws).
8 tests green (fake in-memory transport, no relay). Screen/routing/i18n come
next — they need two product decisions (coarse-area capture, relay list).