Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/docs/feature-flag-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ and an explicit empty literal renders as `''`.
| `CONVERSATION_TERMINAL_FAMILY_MODE` | Default on; stamp backend-only conversation terminal_family and atomically refuse late processor success over failure markers; on\|off | backend | env | open | {value: 'on', category: ops_kill} | on (backend-listen (chart), pusher (chart)); {value: 'on', category: ops_kill} (cloud_run/backend, cloud_run/backend-integration, cloud_run/backend-sync, cloud_run/backend-sync-backfill, gke/backend-listen, gke/pusher) | on (backend-listen (chart), pusher (chart)); {value: 'on', category: ops_kill} (cloud_run/backend, cloud_run/backend-integration, cloud_run/backend-sync, cloud_run/backend-sync-backfill, gke/backend-listen, gke/pusher) | — | keep | keep | — | uicleanup |
| `CONVERSATION_TOPIC_DETERMINISTIC_SHORT_ENABLED` | Default on; the desktop provisional-topic endpoint answers short transcripts deterministically only when the conversation language matches the resolved output language; a mismatch uses one pinned conv_structure call | backend | env | open | — | — | — | — | keep | keep | — | auditfix |
| `CONVERSION_BUNDLE_ATTRIBUTION_ENABLED` | Default on; accept only matching partial coupon assertions and strictly integer single-use bundle codes. off/false/0/no restores the prior conservative attribution validator without changing code benefit or entitlement. | backend | env | open | — | — | — | — | keep | keep | — | Goal: Conversion |
| `DAILY_RECAP_LEARNING_REFS_ENABLED` | Default on; resolve stored recap learning references to live feedback targets and omit retracted rows without a unique successor | backend | env | open | — | — | — | — | keep | keep | — | quality-lead |
| `DAY3_REENGAGEMENT_EMAIL_KILL_SWITCH` | Stop day-three re-engagement email | backend | env | inverted | false | false | false | — | keep | keep | — | unowned |
| `DESKTOP_LOOP_WATCHDOG_ENABLED` | Desktop event-loop stall warning and liveness signal; default on, false disables both | backend | env | open | — | — | — | — | keep | keep | — | auditfix |
| `DESKTOP_UPDATE_POINTERS_MODE` | Fall back to legacy desktop update pointers | backend | env | open | primary | primary (backend-listen (chart), cloud_run/backend, gke/backend-listen) | primary (backend-listen (chart), cloud_run/backend, gke/backend-listen) | — | keep | keep | — | unowned |
Expand Down Expand Up @@ -1225,6 +1226,7 @@ their code default (`fail` tells you which way a missing value resolves).
- `CONVERSATION_STORED_MEETING_CONTEXT_ENABLED` — Incident stop for stored meeting context lookup (fail: open)
- `CONVERSATION_TOPIC_DETERMINISTIC_SHORT_ENABLED` — Default on; the desktop provisional-topic endpoint answers short transcripts deterministically only when the conversation language matches the resolved output language; a mismatch uses one pinned conv_structure call (fail: open)
- `CONVERSION_BUNDLE_ATTRIBUTION_ENABLED` — Default on; accept only matching partial coupon assertions and strictly integer single-use bundle codes. off/false/0/no restores the prior conservative attribution validator without changing code benefit or entitlement. (fail: open)
- `DAILY_RECAP_LEARNING_REFS_ENABLED` — Default on; resolve stored recap learning references to live feedback targets and omit retracted rows without a unique successor (fail: open)
- `DEEPGRAM_SELF_HOSTED_ENABLED` — Retired 2026-08-27 with the rest of Deepgram; env removed from all charts and forbidden_env on every Cloud Run owner (fail: closed)
- `DESKTOP_LOOP_WATCHDOG_ENABLED` — Desktop event-loop stall warning and liveness signal; default on, false disables both (fail: open)
- `DIARIZATION_V2_ENABLED` — Enable the separate batch-only diarizer app; default false; startup loads models before readiness (fail: closed)
Expand Down
10 changes: 7 additions & 3 deletions backend/routers/users.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""User-account HTTP surface: profile, onboarding, people/contacts, webhooks,

Check warning on line 1 in backend/routers/users.py

View workflow job for this annotation

GitHub Actions / Hygiene

Large changed file

backend/routers/users.py is 2806 lines; consider splitting files over 800 lines.
tokens, geolocation, and the account-deletion wipe runner.

The OIDC-posted wipe endpoint is the sole wipe executor in production (startup
Expand Down Expand Up @@ -169,6 +169,7 @@
)
from utils.other.daily_recap import delivery_allowed as daily_summary_delivery_allowed
from utils.memory.learned_today import memories_learned_payload, memory_review_card_block
from utils.memory.recap_review import refresh_recap_learning_refs
from utils.other import endpoints as auth
from utils.other.list_budget import finish_list_budget
from utils.other.storage import (
Expand Down Expand Up @@ -1375,7 +1376,7 @@
return snapshot


def _user_subscription_response(

Check warning on line 1379 in backend/routers/users.py

View workflow job for this annotation

GitHub Actions / Hygiene

Long function

_user_subscription_response is 277 lines; consider extracting focused helpers over 150 lines.
uid: str,
x_app_platform: Optional[str],
x_app_version: Optional[str],
Expand Down Expand Up @@ -2083,7 +2084,8 @@
Returns summaries in reverse chronological order.
"""
try:
return {'summaries': read_daily_summary_page(uid, limit=limit, offset=offset, request=request)}
summaries = read_daily_summary_page(uid, limit=limit, offset=offset, request=request)
return {'summaries': refresh_recap_learning_refs(uid, summaries)}
except DailySummaryUnavailable:
raise HTTPException(status_code=503, detail='Daily recap data is temporarily unavailable') from None

Expand Down Expand Up @@ -2183,7 +2185,8 @@
except DailySummaryUnavailable:
raise HTTPException(status_code=503, detail='Daily recap data is temporarily unavailable') from None
filtered = filter_daily_summaries([item.model_dump() for item in valid], query, limit)
return {'summaries': [DailySummaryResponse.model_validate(item) for item in filtered]}
matches = [DailySummaryResponse.model_validate(item) for item in filtered]
return {'summaries': refresh_recap_learning_refs(uid, matches)}


@router.get('/v1/users/daily-summaries/{summary_id}', tags=['v1'], response_model=DailySummaryResponse)
Expand All @@ -2195,7 +2198,8 @@
if not summary:
raise HTTPException(status_code=404, detail='Daily summary not found')
try:
return require_daily_summary(summary, uid=uid, operation='detail')
validated = require_daily_summary(summary, uid=uid, operation='detail')
return refresh_recap_learning_refs(uid, [validated])[0]
except DailySummaryUnavailable:
raise HTTPException(status_code=503, detail='Daily recap data is temporarily unavailable') from None

Expand Down
8 changes: 8 additions & 0 deletions backend/tests/support/firestore_outside_query_drivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,3 +586,11 @@ def _enrichment_redrive_rows(client, combo, trial):
profile='maintenance-lake-conversation-erasure',
serving=False,
)

_driver(
'utils.memory.recap_review._source_successor',
base={'uid': UID},
domains={'memory_id': ['retired-memory', 'another-retired-memory']},
neutrals={'deadline': (None, 'RPC wall-time bound only; no query-shape change')},
profile='recap-learning-source-successor',
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
from routers.users import get_daily_summaries, get_daily_summary, search_daily_summaries


@pytest.fixture(autouse=True)
def _isolate_memory_reference_reads(monkeypatch):
# These tests cover schema/paging resilience. Memory authority resolution
# has its own transport regressions in test_recap_learning_refs.py.
monkeypatch.setattr(users_router, 'refresh_recap_learning_refs', lambda uid, summaries: summaries)


def _read_auth():
return ApiKeyAuth(
uid="uid1",
Expand Down
Loading
Loading