diet-guard/diet_guard
Krzysztof kuhy Rudnicki 04f5d75aab fix: stop a touched credentials file clobbering a newer peer edit
`_local_credential_log` fell back to the hand-written `kuchnia_credentials`
and used its **mtime** as the edit clock. That clock is not trustworthy:
`git checkout`, a backup restore, and re-running the `install -m 600` setup
line all bump it forward without the credential changing.

Reproduced before fixing: a PC whose file had merely been touched, syncing
against a phone that had set a new password an hour earlier, resolved to the
PC's stale password. The phone user would have seen their edit silently revert.

The bootstrap is still needed -- someone has to publish first, and the PC is
where the password is typed -- so it moves to `_bootstrap_credential_log` and
runs only when the merge came back completely empty. It can no longer outrank
a real edit from a peer; it can only fill a vacuum. Once anything has been
published, the synced cache (which carries a real edit time) takes over
permanently.

`test_a_touched_handwritten_file_cannot_clobber_a_peer` pins it, and was
checked against the pre-fix code: reintroducing the fallback fails it.

Also rewrites the two remaining places that still claimed a credential "must
never leave the machine it was entered on" -- `_constants.py`'s comment and
the doc's Credentials section, which now has a table of which of the three
files syncs and which does not. Rewritten rather than given an exception
clause.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQpCiPaSbyRpwsLkH3dgsX
2026-08-23 08:15:40 +02:00
..
sync_merge feat: sync the catering credential as its own document 2026-08-23 08:12:30 +02:00
tests fix: stop a touched credentials file clobbering a newer peer edit 2026-08-23 08:15:40 +02:00
__init__.py Remove unused features; fix reminder false alarms; share all state 2026-07-26 16:39:52 +02:00
__main__.py Extract diet_guard from testsAndMisc as a standalone repo 2026-06-22 12:18:39 +02:00
_averages_periods.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_averages_report.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_averages.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_budget_biometrics.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_budget_derived.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_budget_history.py Split _sync.py and its tests; extract the gate fixtures from conftest 2026-08-15 18:51:18 +02:00
_budget.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_calendar_view.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_cli_args.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_cli_averages.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_cli_gate.py perf(gate): narrow the pre-lock pull and defer the heavy imports 2026-08-21 12:58:44 +02:00
_cli_init.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_cli_kuchnia.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_cli_log.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_cli_prune.py feat(sync): add prune-peers to remove device dirs nothing writes to 2026-08-21 13:28:04 +02:00
_cli_sync.py perf(gate): narrow the pre-lock pull and defer the heavy imports 2026-08-21 12:58:44 +02:00
_cli.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_coerce.py Extract diet_guard from testsAndMisc as a standalone repo 2026-06-22 12:18:39 +02:00
_constants.py fix: stop a touched credentials file clobbering a newer peer edit 2026-08-23 08:15:40 +02:00
_daystatus.py Show weekly and monthly average intake on both devices 2026-08-09 14:59:40 +02:00
_device.py Split _sync.py and its tests; extract the gate fixtures from conftest 2026-08-15 18:51:18 +02:00
_estimator_off.py perf(gate): narrow the pre-lock pull and defer the heavy imports 2026-08-21 12:58:44 +02:00
_estimator.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_foodbank_manual.py Remove unused features; fix reminder false alarms; share all state 2026-07-26 16:39:52 +02:00
_foodbank_rebuild.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_foodbank_search.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_foodbank.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_fuzzy.py feat(diet_guard): add meal-logging screen-lock gate with trigger fix 2026-06-10 22:32:39 +02:00
_gate.py Read the meal schedule from a forward-only history (Python) 2026-08-16 14:28:22 +02:00
_gatelock_budgetedit.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_gatelock_calendar_schedule.py Let the PC gate set the eating window and meal count 2026-08-16 15:02:35 +02:00
_gatelock_calendar_types.py Let the PC gate set the eating window and meal count 2026-08-16 15:02:35 +02:00
_gatelock_calendar_ui.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock_calendar_widgets.py Let the PC gate set the eating window and meal count 2026-08-16 15:02:35 +02:00
_gatelock_calendar.py Let the PC gate set the eating window and meal count 2026-08-16 15:02:35 +02:00
_gatelock_core.py Remove unused features; fix reminder false alarms; share all state 2026-07-26 16:39:52 +02:00
_gatelock_delivery.py fix: keep the catering dish queue alive across a submit 2026-08-22 23:36:53 +02:00
_gatelock_fetch.py perf(gate): unfreeze "Fetch from sync" and bound the interactive timeout 2026-08-21 13:07:37 +02:00
_gatelock_fields.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock_groups.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock_kuchnia.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_gatelock_layout.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_gatelock_lockfile.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock_mealflow.py fix: keep the catering dish queue alive across a submit 2026-08-22 23:36:53 +02:00
_gatelock_nutrition.py Split _state.py and _tk_fakes.py; make the food-log redirect fail closed 2026-08-15 20:21:26 +02:00
_gatelock_scheduleedit.py Let the PC gate set the eating window and meal count 2026-08-16 15:02:35 +02:00
_gatelock_spacing.py Migrate diet_guard to gatelock v0.2.0 per-output locking 2026-07-25 16:56:13 +02:00
_gatelock_support.py feat: split oversized modules for 500-line limit, fix kasa coverage gap 2026-06-14 07:19:37 +02:00
_gatelock_typography.py Make the meal gate usable without a pointer on a 1366x768 screen 2026-07-30 16:21:27 +02:00
_gatelock_ui_types.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_gatelock_ui.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock_widgetgroups.py Split the six Python gate files; guard the fake-tk patch set 2026-08-15 20:08:03 +02:00
_gatelock.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_client.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_config.py feat: sync the catering credential as its own document 2026-08-23 08:12:30 +02:00
_kuchnia_credential_store.py feat: sync the catering credential as its own document 2026-08-23 08:12:30 +02:00
_kuchnia_errors.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_import.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_log.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_orders.py feat: import Kuchnia Wikinga catering deliveries into the food bank 2026-08-22 23:04:22 +02:00
_kuchnia_parse.py feat: mirror the catering parser and slot spread in Dart, gated by one fixture 2026-08-23 08:00:54 +02:00
_kuchnia_spread.py feat: mirror the catering parser and slot spread in Dart, gated by one fixture 2026-08-23 08:00:54 +02:00
_mcp_read.py Read the meal schedule from a forward-only history (Python) 2026-08-16 14:28:22 +02:00
_mcp_server.py Make PC sync event-driven; retire the 15-min timer 2026-08-15 19:21:30 +02:00
_mcp.py Read the meal schedule from a forward-only history (Python) 2026-08-16 14:28:22 +02:00
_meal_schedule_store.py Read the meal schedule from a forward-only history (Python) 2026-08-16 14:28:22 +02:00
_meal_schedule.py Derive meal slots from an eating window and a meal count 2026-08-16 14:21:12 +02:00
_portions.py Extract diet_guard from testsAndMisc as a standalone repo 2026-06-22 12:18:39 +02:00
_prune_peers.py fix(sync): prune the revision marker too, not just the device directory 2026-08-21 13:38:34 +02:00
_resolve.py Split the last seven Python files; extend the redirect guard to all five paths 2026-08-15 20:37:05 +02:00
_slots.py Read the meal schedule from a forward-only history (Python) 2026-08-16 14:28:22 +02:00
_state_sync.py Split _state.py and _tk_fakes.py; make the food-log redirect fail closed 2026-08-15 20:21:26 +02:00
_state_today.py Split _state.py and _tk_fakes.py; make the food-log redirect fail closed 2026-08-15 20:21:26 +02:00
_state.py Split _state.py and _tk_fakes.py; make the food-log redirect fail closed 2026-08-15 20:21:26 +02:00
_sync_banks.py perf(sync): hoist the device listing and stop the curated-bank 404 storm 2026-08-21 13:16:08 +02:00
_sync_client.py perf(gate): unfreeze "Fetch from sync" and bound the interactive timeout 2026-08-21 13:07:37 +02:00
_sync_errors.py Split _sync.py and its tests; extract the gate fixtures from conftest 2026-08-15 18:51:18 +02:00
_sync_events.py perf(cli): publish off-thread so logging a meal returns immediately 2026-08-21 13:22:26 +02:00
_sync_kuchnia.py fix: stop a touched credentials file clobbering a newer peer edit 2026-08-23 08:15:40 +02:00
_sync_paths.py feat: sync the catering credential as its own document 2026-08-23 08:12:30 +02:00
_sync_refresh.py perf(gate): unfreeze "Fetch from sync" and bound the interactive timeout 2026-08-21 13:07:37 +02:00
_sync.py feat: sync the catering credential as its own document 2026-08-23 08:12:30 +02:00
_test_guard.py Remove unused features; fix reminder false alarms; share all state 2026-07-26 16:39:52 +02:00