feat: Sprint 10+11 — privacy hardening and multi-device support

Privacy Hardening (Sprint 10):
- Server --redact-logs flag: SHA-256 hashed identity prefixes in audit
  logs, payload_len omitted when enabled
- Client /privacy command suite: redact-keys on|off, auto-clear with
  duration parsing, padding on|off for traffic analysis resistance
- Forward secrecy: /verify-fs checks MLS epoch advancement,
  /rotate-all-keys rotates MLS leaf + hybrid KEM keypair
- Dummy message type (0x09): constant-rate traffic padding every 30s,
  silently discarded by recipients, serialize_dummy() + parse support
- delete_messages_before() for auto-clear in ConversationStore

Multi-Device Support (Sprint 11):
- Device registry: registerDevice @24, listDevices @25, revokeDevice @26
  RPCs with Device struct (deviceId, deviceName, registeredAt)
- Server storage: devices table (migration 008), max 5 per identity,
  E029_DEVICE_LIMIT and E030_DEVICE_NOT_FOUND error codes
- Device cleanup integrated into deleteAccount transaction
- Client REPL: /devices, /register-device <name>, /revoke-device <id>

72 core + 35 server tests pass.
This commit is contained in:
2026-03-04 01:55:23 +01:00
parent 1b61b7ee8f
commit 9244e80ec7
16 changed files with 958 additions and 45 deletions

View File

@@ -123,6 +123,15 @@ interface NodeService {
# A tombstone entry is added to the KT log for auditability.
# All active sessions for the identity are invalidated.
deleteAccount @23 (auth :Auth) -> (success :Bool);
# Register a device for the authenticated identity. Max 5 devices per identity.
registerDevice @24 (auth :Auth, deviceId :Data, deviceName :Text) -> (success :Bool);
# List all registered devices for the authenticated identity.
listDevices @25 (auth :Auth) -> (devices :List(Device));
# Revoke (remove) a registered device.
revokeDevice @26 (auth :Auth, deviceId :Data) -> (success :Bool);
}
struct Auth {
@@ -131,6 +140,12 @@ struct Auth {
deviceId @2 :Data; # optional UUID bytes for auditing/rate limiting
}
struct Device {
deviceId @0 :Data;
deviceName @1 :Text;
registeredAt @2 :UInt64;
}
# A delivery envelope pairing a per-inbox sequence number with an opaque payload.
# Clients sort by `seq` before processing to guarantee MLS commit ordering.
struct Envelope {