docs(manual): Batch 8 — update theme landmine entry (C-ART-EDGE-002 closed, theme scanner mandatory)
This commit is contained in:
parent
eb78b920a4
commit
df2837dc06
|
|
@ -81,8 +81,8 @@ collection name, and architectural fact. Never assume.
|
||||||
| 4 | ✅ done | Handler table missing functions (`syncEntitlement`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder`, `sendChallengeDayReminders`, `unlockDueMemoryCapsules`, `sendGentleReminderCallable`, `onEntitlementChanged`, `onAnswerRevealed`, `onCoupleLeave`, `leaveCoupleCallable`, `submitOutcomeCallable`, `scheduledOutcomesReminder`, `onGamePartFinished`, `notifyOnDateMatch`); still listed removed `health` endpoint and old name `createDateMatchOnMutualLove`; webhook section said 200-ack-before-process (now process-before-ack); `scheduledOutcomesReminder` timezone wrong | Removed `health`; added all current functions and corrected `notifyOnDateMatch`; updated module responsibilities; corrected webhook to process-before-ack with 500-on-failure; fixed schedule timezones (only `assignDailyQuestion`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder` use `America/Chicago`). |
|
| 4 | ✅ done | Handler table missing functions (`syncEntitlement`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder`, `sendChallengeDayReminders`, `unlockDueMemoryCapsules`, `sendGentleReminderCallable`, `onEntitlementChanged`, `onAnswerRevealed`, `onCoupleLeave`, `leaveCoupleCallable`, `submitOutcomeCallable`, `scheduledOutcomesReminder`, `onGamePartFinished`, `notifyOnDateMatch`); still listed removed `health` endpoint and old name `createDateMatchOnMutualLove`; webhook section said 200-ack-before-process (now process-before-ack); `scheduledOutcomesReminder` timezone wrong | Removed `health`; added all current functions and corrected `notifyOnDateMatch`; updated module responsibilities; corrected webhook to process-before-ack with 500-on-failure; fixed schedule timezones (only `assignDailyQuestion`, `sendDailyQuestionProactiveReminder`, `sendReengagementReminder` use `America/Chicago`). |
|
||||||
| 5 | ✅ done | `users/{uid}` section still described non-existent `hasPremium` root field; `couples/{coupleId}` section said all client writes denied (create is shape-restricted but possible); helper paragraph listed non-existent `isStartingEncryptionMigration`/`isCompletingOwnEncryptionMigration` | Updated `users/{uid}` to clarify `plan` is client-written and premium lives in `/entitlements/premium`; corrected couples create/update description; removed migration-helper references. |
|
| 5 | ✅ done | `users/{uid}` section still described non-existent `hasPremium` root field; `couples/{coupleId}` section said all client writes denied (create is shape-restricted but possible); helper paragraph listed non-existent `isStartingEncryptionMigration`/`isCompletingOwnEncryptionMigration` | Updated `users/{uid}` to clarify `plan` is client-written and premium lives in `/entitlements/premium`; corrected couples create/update description; removed migration-helper references. |
|
||||||
| 6 | ✅ done | Billing Webhook flow still said "ack 200 then process" (process-before-ack was fixed in Batch 4 but Billing section had stale duplicate); missing `CouplePremiumChecker`; Notifications said quiet-hours server-side suppression not implemented (it is, via `recipientInQuietHours`); Notifications said `notification_queue` reads denied for clients (Android reads it for Together feed); `onEntitlementChanged` handler table description said it mirrors `plan` (it notifies partner instead) | Updated Billing webhook flow; added `CouplePremiumChecker` note; corrected quiet-hours to server-side-implemented; corrected `notification_queue` read claim; fixed `onEntitlementChanged` description. |
|
| 6 | ✅ done | Billing Webhook flow still said "ack 200 then process" (process-before-ack was fixed in Batch 4 but Billing section had stale duplicate); missing `CouplePremiumChecker`; Notifications said quiet-hours server-side suppression not implemented (it is, via `recipientInQuietHours`); Notifications said `notification_queue` reads denied for clients (Android reads it for Together feed); `onEntitlementChanged` handler table description said it mirrors `plan` (it notifies partner instead) | Updated Billing webhook flow; added `CouplePremiumChecker` note; corrected quiet-hours to server-side-implemented; corrected `notification_queue` read claim; fixed `onEntitlementChanged` description. |
|
||||||
| 7 | in_progress | | |
|
| 7 | ✅ done | iOS E2EE gap paragraph said iOS create invite writes an invite with null E2EE fields (server now rejects empty data, so no invite is created); ProGuard section claimed Tink reflection paths are kept (they are not in current rules) | Updated iOS create-invite consequence to "rejected by server"; clarified ProGuard does not currently keep Tink. |
|
||||||
| 8 | todo | | |
|
| 8 | in_progress | | |
|
||||||
| 9 | todo | | |
|
| 9 | todo | | |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
|
||||||
|
|
@ -1247,10 +1247,12 @@ These are bugs that cost real debugging time and are easy to re-introduce if you
|
||||||
**Fix (R12)**: `DateMatchViewModel` injects `CouplePremiumChecker`; `swipeCurrent` intercepts LOVE/MAYBE on a premium idea when neither partner is premium → emits `paywallRequired` → `DateMatchScreen` navigates to the Paywall; SKIP still passes; the deck stays on the card. Mirrors the established [gate pattern](#premium-gated-features-and-gate-pattern).
|
**Fix (R12)**: `DateMatchViewModel` injects `CouplePremiumChecker`; `swipeCurrent` intercepts LOVE/MAYBE on a premium idea when neither partner is premium → emits `paywallRequired` → `DateMatchScreen` navigates to the Paywall; SKIP still passes; the deck stays on the card. Mirrors the established [gate pattern](#premium-gated-features-and-gate-pattern).
|
||||||
**Re-introduction risk / lesson**: a feature can ship an `isPremium` content flag + a `PremiumBadge` with **no enforcement at all**. When adding premium content, wire a real `CouplePremiumChecker` gate (filter OR paywall-on-interaction) — a badge is a label, not a lock. Audit by **trying to USE premium content as a free user**, not by grepping for checker usages (which only finds the features that already have one).
|
**Re-introduction risk / lesson**: a feature can ship an `isPremium` content flag + a `PremiumBadge` with **no enforcement at all**. When adding premium content, wire a real `CouplePremiumChecker` gate (filter OR paywall-on-interaction) — a badge is a label, not a lock. Audit by **trying to USE premium content as a free user**, not by grepping for checker usages (which only finds the features that already have one).
|
||||||
|
|
||||||
### Theme-variant + soft-edge art (C-DARKART-001, C-ART-EDGE-001; C-ART-EDGE-002 open)
|
### Theme-variant + soft-edge art (C-DARKART-001, C-ART-EDGE-001, C-ART-EDGE-002 closed; theme scanner now mandatory)
|
||||||
**Symptom**: (1) art didn't follow the IN-APP theme — `CloserTheme(darkTheme)` only swaps Compose colors, while `painterResource`/`-night` drawables resolve off the **system** `uiMode`, so app-Dark on a light-mode phone showed light illustrations on a dark screen (C-DARKART-001). (2) Tiled illustrations showed a hard rounded-rect edge instead of blending (C-ART-EDGE-001).
|
**Symptom**: (1) art didn't follow the IN-APP theme — `CloserTheme(darkTheme)` only swaps Compose colors, while `painterResource`/`-night` drawables resolve off the **system** `uiMode`, so app-Dark on a light-mode phone showed light illustrations on a dark screen (C-DARKART-001). (2) Tiled illustrations showed a hard rounded-rect edge instead of blending (C-ART-EDGE-001). (3) Hero illustrations rendered as opaque tiles had a hard bright block on dark (C-ART-EDGE-002).
|
||||||
**Fix (R11)**: `CloserTheme` provides `LocalAppInDarkTheme`; `BrandIllustration` loads each drawable through `context.createConfigurationContext(cfg)` with `UI_MODE_NIGHT_*` from `LocalAppInDarkTheme` (theme-correct `-night`), and feathers its 4 edges to transparent via `graphicsLayer{compositingStrategy=Offscreen}` + `drawWithContent` `BlendMode.DstIn` gradients; `EmptyState` routes its image through `BrandIllustration`. Files: `ui/theme/Theme.kt`, `ui/components/BrandIllustration.kt`, `ui/components/EmptyState.kt`.
|
**Fix (R11)**: `CloserTheme` provides `LocalAppInDarkTheme`; `BrandIllustration` loads each drawable through `context.createConfigurationContext(cfg)` with `UI_MODE_NIGHT_*` from `LocalAppInDarkTheme` (theme-correct `-night`), and feathers its 4 edges to transparent via `graphicsLayer{compositingStrategy=Offscreen}` + `drawWithContent` `BlendMode.DstIn` gradients; `EmptyState` routes its image through `BrandIllustration`.
|
||||||
**Re-introduction risk / still-open**: any art rendered via a **direct** `painterResource(R.drawable.illustration_*)` (NOT `BrandIllustration`) bypasses both fixes — hero images (daily-question, couple_subscription/paywall/onboarding, home prompts, spin-wheel) still hard-edge on dark (**C-ART-EDGE-002, open P3**). Prefer routing illustrations through `BrandIllustration`.
|
**Fix (R13)**: opaque hero tiles routed through `BrandIllustration(tile=true)` with `-night` variants; transparent celebration art (`spin_wheel`, `streak_milestone`, `reveal_celebration`) left as direct `Image`/`painterResource` because feathering floats is wrong.
|
||||||
|
**Fix (R15)**: `scripts/theme-scan.sh` is a mandatory Pass C pre-check that statically detects hardcoded colors, direct `painterResource`/`Image` usage outside `BrandIllustration`, mismatched container/surface colors, and missing `preview`s. Run it before any manual visual sweep; file findings in `ClaudeReport.md` and counts in `ClaudeQACoverage.md`.
|
||||||
|
**Re-introduction risk / still-open**: any new art rendered via a **direct** `painterResource(R.drawable.illustration_*)` (NOT `BrandIllustration`) bypasses theme-correct loading and feathering. Always route opaque rounded-rect illustrations through `BrandIllustration`; keep `MaterialTheme.colorScheme` for surfaces; add Tier 1/2 previews for new screens. A hardcoded `CloserPalette.*` dark value or a raw `Color.White`/`Color.Black` will be flagged by `theme-scan.sh`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue