# DFP Bootstrap Design ## Goal Add a pure Python DFP bootstrap layer that consumes `DeviceProfile` and builds DFP/unifiedId request material without depending on APP runtime, HAR templates, Frida logs, or scripts under `out/`. The first deliverable is deterministic dry-run request construction. Online POST and profile update are added only after dry-run form material is isolated, tested, and stable. ## Current Evidence Recovered relationships and algorithms already available in `core/`: - `core.enc_data.kwsg_10400_raw()` builds the 10400 `deviceInfo` envelope. - `core.dfp_sign.sign_dfp_form()` builds 10405 `sign`. - `core.device_profile.DeviceProfile` holds local `did/oDid/rdid/egid` state. - `egid` is returned by `/rest/infra/gdfp/report/kuaishou/android`. - cloud `did/cdid_tag` comes from unifiedId fetch/repair responses. Useful prototype code currently lives under `out/`: - `out/dfp_sq0_proto.py` - `out/build_dfp_lite_knn.py` - `out/build_dfp_full_knn.py` - `out/build_dfp_fetch_form.py` - `out/build_dfp_repair_form.py` - `out/build_dfp_check_repair_form.py` - `out/build_dfp_report_form.py` - `out/dfp_protocol_client.py` Phase 2 migrates the reusable pieces into `core/` and leaves analysis scripts in `out/` as historical evidence only. ## Scope ### Included - Encode DFP sq0 protobuf bytes for lite and full kNN maps. - Build lite and full kNN maps from `DeviceProfile` plus optional static environment/profile fields. - Build signed forms for: - `unifiedId/fetch/android` - `unifiedId/checkRepair` - `unifiedId/repair/android` - `gdfp/report/kuaishou/android` - Export request specs with URL, headers, ordered form, body, and debug hashes. - Add optional online POST client after dry-run builders pass tests. - Parse cloud DID / did tag / egid responses and write them back through `DeviceProfile.apply_cloud_identity()`. ### Excluded - Live APP instrumentation. - HAR runtime templates. - Mutating `main.py` task flow. - Claiming `egid` is locally generated. ## Architecture ```text DeviceProfile -> core.dfp_knn.build_lite_knn() -> core.dfp_sq0.encode_sq0_device_info() -> core.enc_data.kwsg_10400_raw() -> core.dfp_forms.build_unified_fetch_form() -> core.dfp_forms.build_unified_check_repair_form() -> core.dfp_forms.build_gdfp_report_form() -> core.dfp_client.post_request() # online only -> DeviceProfile.apply_cloud_identity() ``` ### `core/dfp_sq0.py` Pure sq0 protobuf encoder/decoder. Responsibilities: - load embedded lite/full key-to-proto-tag schema - encode ordered kNN string maps - decode fields for tests and diagnostics ### `core/dfp_knn.py` Build DFP plaintext kNN maps. Responsibilities: - build lite 33-key map - build full 119-key map - compute `k14` CRC - use `DeviceProfile` for identity fields: - `k31` android id - `k66` oDid suffix - `k83` current cached egid or empty first-run value - `k107` did tag - `k112` cache marker if supplied - `k93.28` gRdi2 ### `core/dfp_forms.py` Build signed form objects. Responsibilities: - wrap sq0 bytes in 10400 `deviceInfo` - Java-style base64 and form encoding - preserve request form order - use `core.dfp_sign.sign_dfp_form()` - expose `DfpRequestSpec` ### `core/dfp_client.py` Optional online client. Responsibilities: - POST request specs using `requests` - parse JSON safely - return structured `DfpResponse` - update `DeviceProfile` only when response fields pass validation ### `tools/new_device.py` Extends current CLI: - `--dfp-dry-run`: write DFP request material without sending. - `--online`: send DFP bootstrap requests and update saved profile. - `--profile PATH`: load an existing profile instead of creating a new one. ## Error Handling - Missing required identity fields raise `ValueError`. - Invalid DFP response fields are recorded and not applied. - Online mode records HTTP status, JSON parse failures, and business result. - Request builders never silently omit known empty fields; empty strings remain present when the Java form includes the key. ## Test Strategy Use TDD and `unittest` because this project does not currently depend on `pytest`. Required checks: - sq0 encoder keeps key order and skips empty values in the same way as the prototype. - k14 CRC changes when any mapped value changes. - lite kNN uses `DeviceProfile` identity fields. - form builders preserve known form order. - DFP sign input material matches `core.dfp_sign` rules. - dry-run request specs produce deterministic body ordering. - online response parser only applies valid `cloud_did/did_tag/egid`. ## Milestones 1. Dry-run migration: - `core/dfp_sq0.py` - `core/dfp_knn.py` - `core/dfp_forms.py` 2. CLI integration: - `tools/new_device.py --dfp-dry-run` 3. Online bootstrap: - `core/dfp_client.py` - `tools/new_device.py --online` 4. Request/profile persistence: - save request material under `out/devices//dfp_*.json` - save updated profile JSON after accepted server identity response