MPS-22: kill-switch feature flags for karaoke + torrent
Karaoke (MPS-18) and torrent (MPS-19) are broken in production. Adding
two global feature flags off by default so neither feature surfaces in
UI or accepts route traffic until they're fixed.
Pattern mirrors app.features.popout_player.enabled — reified request
properties (request.karaoke_enabled, request.torrent_enabled) read from
ini settings. Templates wrap UI in {% if %}, views return HTTPNotFound
on form sections + routes, view contexts blank out feature-specific
keys when flag off so SPA navigation does not try to render them.
test.ini sets both flags True so existing feature tests keep working.
TestKillSwitches builds a fresh app with both False and verifies the
off path: form_section POSTs return 404, settings page omits sections,
karaoke route 404s, landing page omits karaoke marketing copy.
GET /s/{shop_id}/torrent-backfill-status is shadowed by an earlier
shop_slug catch-all route in production — pre-existing routing defect
that MPS-19 needs to fix when it lands.
This commit is contained in:
parent
b3d9b2b39c
commit
2659ebdcbe
15 changed files with 458 additions and 21 deletions
|
|
@ -234,6 +234,7 @@ mps_page_session (raw rows)
|
|||
| [MPS-19](tickets/mps-19.md) | BitTorrent / Magnet Link — Diagnose & Fix Distribution | Open (Broken in prod) |
|
||||
| [MPS-20](tickets/mps-20.md) | Auction House Mode (eBay-style Bidding) | Proposed |
|
||||
| [MPS-21](tickets/mps-21.md) | Make-an-Offer Mode | Proposed |
|
||||
| [MPS-22](tickets/mps-22.md) | Kill-Switch Feature Flags — Karaoke + Torrent Off by Default | Complete |
|
||||
|
||||
## Related Docs
|
||||
|
||||
|
|
|
|||
140
docs/tickets/mps-22.md
Normal file
140
docs/tickets/mps-22.md
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
# MPS-22: Kill-Switch Feature Flags — Karaoke + Torrent Off by Default
|
||||
|
||||
## Status
|
||||
|
||||
**TO IMPLEMENT.** Karaoke (MPS-18) and torrent (MPS-19) are broken in
|
||||
production. Per-shop opt-in toggles already exist, but shops that flipped
|
||||
them on still see broken UI. Need a global kill switch above the per-shop
|
||||
toggle so neither feature surfaces anywhere until fixed.
|
||||
|
||||
## Problem
|
||||
|
||||
- Karaoke is gated only by `shop.unsandbox_public_key` + `secret_key`. A
|
||||
shop with creds set sees broken karaoke UI on every product page.
|
||||
- Torrent is gated only by `shop.torrent_enabled`. Toggle on → broken
|
||||
magnet button + dead backfill UI.
|
||||
|
||||
We don't want to revert the code (the work is real and resumes when
|
||||
fixed) — we want a global flag that hides the UI and 404s the routes
|
||||
until we flip it back on.
|
||||
|
||||
## Proposal
|
||||
|
||||
Mirror the existing `app.features.popout_player.enabled` pattern exactly:
|
||||
|
||||
1. **Two new ini settings**, both default `False`:
|
||||
- `app.features.karaoke.enabled = ${MPS_FEATURES_KARAOKE_ENABLED:-False}`
|
||||
- `app.features.torrent.enabled = ${MPS_FEATURES_TORRENT_ENABLED:-False}`
|
||||
2. **Two reified request properties** in `request_methods.py`:
|
||||
- `request.karaoke_enabled`
|
||||
- `request.torrent_enabled`
|
||||
3. **Template guards** wrap every UI surface in `{% if request.X_enabled %}`
|
||||
4. **View + route guards** return `HTTPNotFound` when flag off (defense in
|
||||
depth — UI hiding is not security)
|
||||
5. **Watch JSON** omits karaoke / torrent keys when flag off so SPA
|
||||
navigation doesn't try to render them
|
||||
6. **Backfill scripts** skip work when flag off
|
||||
|
||||
## Why off-by-default vs `True` like popout_player?
|
||||
|
||||
`popout_player` defaults `True` because it works. Karaoke and torrent
|
||||
default `False` because they don't. When MPS-18 and MPS-19 land, flip
|
||||
the dev default to `True` and add `MPS_FEATURES_KARAOKE_ENABLED=True`
|
||||
to `~/git/foxhop-pillar/uwsgi/makepostsell/init.sls` for prod.
|
||||
|
||||
## UI Surfaces to Hide
|
||||
|
||||
### Karaoke
|
||||
| File | Surface |
|
||||
|------|---------|
|
||||
| `templates/shop_settings.j2` | Unsandbox API keys section + backfill button |
|
||||
| `templates/content.j2` | Karaoke player toggle + URLs |
|
||||
| `templates/player.j2` | Karaoke audio source switch |
|
||||
| `templates/snippets/related_content.j2` | Karaoke indicator on related items |
|
||||
| `templates/home.j2` | Any karaoke discovery / promo |
|
||||
| `static/js/watch.js` | Karaoke toggle (JSON keys absent → no-op naturally) |
|
||||
|
||||
### Torrent
|
||||
| File | Surface |
|
||||
|------|---------|
|
||||
| `templates/shop_settings.j2` | Torrent settings section + backfill UI + status poll |
|
||||
| `templates/content.j2` | Magnet link button |
|
||||
| `templates/product_edit.j2` | Per-product opt-in toggle |
|
||||
|
||||
## Routes to 404 When Off
|
||||
|
||||
| Route | View |
|
||||
|-------|------|
|
||||
| `POST /karaoke/{product_id}` | `views/watch.py:karaoke_process` |
|
||||
| `GET /s/{shop_id}/torrent-backfill-status` | `views/shop.py` |
|
||||
| Settings `form_section=backfill-karaoke` | `views/shop.py:1019-1023` |
|
||||
| Settings `form_section=unsandbox-settings` | `views/shop.py` (creds save) |
|
||||
| Settings `form_section=torrent-settings` | `views/shop.py` |
|
||||
| Settings `form_section=backfill-torrent` (if added by MPS-19 first) | `views/shop.py` |
|
||||
| Karaoke trigger in `views/product.py:464-475` | gate on `request.karaoke_enabled` |
|
||||
|
||||
## Files
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `data/development.ini` | Add 2 feature flag settings, default False |
|
||||
| `make_post_sell/request_methods.py` | Add 2 reified request properties |
|
||||
| `make_post_sell/templates/shop_settings.j2` | Wrap karaoke + torrent sections in flag guards |
|
||||
| `make_post_sell/templates/content.j2` | Wrap karaoke + magnet UI |
|
||||
| `make_post_sell/templates/player.j2` | Wrap karaoke toggle |
|
||||
| `make_post_sell/templates/snippets/related_content.j2` | Wrap karaoke indicator |
|
||||
| `make_post_sell/templates/home.j2` | Wrap any karaoke promo |
|
||||
| `make_post_sell/templates/product_edit.j2` | Wrap torrent opt-in toggle |
|
||||
| `make_post_sell/views/watch.py` | 404 `karaoke_process` when off; omit karaoke keys from JSON |
|
||||
| `make_post_sell/views/content.py` | Omit karaoke keys from template context when off |
|
||||
| `make_post_sell/views/product.py` | Skip karaoke spawn when off |
|
||||
| `make_post_sell/views/shop.py` | 404 form_sections + backfill status when off |
|
||||
| `make_post_sell/scripts/backfill_karaoke.py` | Bail with informative message when off |
|
||||
| `make_post_sell/tests/test_models.py` | Request property unit tests |
|
||||
| `make_post_sell/tests/test_integration.py` | Form section refusal when off |
|
||||
| `make_post_sell/tests/test_functional.py` | UI hidden / routes 404 when off |
|
||||
| `CLAUDE.md` | Document kill-switch pattern + current flag state |
|
||||
| `docs/architecture.md` | Add MPS-22 to ticket index |
|
||||
|
||||
## Tests
|
||||
|
||||
### Unit (`test_models.py`)
|
||||
- `request.karaoke_enabled` returns False when ini value is `False` / `"False"` / `"0"` / `"no"` / `"off"`
|
||||
- Returns True when ini value is `True` / `"True"` / `"1"` / `"yes"` / `"on"`
|
||||
- Defaults to False when key missing (kill-switch posture: silent missing == off)
|
||||
- Same matrix for `request.torrent_enabled`
|
||||
|
||||
### Integration (`test_integration.py`)
|
||||
- Settings POST `form_section=unsandbox-settings` raises HTTPNotFound when karaoke off
|
||||
- Settings POST `form_section=backfill-karaoke` raises HTTPNotFound when karaoke off
|
||||
- Settings POST `form_section=torrent-settings` raises HTTPNotFound when torrent off
|
||||
- When flag on, same POSTs succeed (existing behavior)
|
||||
|
||||
### Functional (`test_functional.py`)
|
||||
- Shop settings page response **does not contain** strings "Unsandbox", "karaoke", "Backfill Vocal", "torrent", "magnet" when both flags off
|
||||
- Shop settings page **does contain** them when both flags on
|
||||
- `POST /karaoke/{product_id}` → 404 when off, 200 when on (with creds)
|
||||
- `GET /s/{shop_id}/torrent-backfill-status` → 404 when off
|
||||
- Product page response does not include magnet button or karaoke toggle when off
|
||||
- Watch JSON response does not include `karaoke_*` or `torrent_*` keys when respective flag off
|
||||
|
||||
## Go-to-Market
|
||||
|
||||
| Surface | Action |
|
||||
|---------|--------|
|
||||
| `~/git/foxhop-pillar/uwsgi/makepostsell/init.sls` | (later) add `MPS_FEATURES_KARAOKE_ENABLED` and `MPS_FEATURES_TORRENT_ENABLED` env vars when ready to flip on |
|
||||
| `docs/architecture.md` | Note MPS-22 + reference both flags in feature toggle matrix |
|
||||
| `CLAUDE.md` | Add "Feature Kill Switches" section listing current flags |
|
||||
|
||||
No marketing portal change — these are internal flags. Only flip MPS-18 / MPS-19 GTM when those tickets ship.
|
||||
|
||||
## Verification
|
||||
|
||||
1. `source vars.sh && make test` — all pass
|
||||
2. Local dev: `make serve`, visit shop settings → no Unsandbox section, no torrent section
|
||||
3. Visit a product page → no magnet button, no karaoke toggle
|
||||
4. `curl -X POST /karaoke/{product_id}` → 404
|
||||
5. Flip both env vars to `True`, restart, verify all UI returns
|
||||
6. Flip back to `False`, verify clean hide again
|
||||
7. Push → CI green → deploy → bump GIT_HASH
|
||||
8. Prod check: visit my.makepostsell.com shop settings, confirm sections gone
|
||||
Loading…
Add table
Add a link
Reference in a new issue