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

171 lines
4.9 KiB
Markdown

# 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/<profile>/dfp_*.json`
- save updated profile JSON after accepted server identity response