Skip to content

Add an admin-set full feature access override for shopkeepers - #159

Merged
dadachi merged 1 commit into
mainfrom
feature/feature-access-state
Oct 17, 2026
Merged

dadachi merged 1 commit into
mainfrom
feature/feature-access-state

Conversation

@dadachi

@dadachi dadachi commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports MyTurnTag's feature_access_state override from myturntagapi so the paid iOS/Android clients can unlock every paid feature without a purchase: testing on production, staff/partner/comp accounts, and App Review demo accounts.

  • shopkeepers.feature_access_state enum: normal_feature_access (1, default) / all_feature_access (2), null: false, indexed. Same names and values as myturntagapi.
  • Editable only in /madmin (ShopkeeperResource). Not permitted in sign-up or PATCH /shopkeeper_auth.
  • Sign-in (ShopkeeperSignInSerializer) returns feature_access_state and account_owner_feature_access_state; accounts (AccountSerializer) return owner_feature_access_state. The paid clients read these exact field names and string values. The accounts index already preloads owner, so this adds no queries.
  • Fixtures: one is normal_feature_access, two is all_feature_access, so tests cover both values.
  • Docs: OpenAPI schemas, README "Full feature access override" (when to use it, plus RevenueCat promotional entitlements as the no-code alternative: they need billing on and are keyed to the owner's app user ID), an AGENTS.md "Billing (paid clients)" section, and CHANGELOG.

Tests

  • madmin_test: the shopkeeper edit form, submitted as the browser sends it, sets all_feature_access
  • registrations_controller_test: sign-up and PATCH /shopkeeper_auth with feature_access_state: "all_feature_access" both leave it normal_feature_access
  • Serializer tests: sign-in returns both fields; accounts return the owner's state, not the viewing member's

To confirm each new test can fail, I permitted the param in both devise sanitizers, removed the madmin attribute and hard-coded the serializer values. All 6 new tests went red, then green again once the code was restored.

Local results: bin/rails test (643 runs, 0 failures), bin/rubocop, erb_lint, brakeman, bundler-audit and RAILS_ENV=test db:seed_fu all pass. I also ran a dev server and set the override on a seeded shopkeeper. Sign-in and GET /accounts returned all_feature_access, and a PATCH /shopkeeper_auth that tried to change it was ignored.

🤖 Generated with Claude Code

https://claude.ai/code/session_016JZoj1UtkFVFNcwoDfdb9f

Port feature_access_state from myturntagapi so the paid clients can
unlock every paid feature without a purchase: testing on production,
staff/partner/comp accounts and App Review demo accounts.

- shopkeepers.feature_access_state enum (normal_feature_access 1 default,
  all_feature_access 2), indexed, editable only in madmin
- Sign-in returns feature_access_state and
  account_owner_feature_access_state; accounts return
  owner_feature_access_state
- Tests: madmin can set it; sign-up and PATCH /shopkeeper_auth ignore it;
  serializers return the owner's state
- OpenAPI, README, AGENTS.md and CHANGELOG document the override and
  RevenueCat promotional entitlements as the no-code alternative

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JZoj1UtkFVFNcwoDfdb9f
@dadachi
dadachi merged commit a33ad5a into main Oct 17, 2026
3 checks passed
@dadachi
dadachi deleted the feature/feature-access-state branch October 17, 2026 00:07
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.

1 participant