Skip to content

fix: align license_service with Worker flat response shape#34

Merged
iamvirul merged 1 commit into
masterfrom
fix/license-response-shape
Jun 23, 2026
Merged

fix: align license_service with Worker flat response shape#34
iamvirul merged 1 commit into
masterfrom
fix/license-response-shape

Conversation

@iamvirul

@iamvirul iamvirul commented Jun 23, 2026

Copy link
Copy Markdown
Member

Summary

  • The licensing Worker's ok() helper returns { token, tier, features } at the response root - there is no data wrapper
  • license_service.dart was reading body['data']['token'], which is always null, causing every valid activation to throw 'Invalid response from licensing server'
  • Fixed activate() to read body['token'], body['tier'], and body['features'] directly
  • Fixed validateOnline() to read the refreshed token from body['token'] directly

Root cause

Discovered by reading src/lib/response.ts in the Worker repo:

export const ok = (data: unknown, status = 200): Response =>
  new Response(JSON.stringify(data), { status, headers: JSON_CT });

And src/routes/activate.ts:

return ok({ token, tier: license.tier, features: TIER_FEATURES[license.tier] });
// Response: { "token": "...", "tier": "pro", "features": [...] }

The Flutter client expected { "data": { "token": "..." } } which never matched.

Test plan

  • Enter a valid BMS license key on the activation screen - should activate successfully instead of showing "Invalid response from licensing server"
  • Restart the app - validateOnline() should refresh the JWT correctly
  • Enter an invalid key - should show the server error message (e.g. "Invalid or revoked license key")

Summary by CodeRabbit

  • Bug Fixes

    • Refined licensing server response parsing to improve token validation reliability.
    • Enhanced error detection for invalid licensing server responses.
  • Refactor

    • Streamlined token refresh logic during license validation.

Worker ok() returns {token, tier, features} at the root - not wrapped
under a 'data' key. Both activate() and validateOnline() were looking
for body['data']['token'], causing 'Invalid response' on every valid
activation attempt.
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 414a2136-cbdc-41fb-a819-2c112d10de56

📥 Commits

Reviewing files that changed from the base of the PR and between 37178d4 and 52b4819.

📒 Files selected for processing (1)
  • lib/licensing/license_service.dart

📝 Walkthrough

Walkthrough

LicenseService.activate and validateOnline are updated to parse the licensing server response from the top-level JSON object (body['token'], body['tier'], body['features']) instead of a nested body['data'] map. activate also gains an explicit INVALID_RESPONSE exception when the token is absent.

Changes

Licensing Server Response Parsing

Layer / File(s) Summary
Top-level JSON field extraction in activate and validateOnline
lib/licensing/license_service.dart
activate now reads jwt from body['token'] and throws LicenseException('Invalid response from licensing server', 'INVALID_RESPONSE') when missing, then reads tier/features from top-level body instead of body['data']. validateOnline similarly reads newJwt from body['token'] directly, dropping the body['data'] map check.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • getbms/bms#24: Introduced LicenseService including the original activate and validateOnline implementations that read from body['data'], which this PR directly modifies.

Poem

🐇 Hop, hop, no more nested nest,
The token now lives at the top of the rest,
body['data'] has packed up and gone,
body['token'] is where we belong!
Less indirection, cleaner the burrow — 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: aligning license_service to match the Worker's flat response structure instead of expecting a nested data wrapper.
Description check ✅ Passed The description comprehensively covers the summary, root cause, and test plan sections from the template, with clear explanations and linked evidence.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/license-response-shape

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

@github-actions

Copy link
Copy Markdown
Contributor

Preview deployed

URL https://getbms.github.io/bms/pr-34/
Commit 3edbb0e
Status Live

Updates automatically on every push.

@iamvirul iamvirul merged commit d26ca9b into master Jun 23, 2026
11 checks passed
@iamvirul iamvirul deleted the fix/license-response-shape branch June 23, 2026 08:17
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