10 KiB
LAN ABSDK and Local Experience Design
Status
Approved on 2026-08-24 by the project owner. This specification replaces the three-provider model in feat/provider-login.
Goal
ABox Manager exposes exactly two choices before authentication:
- ABox uses the real vendor ABSDK bridge to communicate with the smart-home gateway available on the current LAN.
- Local experience uses production-safe simulation implementations, establishes a simulated session immediately, and enters the authenticated app without requesting credentials.
The app no longer offers or plans a self-hosted ABSDK-compatible backend.
Confirmed Environment and Constraints
- The observed gateway address is
192.168.100.1. - The gateway responds to the ABSDK-compatible route
POST /abox/index.php/abjhsdk/user/validate. libABSDK0630.jarhardcodesa-box.com.cn/abox/index.php/and does not expose a supported base-URL setter.setHostInfo(url, hotelName, roomNo, apikey)submitsurlas an initialization form field and does not change the HTTP target.- Hardware testing on
feat/moler-infrared-controlconfirms that the current network environment allows the vendor ABSDK to reach the real gateway. - Debug and release builds expose the same provider choices and routing behavior. Release is not treated as a special case.
- The vendor JAR uses cleartext HTTP. The existing
@CleartextAbsdkTransportopt-in remains mandatory, and the Android application must explicitly permit the required LAN transport. - Fake and real sessions, devices, state, and credentials must never be mixed.
Provider Model
ProviderType contains only:
enum class ProviderType {
ABOX,
LOCAL_EXPERIENCE,
}
The built-in profiles are:
abox-default -> ProviderType.ABOX
local-experience -> ProviderType.LOCAL_EXPERIENCE
The persisted profile store remains tolerant of removed enum values. A stored COMPATIBLE_BACKEND profile is ignored. If it was active, the app returns to provider selection rather than attempting migration to another provider.
User Flow
ABox
Provider selection
-> choose ABox
-> save and activate ABox profile
-> restore automatic-login preferences when available
-> otherwise show username/password login
-> SessionCoordinator delegates to the process-wide AbsdkBridge
-> enter authenticated app only after DomainResult.Success<Session>
Invalid credentials, network errors, and token failures remain on the login screen and display localized errors.
Local experience
Provider selection
-> choose Local experience
-> save and activate local profile
-> SimulationSessionGateway establishes Username("local") session
-> enter authenticated app immediately
Local experience:
- never displays the credential form;
- never calls ABSDK;
- never reads or writes Keystore credentials;
- uses production-safe simulation device gateways;
- can later be removed as a single provider/module boundary if the team decides not to ship it.
Module Boundaries
:absdk-bridge
Remains the anti-corruption layer around the vendor JAR and implements:
SessionGateway;SocketGateway;TemperatureHumidityGateway;InfraredGateway.
A single process-wide AbsdkBridge instance is shared by session and device operations so the mutex and vendor singleton Token remain aligned.
New :runtime:simulation
A production Kotlin/JVM module implementing:
LocalSessionGatewayasSimulationSessionGateway;DeviceCatalogasSimulationDeviceCatalog;SocketGatewayasSimulationSocketGateway;TemperatureHumidityGatewayasSimulationTemperatureHumidityGateway;InfraredGatewayasSimulationInfraredGateway.
These implementations provide deterministic local experience behavior but do not expose test-only failure injection, mutable call-recording APIs, or assertion helpers.
:testing:fakes
Remains test-only. It keeps scriptable errors, call recording, and other testing controls. It must not be added as an application runtime dependency.
:android:core:session
Keeps provider/profile persistence, Keystore credential storage, and LocalSessionGatewayImpl only until the new simulation gateway replaces it. After migration, the old local gateway implementation is removed to prevent two production local-session implementations.
:android:app
Owns the Hilt composition root and provider-aware routing. It injects:
SessionGateway -> AbsdkBridge
LocalSessionGateway -> SimulationSessionGateway
For ABSDK-backed device operations, the app exposes provider-routing adapters:
RoutingSocketGateway
RoutingTemperatureHumidityGateway
RoutingInfraredGateway
Each adapter reads the active ProviderProfile and delegates:
ABOX -> real AbsdkBridge implementation
LOCAL_EXPERIENCE -> simulation implementation
DeviceCatalog is not implemented by ABSDK 0630. The ABox catalog remains a provider-scoped local persistence responsibility owned by the device-catalog module; SimulationDeviceCatalog supplies only the built-in local-experience catalog. This change does not invent a remote discovery API or take ownership of the final ABox catalog implementation from its module owner.
No feature UI selects Real or Fake directly.
Session and Credential Rules
SessionCoordinatorcontinues to select the session gateway fromProviderType.- ABox credentials can use remember-username and automatic-login settings.
- Automatic-login passwords are stored through Android Keystore.
- Local experience cannot persist credentials or login preferences requiring a password.
- Switching provider logs out the current gateway before activating another profile.
- Logging out of ABox clears credentials and the Bridge-local session but leaves the ABox profile active so the login page can be shown again.
- Logging out of local experience clears the local session and active profile, returning to provider selection.
- Only a session whose
profileIdmatches the active profile can produce the authenticated UI state.
Provider Availability
As implemented, ProviderAvailability was deleted entirely: both remaining options are always enabled, so an availability model with disabled states has no caller. The provider selection screen lists exactly ABox and local experience in every build type, with no per-provider availability state or disabled reason.
Android Transport
The application declares:
<uses-permission android:name="android.permission.INTERNET" />
and permits the vendor cleartext transport required by the current ABSDK. This is an explicit acceptance of the current LAN integration constraint, not a claim that the transport is encrypted.
No password, Token, API key, raw vendor response, or infrared payload may be logged.
UI and Copy
Provider selection presents exactly:
- ABox — connects to the ABox smart-home gateway through ABSDK on the current LAN;
- Local experience — uses simulated local devices without network access.
All compatibility-backend copy, status labels, and branches are removed from English and Simplified Chinese resources.
Error Handling
- ABox authentication failure maps to the localized invalid-credentials message and does not create a session.
- Network failure maps to the localized network message and does not create a session.
- Token invalidation clears the Bridge-local session and returns the app to login.
- Selecting local experience fails visibly if profile persistence or simulated-session creation fails.
- Routing adapters return
DomainError.InvalidRequestwhen no active profile exists or the profile type is unsupported. - Cancellation is rethrown rather than converted to a normal failure.
Testing Strategy
Unit tests
ProviderTypeand provider selection expose exactly ABox and local experience.- Removed persisted compatible profiles are ignored and cannot become active.
SessionCoordinatorroutes ABox toSessionGatewayand local experience toLocalSessionGateway.- Arbitrary ABox credentials do not succeed unless the injected real/fake test gateway returns success.
- Local experience selection creates a session without calling the ABox gateway or credential store.
- Each socket, temperature/humidity, and infrared routing adapter delegates ABox calls to the real test double and local calls to simulation.
- The local-experience device catalog is supplied by simulation without asserting that ABSDK provides ABox device discovery.
- Switching providers logs out the previous session and isolates state.
Integration and build verification
- Debug and release compile with the same real ABSDK and simulation modules.
- Hilt resolves one binding for each public gateway.
- Android lint validates Internet/cleartext configuration.
- Full command:
./gradlew check testDebugUnitTest test.
Authorized hardware validation
On a device connected to the gateway LAN:
- Choose ABox.
- Enter a known-invalid credential pair and verify the app stays on login.
- Enter an authorized valid credential pair and verify authenticated navigation.
- Validate Token using the shared Bridge.
- Perform one read-only device query before any control operation.
- Choose local experience and verify no ABSDK call or network dependency is required.
Sensitive credentials and Tokens are never captured in test reports.
Documentation Changes
The implementation updates:
docs/requirement_spec.md;docs/project_plan.md;docs/architecture.md;docs/protocol/absdk-0630.md.
The documents must no longer state that the product connects to an ABox cloud service or a self-hosted compatible backend. They must distinguish confirmed LAN behavior from the JAR's still-hardcoded host behavior.
Out of Scope
- Reimplementing the ABSDK HTTP/signature protocol;
- patching or rewriting the vendor JAR;
- adding a self-hosted compatibility server;
- adding an in-app gateway IP field that the current JAR cannot consume;
- merging the authenticated app shell PR;
- deciding whether local experience remains in the final product beyond preserving it as a removable module boundary.