Encrypt synchronized Today journeys at rest #1112

Closed
opened 2026-08-19 04:25:15 +00:00 by timmy · 0 comments
Owner

Problem

Today plans, active sessions, recap items, and recap time-log identities are retained as plaintext in today.sqlite3. A copied database, WAL, backup, or host snapshot reveals issue identities, estimates, elapsed time, device identifiers, and recap outcomes. Existing private-state encryption protects worker snapshots and Web Push subscriptions but not Today.

Vertical slice

Encrypt every task-bearing Today payload with the existing authenticated private-state cipher, account/record-bound AAD, transparent transactional migration of legacy plaintext, and fail-closed API behavior. Preserve revisions, idempotency, conflict handling, ordering, retention, and cross-device behavior.

Acceptance

  • Plan, active-session, recap, and time-log canaries never appear in raw SQLite/WAL bytes.
  • Same-key restart preserves all existing Today behavior.
  • Legacy plaintext rows migrate without revision or status changes.
  • Wrong keys, tampering, and cross-account/record substitution fail closed without overwriting ciphertext.
  • Focused behavioral tests and the full suite pass.

Evidence / non-duplication

Current origin/main is c219f13. src/today_store.py writes these payloads directly; src/state_encryption.py already provides AES-256-GCM envelopes. All 558 historical issue titles and recent commits were checked: no Today-at-rest encryption work exists. The nearest issues only cover filesystem permissions (#891), synchronized Draft encryption (#1098/#1100), worker snapshots (#1106), and Web Push subscriptions (#1108).

## Problem Today plans, active sessions, recap items, and recap time-log identities are retained as plaintext in `today.sqlite3`. A copied database, WAL, backup, or host snapshot reveals issue identities, estimates, elapsed time, device identifiers, and recap outcomes. Existing private-state encryption protects worker snapshots and Web Push subscriptions but not Today. ## Vertical slice Encrypt every task-bearing Today payload with the existing authenticated private-state cipher, account/record-bound AAD, transparent transactional migration of legacy plaintext, and fail-closed API behavior. Preserve revisions, idempotency, conflict handling, ordering, retention, and cross-device behavior. ## Acceptance - Plan, active-session, recap, and time-log canaries never appear in raw SQLite/WAL bytes. - Same-key restart preserves all existing Today behavior. - Legacy plaintext rows migrate without revision or status changes. - Wrong keys, tampering, and cross-account/record substitution fail closed without overwriting ciphertext. - Focused behavioral tests and the full suite pass. ## Evidence / non-duplication Current `origin/main` is `c219f13`. `src/today_store.py` writes these payloads directly; `src/state_encryption.py` already provides AES-256-GCM envelopes. All 558 historical issue titles and recent commits were checked: no Today-at-rest encryption work exists. The nearest issues only cover filesystem permissions (#891), synchronized Draft encryption (#1098/#1100), worker snapshots (#1106), and Web Push subscriptions (#1108).
timmy self-assigned this 2026-08-19 04:25:15 +00:00
timmy closed this issue 2026-08-19 04:41:17 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stackchain/stackchain-dashboard#1112
No description provided.