Move monetization, entitlement, paywall, and usage metering into a focused commerce layer independent of OpenCode sync state and legacy AppViewModel.
- StoreKit and usage meter primitives live in
Commerce/OpenClientCommerce.swift. - Usage meter state, paywall reason, debug entitlement override, purchase manager, and gates live in
AppViewModel. - Paywall views call
AppViewModelfor purchase/restore/dismiss/debug actions. - Prompt send and session creation call commerce gates through
AppViewModel.
CommerceStore: entitlement state, paywall reason, usage meter, debug override.CommerceService: StoreKit purchase/restore/refresh and usage persistence.CommerceFacade: view-facing paywall state and workflow-facing gates.- Views render commerce state and call facade intent methods.
- Send/session workflows query commerce gates through facade/service.
- Free prompt reserve succeeds until limit.
- Failed send refunds reserved prompt.
- Pro unlock bypasses prompt/session limits.
- Debug
limitReachedforces prompt block in Debug only. - Session creation gate blocks after free session limit and records successful creation once.
- Daily prompt count resets by local day while session count persists.
- Extract
CommerceStorewithusageMeter,paywallReason, and debug override. - Move
hasProUnlock, remaining prompt count, session count, and gate decisions into commerce layer. - Move purchase/restore wrappers out of
AppViewModel. - Update paywall and debug entitlement views to use commerce facade.
- Update send/session workflows to query commerce facade.
- Delete
AppViewModel+Commercewrappers after call sites migrate.
- Commerce rules are not scattered through chat/session/project views.
AppViewModeldoes not own paywall or usage state.- Debug overrides are Debug-only.
- Tests cover gate and refund semantics.