- Replaced the legacy Devices page with an interactive Network dashboard.
- Added a visual topology model showing one server node and all connected collector nodes.
- Added collector health/detail controls directly from node selection.
- Implemented topology rendering with native React + SVG instead of adding a new graph library.
- Rationale: no additional dependency churn and enough flexibility for glowing edges + pulse animation.
- Used existing Tauri commands as the backend integration surface:
get_system_state,get_collector_ids,get_component_config,set_component_config.
- Kept alias/icon customization local to the interface (localStorage override) because current backend config RPCs do not expose alias/icon fields.
- Implemented force-sync action as an explicit attempted RPC call (
force_collector_sync) with surfaced warning when unavailable.
- UI loads collector state via
get_system_state(fallbackget_collector_ids). - UI loads per-collector modality configs for managed modalities.
- Topology graph renders:
- edge glow based on online/offline status,
- pulse animation based on active source state inference.
- Selecting a node opens controls for:
- per-modality enable/disable,
- pause/resume all known modalities,
- local alias/icon override save.
- Added
NetworkTopologyDashboardunit test for node render + modality update command dispatch. - Verified via
just test-uiandjust validate-all.
- Enhance search results with:
- text snippets around query terms,
- highlighted term matches,
- lightweight thumbnails for image modalities.
- Keep
query_timelineas the primary key retrieval path. - Add an interface backend enrichment command:
get_frame_data_thumbnails(keys)returns frame metadata plus downscaled image previews.
- Perform snippet construction in the frontend from enriched frame fields.
- Rationale: avoids proto churn and allows UI-level tuning of snippet length and highlight behavior.
- UI calls
query_timelinewith text query. - UI calls
get_frame_data_thumbnailsfor returned keys. - UI builds
SearchResultmodels with:snippet,highlightTerms,preview(thumbnail data URL for image frames).
ResultCardrenders lazy thumbnail + highlighted snippet.
- Added
SearchDashboardUI tests for:- snippet highlighting,
- thumbnail rendering.
- Verified with
just test-uiandjust validate.
- Enforced mandatory TLS for server and collector gRPC traffic.
- Enforced mandatory bearer authentication token checks on server RPC entrypoints.
- Wired collector pairing usage (
PairCollector) into collector handshake when only enrollment token is present. - Unified collector identity usage across control/state traffic to configured collector id.
- Server startup now fails if TLS cert/key are not configured via:
LIFELOG_TLS_CERT_PATH,LIFELOG_TLS_KEY_PATH.
- Server startup now fails if token env vars are missing:
LIFELOG_AUTH_TOKEN,LIFELOG_ENROLLMENT_TOKEN.
- Collector and upload manager now reject non-
https://server addresses. - Pairing keeps configured collector identity as source of truth for stream/upload consistency.
- Verified compilation with
tools/ai/run_and_digest.sh "just check"after changes. just testwas started under digest wrapper and did not complete in this environment within the session window.
- Added coarse-grained retention controls for automatic data lifecycle management.
- Added a server-side pruning worker and UI controls in Settings.
ServerConfignow carriesretention_policy_days: map<string,uint32>.- Keys are modality buckets (for now:
screen,audio,text; optionalallfallback in pruning logic). 0means no automatic deletion.
- Keys are modality buckets (for now:
- Retention worker runs as a dedicated server background task.
- Default schedule is daily.
LIFELOG_RETENTION_INTERVAL_SECScan override interval for testing/ops.
- Prune semantics:
- Use
t_canonicalwhen present, otherwisetimestamp. - Delete stale rows from origin tables by modality policy.
- Gather
blob_hashvalues from deleted rows and remove only orphaned CAS blobs after cross-table reference checks.
- Use
- Live config updates:
SetSystemConfigRequestnow carries fullSystemConfig.- Server
SetConfigapplies server retention/default-window updates and forwards collector updates overControlStreamviaUpdateConfig.
tools/ai/run_and_digest.sh "just check": pass.tools/ai/run_and_digest.sh "just test": pass.tools/ai/run_and_digest.sh "cd interface && npm run build": pass.
- Added initial PostgreSQL migration assets and runtime helper module in
server/. - Kept SurrealDB runtime paths intact to avoid partial cutover regressions while landing scaffolding.
- Added a new server-local PostgreSQL helper module (
server/src/postgres.rs) with:- URI detection helper (
postgres:///postgresql://). - Connection pooling via
deadpool-postgres. - Ordered SQL migration execution from
server/migrations/.
- URI detection helper (
- Added first static migration file (
20260303143000_init_postgres.sql) containing:upload_chunksidempotency/resume metadata table.catalogandtransform_watermarksmetadata tables.- Initial unified modality tables (
screen_records,browser_records,ocr_records,audio_records,clipboard_records,shell_history_records,keystroke_records). TSTZRANGE+ GIST temporal indexes and TSVECTOR + GIN text indexes for search-capable modalities.
- Added
justrecipes for SQL migration workflow:just sqlx-migrate-add <name>just sqlx-migrate-run <database_url>
just check-digest: pass.tools/ai/run_and_digest.sh "nix develop --command cargo test -p lifelog-server postgres::tests --lib": pass.
- Rewrote the server ingest path to support PostgreSQL as an ingest backend for chunk streaming.
- Preserved existing Surreal ingest/query runtime as fallback to avoid partial cutover regressions.
- Added
PostgresIngestBackendimplementingutils::ingest::IngestBackend. - Added
HybridIngestBackenddelegator (SurrealorPostgres) soUploadChunkscan route at runtime without changing the collector protocol. - PostgreSQL ingest writes decoded frame payloads directly via parameterized SQL (no
ToRecordin Postgres path). - Idempotency strategy for chunk metadata:
INSERT ... ON CONFLICT (id) DO UPDATE SET indexed = (upload_chunks.indexed OR EXCLUDED.indexed).
- ACK gate semantics preserved:
screenchunks remain pinned (indexed=false) when OCR transform is enabled.- other mapped streams set
indexed=trueonce persisted.
- CAS remains filesystem-backed; Postgres records store
blob_hashandblob_sizereferences. - Postgres ingest activation is explicit through
LIFELOG_POSTGRES_INGEST_URL(+ optionalLIFELOG_POSTGRES_INGEST_MAX_CONNECTIONS).
just check-digest: pass.tools/ai/run_and_digest.sh "just test": pass.
- Switched deployment defaults to PostgreSQL-first operation while preserving SurrealDB during hybrid transition.
- Added PostgreSQL pool observability to server state responses.
- Updated operational docs/config examples to reflect PostgreSQL as the primary dependency.
- Added a NixOS module in
flake.nix(nixosModules.lifelog-postgres) that:- enables
services.postgresql, - auto-creates
lifelogdatabase andlifelogrole (configurable).
- enables
- Updated server systemd units to:
- depend on
postgresql.service, - export
LIFELOG_POSTGRES_INGEST_URLandLIFELOG_POSTGRES_INGEST_MAX_CONNECTIONS.
- depend on
- Kept
lifelog-surrealdb.servicedependency/env in place for transition safety. - Extended
ServerStatewith PostgreSQL pool metrics sourced fromdeadpool-postgresstatus:- enabled flag,
- max size,
- current pool size,
- available connections,
- waiting requests.
tools/ai/run_and_digest.sh "just check-digest": pass.