Encrypt Security activity journal at rest #1118

Closed
opened 2026-08-19 07:18:52 +00:00 by rockachopa · 0 comments
Member

Problem

The durable Security activity journal retains kind, authentication method, operator device_label, and private repository/issue target as plaintext SQLite columns for up to 10,000 events / 90 days. A copied state volume or backup therefore exposes an operational map even though the journal is described as privacy-preserving. Existing PrivateStateCipher infrastructure already provides authenticated AES-GCM envelopes and fail-closed behavior.

Vertical slice

Encrypt every event's sensitive payload at rest with STACKCHAIN_PRIVATE_STATE_ENCRYPTION_KEY, binding ciphertext to the immutable event ID. Preserve IDs, ordering, cursor pagination, pending/finalize/discard semantics, retention, and the Security activity API. Atomically migrate legacy plaintext rows. Wrong-key or tampered state must fail closed rather than serving partial history.

Acceptance tests

  • Newly recorded and reserved event metadata round-trips but unique sensitive values do not appear in SQLite bytes.
  • Legacy completed and pending rows migrate without changing IDs, timestamps, order, pagination, or reservation behavior.
  • Restarting with the same key preserves history; wrong-key/tampered ciphertext raises the privacy-safe store error and the API returns 503.
  • Age/count pruning remains enforced.
  • Focused and full test suites pass.

Non-duplicate evidence

Compared against all 561 historical issue titles and recent origin/main history at 91fdd958c218038b19644ac78ea77793f905715a. Existing work adds Security activity (#493), truthful reservation failures (#497), enrollment auditing (#513), alerts (#543), and lazy loading (#605); recent encryption work covers Drafts, worker snapshots, Web Push, Today, and Later, but not Security activity.

## Problem The durable Security activity journal retains `kind`, authentication `method`, operator `device_label`, and private repository/issue `target` as plaintext SQLite columns for up to 10,000 events / 90 days. A copied state volume or backup therefore exposes an operational map even though the journal is described as privacy-preserving. Existing `PrivateStateCipher` infrastructure already provides authenticated AES-GCM envelopes and fail-closed behavior. ## Vertical slice Encrypt every event's sensitive payload at rest with `STACKCHAIN_PRIVATE_STATE_ENCRYPTION_KEY`, binding ciphertext to the immutable event ID. Preserve IDs, ordering, cursor pagination, pending/finalize/discard semantics, retention, and the Security activity API. Atomically migrate legacy plaintext rows. Wrong-key or tampered state must fail closed rather than serving partial history. ## Acceptance tests - Newly recorded and reserved event metadata round-trips but unique sensitive values do not appear in SQLite bytes. - Legacy completed and pending rows migrate without changing IDs, timestamps, order, pagination, or reservation behavior. - Restarting with the same key preserves history; wrong-key/tampered ciphertext raises the privacy-safe store error and the API returns 503. - Age/count pruning remains enforced. - Focused and full test suites pass. ## Non-duplicate evidence Compared against all 561 historical issue titles and recent origin/main history at `91fdd958c218038b19644ac78ea77793f905715a`. Existing work adds Security activity (#493), truthful reservation failures (#497), enrollment auditing (#513), alerts (#543), and lazy loading (#605); recent encryption work covers Drafts, worker snapshots, Web Push, Today, and Later, but not Security activity.
timmy was assigned by rockachopa 2026-08-19 07:18:52 +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#1118
No description provided.