You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Background
The /activity page functions as the guild's audit log — the record admins rely on to confirm what happened (members joining/leaving, passes activating/expiring, guild settings changing). An audit log's value depends heavily on admins being able to trust that historical entries haven't been silently edited or deleted, whether by a bug, a compromised process, or a malicious insider with database access.
Problem
Nothing in the current design (mock in-memory data today, and any future durable Postgres storage from Issue #6) provides tamper evidence for the activity log — a direct database edit (or a bug in application code) could alter or delete historical entries with no way for an admin to detect it after the fact.
Expected outcome
Each activity log entry, when written, includes a cryptographic hash that incorporates the entry's own content plus the hash of the immediately preceding entry (a hash chain), so that altering or deleting any historical entry breaks the chain from that point forward in a way that's programmatically detectable. A verification endpoint/tool allows an admin (or automated check) to confirm the chain is intact, and to pinpoint exactly where it breaks if it doesn't.
Suggested implementation
Define the canonical serialization of an activity entry used for hashing (must be deterministic — e.g. explicit field ordering, not relying on object key iteration order).
On write, compute hash_n = SHA256(serialize(entry_n) + hash_{n-1}), storing hash_n alongside the entry; use a well-known constant (e.g. all-zeros) as hash_0's predecessor.
Add a verification routine that walks the stored chain and recomputes hashes, reporting the first index at which the recomputed hash diverges from the stored one (if any).
Expose this as an internal admin tool/API endpoint (e.g. /api/activity/verify or a CLI script) rather than necessarily a prominent end-user UI feature, since this is primarily an integrity/ops tool.
Consider (and explicitly document the trade-offs of) whether the chain's final/latest hash should be periodically anchored somewhere outside the mutable database (e.g. logged externally) to detect a full-database tamper/replace — this can be scoped out of the initial implementation but should be discussed in the design write-up.
This feature only makes sense once there is a persistent store for activity (mock in-memory data resets on restart anyway) — this should be built on top of Issue Add a server-wide role sync command for admins #6's durable storage mode, or clearly scoped to only apply when durable mode is active.
Acceptance criteria
New activity entries are written with a hash that deterministically depends on their content and the previous entry's hash.
A verification routine correctly reports "chain intact" for an untampered log.
A test that directly mutates a stored historical entry (simulating a bypass of the application layer) causes verification to correctly detect and localize the break.
The design document/PR description explicitly addresses (even if only to defer) the "what if the whole chain is replaced" anchoring problem.
This feature is gated to durable storage mode (or otherwise clearly scoped) with mock mode behavior unchanged.
Tests and pnpm typecheck pass.
Likely affected files/directories apps/dashboard/lib/storage/ (activity write path, building on Issue #6), new verification module/endpoint, apps/dashboard/app/activity/ (optional integrity indicator in UI).
Difficulty: Expert
Type: Security
Background
The
/activitypage functions as the guild's audit log — the record admins rely on to confirm what happened (members joining/leaving, passes activating/expiring, guild settings changing). An audit log's value depends heavily on admins being able to trust that historical entries haven't been silently edited or deleted, whether by a bug, a compromised process, or a malicious insider with database access.Problem
Nothing in the current design (mock in-memory data today, and any future
durablePostgres storage from Issue #6) provides tamper evidence for the activity log — a direct database edit (or a bug in application code) could alter or delete historical entries with no way for an admin to detect it after the fact.Expected outcome
Each activity log entry, when written, includes a cryptographic hash that incorporates the entry's own content plus the hash of the immediately preceding entry (a hash chain), so that altering or deleting any historical entry breaks the chain from that point forward in a way that's programmatically detectable. A verification endpoint/tool allows an admin (or automated check) to confirm the chain is intact, and to pinpoint exactly where it breaks if it doesn't.
Suggested implementation
hash_n = SHA256(serialize(entry_n) + hash_{n-1}), storinghash_nalongside the entry; use a well-known constant (e.g. all-zeros) ashash_0's predecessor./api/activity/verifyor a CLI script) rather than necessarily a prominent end-user UI feature, since this is primarily an integrity/ops tool.durablestorage mode, or clearly scoped to only apply whendurablemode is active.Acceptance criteria
durablestorage mode (or otherwise clearly scoped) with mock mode behavior unchanged.pnpm typecheckpass.Likely affected files/directories
apps/dashboard/lib/storage/(activity write path, building on Issue #6), new verification module/endpoint,apps/dashboard/app/activity/(optional integrity indicator in UI).