# Device Profile Generation Design ## Goal Build a self-contained device identity generation pipeline for producing many stable, self-consistent Android device profiles without depending on live APP runtime state. The first deliverable is local identity generation and persistence. Online DFP bootstrap is intentionally separated into a later step because `egid` and cloud `did` are server-issued values and require a coherent `deviceInfo` payload. ## Current Findings Known runtime relationships: - `oDid = "ANDROID_" + android_id` - `rdid = "ANDROID_" + md5(gRdi2)[16:32]` - local fallback `did` can be generated independently - cloud `did` and `cdid_tag` override local fallback values after unifiedId refresh - `egid` is returned by DFP report, not derived by a local hash Observed sample: ```text android_id=46a032e0a2af8184 oDid=ANDROID_46a032e0a2af8184 gRdi2=799999139::8641|899999556::8641|999999345::4741|899999995::8641|999999515::4741 md5(gRdi2)=be49e5841412c571741de4351c44850d rdid=ANDROID_741de4351c44850d did=ANDROID_e8dfd2f16b618053 cdid_tag=2 ``` ## Scope ### Included in phase 1 - Generate local Android identity fields. - Generate a stable `gRdi2` string and matching `rdid`. - Generate a local fallback `did`. - Persist and reload profiles without changing identities. - Apply server identity values later through an explicit update method. - Export profiles as JSON and `.env` snippets for other scripts. ### Excluded from phase 1 - Calling DFP/unifiedId services. - Producing a guaranteed valid `egid`. - Replacing `main.py` task runner behavior. - Reusing HAR files as runtime templates. ## Architecture ### `core/device_profile.py` Owns device identity data and local generation rules. Main objects: - `DeviceProfile`: serializable profile model. - `DeviceProfileGenerator`: creates new profiles from a random source. - `load_device_profile(path)`: loads a persisted profile. - `save_device_profile(profile, path)`: writes profile JSON. ### `tools/new_device.py` Small CLI wrapper around the core generator. Responsibilities: - create one or more profiles - save JSON files - optionally print `.env` format - avoid depending on APP, Frida, HAR, or `out/` ### Tests `tests/test_device_profile.py` verifies: - android_id is 16 lowercase hex characters - `oDid` matches android_id - `rdid` matches `md5(gRdi2)[16:32]` - persisted profile reloads identically - cloud identity update changes `did`, `cdid_tag`, and `egid` only when explicit ## Data Flow ```text new_device.py -> DeviceProfileGenerator.new_profile() -> DeviceProfile.to_dict() -> save JSON / print env existing JSON -> load_device_profile() -> use stable identity in request builders server response -> profile.apply_cloud_identity(did, cdid_tag, egid) -> save JSON ``` ## Error Handling - Invalid `android_id`, `did`, `oDid`, `rdid`, or `egid` values raise `ValueError`. - Loading malformed JSON raises `ValueError` with the file path. - Existing output files are not overwritten unless the CLI receives `--force`. - Batch generation creates separate files and fails fast on duplicate filenames. ## Testing Strategy Use TDD: 1. Write failing tests for local generation and persistence. 2. Implement minimal core code to pass tests. 3. Add CLI tests or smoke checks. 4. Run focused tests and compile checks before claiming completion. ## Future Phase After phase 1, add an online bootstrap layer: ```text DeviceProfile -> build DFP fetch/check/repair/report forms -> call unifiedId / gdfp report -> apply cloud did / cdid_tag / egid ``` That layer should migrate useful code out of `out/build_dfp_*.py` into `core/` without making `main.py` depend on HAR templates.