P · 02 Verified · 2026-05-09

premium_no_ads

Premium users see zero ads anywhere in the app. The rewarded-ad to earn AI 點數 is hidden entirely — not greyed-out, removed from the DOM. Free users see the ad option only if they choose to.

$ flutter test test/integration/premium_no_ads_test.dart
# walks 23 screens as Premium user, asserts 0 ad widgets mounted
P · 03 Verified · 2026-05-09

anonymous_default

The first launch creates a local-only profile with no account, no email, no phone number. Sign-in is opt-in only, gated behind one settings toggle. We never ask for email to "save your data".

$ docs/design/scripts/validate-design-system.sh anonymous_default
# greps Onboarding/* for email|phone|account; expect 0
P · 04 Verified · 2026-05-09

data_egress = 0

By default, no cycle data leaves the device. Cloud AI is opt-in. iCloud / Google Drive sync is opt-in. The marketing site uses 0 third-party trackers — no GA, no Mixpanel, no Sentry, no PostHog.

$ npx @cap-go/cli analyze --binary build/ios/QiFlux.app
# expects: outbound endpoints == [Apple StoreKit, Google Play Billing only]
P · 05 Verified · 2026-05-09

sdk_count ≤ 5

We ship at most 5 third-party SDKs across both platforms: RevenueCat, Google Mobile Ads, Sentry (opt-in only), Sign-in-with-Apple, google_sign_in. Every one is documented in sdk.html with what it sends and when.

$ jq '.dependencies | keys | length' pubspec.yaml.json
# expects: ≤ 5 third-party network SDKs
P · 06 Verified · 2026-05-09

cancel ≤ 2 clicks

Cancel a subscription in two taps from anywhere in the app: Settings → "Manage subscription" deep-links to the OS-native subscription page. We never put a cancel flow inside our own UI — Apple and Google both forbid the dark patterns we'd be tempted to use there.

$ flutter test test/integration/cancel_subscription_test.dart
# asserts settings_subscription_row → openManageSubscriptionsUrl()
P · 07 Verified · 2026-05-09

trial_transparent

Three locks on every checkout: (1) bold-faced first-charge date and amount above the Confirm button, (2) "next charge in N days" countdown always visible in Settings, (3) one-tap "cancel now" that skips our UI entirely. No "free trial" headline without the math underneath.

$ flutter test test/widget/paywall_transparency_test.dart
# asserts boldface charge date, countdown, cancel-now visible pre-confirm
P · 08 Verified · 2026-05-09

cloud_ai_anonymized

If you opt in to cloud AI, the prompt sent to Gemini Flash contains only cycle phase, 體質 tag, and 3 chosen symptoms — no name, no email, no birthdate, no device ID. Google's paid tier guarantees no-train. You can flip back to on-device-only at any time.

$ docs/design/scripts/audit-prompt-payload.ts
# decodes outbound prompts; expects no PII fields

If a promise fails

We say so here, first.

No edit silently. No quiet rollback. If we ship a release that breaks one of these, this page changes from green to amber and explains what happened, what we shipped to fix it, and when. The audit log lives at github.com/cjc305/qiflux-promise-audit.