ksjsb/docs/superpowers/specs/2026-07-11-device-profile-generation-design.md
2026-07-30 20:25:56 +08:00

132 lines
3.6 KiB
Markdown

# 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.