Skip to content

feat: add versioned Smart Life and Tuya Smart profiles - #5

Merged
AboveColin merged 2 commits into
AboveColin:mainfrom
jbjardine:codjardine/versioned-app-profiles
Sep 2, 2026
Merged

AboveColin merged 2 commits into
AboveColin:mainfrom
jbjardine:codjardine/versioned-app-profiles

Conversation

@jbjardine

@jbjardine jbjardine commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • bundle immutable, versioned profiles for Smart Life and Tuya Smart;
  • expose TuyaMobileApp and get_mobile_app_profile() for explicit profile selection;
  • add TuyaPasswordClient.for_application() while preserving the existing constructor for custom Tuya-based applications.

Context

Password login and device credential retrieval are now implemented in this package, but standalone callers still have to source the mobile application's signing identity themselves. That gap surfaced in ha-tuya-ble#163: the device data was available, while the caller was blocked on the application constants.

Keeping these two profiles here gives standalone callers and downstream integrations one maintained source. The values match the versioned profiles currently used by the pending Home Assistant integration.

Behavior and compatibility

  • Application selection is explicit because Smart Life and Tuya Smart use different signing identities and request metadata.
  • An authentication failure never triggers a silent retry with the other profile.
  • Existing callers can continue to pass a custom TuyaMobileAppProfile directly.
  • No package version or release metadata is changed in this PR.

Validation

  • pytest: 30 passed;
  • Black check on the changed Python files;
  • Ruff and Codespell checks on the changed surface;
  • clean git diff --check;
  • source distribution and wheel built successfully, both containing tuya_mobile/profiles.py.

The repository CI passed across Python 3.9 through 3.13. Both profiles are covered by offline resolution, immutability, redaction, and client-construction tests. jsimonetti independently used this PR to retrieve a device secKey; the exact Smart Life/Tuya Smart selector is being confirmed because the storefront names are ambiguous.

@coderabbitai

coderabbitai Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 41161d8b-df9e-4aab-b2a6-ddec55e58640

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 817bbf68-ab47-4844-8d44-c4c93ea08ed1

📥 Commits

Reviewing files that changed from the base of the PR and between d5c6f30 and e369961.

📒 Files selected for processing (5)
  • README.md
  • tests/test_profiles.py
  • tuya_mobile/__init__.py
  • tuya_mobile/password_client.py
  • tuya_mobile/profiles.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
🧰 Additional context used
🪛 Betterleaks (1.7.3)
tuya_mobile/profiles.py

[high] 26-26: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 30-30: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 46-46: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Ruff (0.16.1)
tuya_mobile/profiles.py

[warning] 28-28: Implicitly concatenated string literals on one line

Combine string literals

(ISC001)


[warning] 48-48: Implicitly concatenated string literals on one line

Combine string literals

(ISC001)


[warning] 78-80: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (6)
tuya_mobile/profiles.py (2)

23-41: 🎯 Functional Correctness

Validate the Smart Life profile with a controlled login flow.

The PR evidence confirms TuyaMobileApp.TUYA_SMART only. tests/test_profiles.py validates field shape, but it cannot detect stale Smart Life signing constants or request metadata. Before release, authenticate a controlled Smart Life account and retrieve credentials for one device.


14-19: LGTM!

Also applies to: 43-81

README.md (1)

13-14: LGTM!

Also applies to: 27-30, 38-58, 81-97

tests/test_profiles.py (1)

18-103: LGTM!

tuya_mobile/__init__.py (1)

5-6: LGTM!

Also applies to: 37-40, 50-52

tuya_mobile/password_client.py (1)

33-33: LGTM!

Also applies to: 172-191


📝 Summary

Summary by CodeRabbit

  • New Features
    • Added bundled, versioned profiles for the Smart Life and Tuya Smart applications.
    • Added explicit application selection using supported application names or enum values.
    • Added password-login setup through a selected mobile application profile.
    • Exposed profile lookup and application types for integration.
  • Documentation
    • Updated usage guidance and examples for application profiles and password login.
  • Bug Fixes
    • Added validation for unsupported applications and protected profile data from modification or secret exposure.

Walkthrough

The package now bundles versioned Smart Life and Tuya Smart profiles. It exposes profile selection and lookup APIs. TuyaPasswordClient.for_application uses a selected profile to configure password login.

Changes

Application profiles

Layer / File(s) Summary
Profile definition and resolution
tuya_mobile/profiles.py, README.md, tests/test_profiles.py
Defines immutable Smart Life and Tuya Smart profiles, supports enum or string lookup, rejects unsupported applications, and documents profile metadata and custom profiles. Tests cover profile content, immutability, redaction, and lookup behavior.
Password client integration
tuya_mobile/__init__.py, tuya_mobile/password_client.py, README.md
Exports TuyaMobileApp and get_mobile_app_profile. Adds TuyaPasswordClient.for_application and documents profile-driven password login.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to e3699

The PR adds explicit versioned profiles and preserves existing custom-application support; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant TuyaPasswordClient
  participant get_mobile_app_profile
  Caller->>TuyaPasswordClient: for_application(application, session, settings)
  TuyaPasswordClient->>get_mobile_app_profile: resolve application
  get_mobile_app_profile-->>TuyaPasswordClient: TuyaMobileAppProfile
  TuyaPasswordClient-->>Caller: configured TuyaPasswordClient
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding versioned Smart Life and Tuya Smart profiles.
Description check ✅ Passed The description directly explains the bundled profiles, public APIs, compatibility behavior, validation, and purpose of the changes.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 4 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Bundle versioned Smart Life and Tuya Smart identities so standalone callers can use password login without reconstructing application profiles. Keep selection explicit and preserve the custom-profile constructor for other Tuya-based applications.

Refs ha-tuya-ble/ha_tuya_ble#163
@jbjardine
jbjardine force-pushed the codjardine/versioned-app-profiles branch from 5e683a2 to e369961 Compare August 20, 2026 16:43
@jbjardine

Copy link
Copy Markdown
Contributor Author

Independent live validation is now available: jsimonetti reports that this PR successfully retrieved the secKey for a mower already bound to a Tuya application account. This exercises the bundled-profile credential path beyond the offline tests. I have asked which exact selector (TUYA_SMART or SMART_LIFE) was used so the profile-specific result can be recorded unambiguously.

@jbjardine

Copy link
Copy Markdown
Contributor Author

Follow-up to the live-validation note above: jsimonetti confirmed that the successful credential retrieval used TuyaMobileApp.TUYA_SMART. He then used the retrieved secKey with ha-tuya-ble to query the mower battery status directly, providing end-to-end validation of the bundled Tuya Smart profile path.

@jbjardine

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 21, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@jbjardine

Copy link
Copy Markdown
Contributor Author

Hi @AboveColin, could you please let me know whether you would like any further changes before this can be merged?

CI and the full CodeRabbit review are green. The TUYA_SMART profile has also been validated end to end on real hardware, and this PR is the remaining prerequisite for the downstream credential-retrieval work in ha-tuya-ble. Thanks for taking another look.

@AboveColin

Copy link
Copy Markdown
Owner

Thanks for the ping, and for the live validation notes. I reviewed the diff against main: it is additive, no existing code path or export changes, and the suite goes 24 to 30 passing. Happy to merge after two small things.

  1. Rotation error. The profiles pin app versions 7.10.0 and 7.8.6 and nothing watches for a rotation. When Tuya bumps a build, a downstream user gets a bare auth failure with no hint that the bundled profile is stale. Could you map that rejection onto the existing TuyaMobileProfileExpired and name the profile and version in the message, e.g. "bundled Tuya Smart profile 7.8.6 was rejected, the app build has probably rotated"? Bundling the profiles moves that support load to this repo, so I would like the error to point at the cause.

  2. README note. The PR removes the "ships no vendor credentials" line, which leaves a hole. Please add a sentence saying the bundled constants come from public Android builds and are already published in several open-source projects, so nobody reads the package as a credential store.

Nothing else blocking. Two smaller notes you can take or leave: for_application duplicates the constructor defaults, so forwarding **kwargs would stop the two drifting later; and TuyaMobileApp(str, Enum) is safe today only because nothing formats a member into a request, so .value at any future use site is worth a habit.

Identify stale bundled Smart Life and Tuya Smart profiles in typed
authentication errors so downstream users can distinguish app rotation
from account failures.

Document the public origin of the application constants and keep
client defaults owned by TuyaPasswordClient.
@jbjardine

Copy link
Copy Markdown
Contributor Author

Thanks for the clear review. I addressed all four points in 3e8c503. Could you please take another look?

  • Bundled profile rejections now raise TuyaMobileProfileExpired with the profile name, version, and rotation guidance. Custom profiles retain the generic safe error, and server messages remain redacted.
  • The README now states that the constants come from public Android builds, are already published in several open-source projects, and do not make the package a user credential store.
  • for_application keeps username explicit and forwards the remaining client options through **client_kwargs, so constructor defaults have a single owner.
  • TuyaMobileApp now documents the use of .value at serialization or request boundaries. No enum member currently enters a request.

The full local suite passes with 35 tests, package import and build succeed, and CI is green on Python 3.9 through 3.13.

@AboveColin
AboveColin merged commit 1ab38de into AboveColin:main Sep 2, 2026
6 checks passed
@jbjardine
jbjardine deleted the codjardine/versioned-app-profiles branch September 2, 2026 14:25
AboveColin pushed a commit that referenced this pull request Sep 14, 2026
Bundles immutable, versioned Smart Life and Tuya Smart profiles, adds
`TuyaMobileApp`, `get_mobile_app_profile()` and
`TuyaPasswordClient.for_application()`. Existing callers passing their own
`TuyaMobileAppProfile` are unaffected: the diff adds code paths and exports
without changing any existing one.

A rejection of a bundled profile now raises `TuyaMobileProfileExpired` naming
the profile and version, so a rotated app build reports its cause instead of a
bare auth failure. Custom profiles keep the generic redacted error.

The bundled constants come from public Android builds and are already published
in several open-source projects, so the package is not a user credential store.

Suite goes 24 to 35 passing. CI green on Python 3.9 through 3.13.

Claude-Session: https://claude.ai/code/session_01CWPsjG4meqxYHSxBXiUjyd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants