9.6 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 device operations, the app exposes provider-routing adapters:
RoutingDeviceCatalog
RoutingSocketGateway
RoutingTemperatureHumidityGateway
RoutingInfraredGateway
Each adapter observes or reads the active ProviderProfile and delegates:
ABOX -> real AbsdkBridge implementation
LOCAL_EXPERIENCE -> simulation implementation
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
ProviderAvailability is simplified to the two supported options. Both are enabled in all build types:
data class ProviderAvailability(
val abox: Availability = Availability.Enabled,
val local: Availability = Availability.Enabled,
)
Availability.Simulation and compatible-backend-specific disabled reasons are removed unless another current UI requirement uses them.
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 routing adapter delegates ABox calls to the real test double and local calls to simulation.
- 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.