1 contributor
189 lines | 4.635kb

HealthProbe - Core Data Cache Design

Last Updated: 2026-05-23 Status: Initial programmatic model and full-cache rebuild implemented; UI wiring and targeted invalidation pending

1. Purpose

Core Data is not the forensic archive. It is the bounded, UI-friendly store for values already derived from the SQLite archive.

Use Core Data for: - observation rows shown in timelines; - type summaries and expensive counts; - daily/monthly aggregate display rows; - diff summary rows; - export history/status rows; - archive health/status rows; - local app state and settings that are not forensic evidence.

Do not use Core Data for: - the only copy of HealthKit samples; - raw record payload history; - relationship evidence; - point-in-time reconstruction truth; - large record tables.

SQLite wins on disagreement.

2. Store Categories

Core Data may contain two categories of entities.

Rebuildable cache entities Can be deleted and rebuilt from SQLite: - CachedObservationRow; - CachedTypeSummary; - CachedDailyAggregate; - CachedDiffSummary; - CachedExportManifest; - CachedArchiveHealth.

Local app state/settings Not forensic, not necessarily rebuildable: - selected type preferences; - UI display preferences; - last opened screen/state; - feature flags for legacy-device UI simplification.

Cache rebuild must not delete settings unless the user explicitly resets the app.

3. Entity Contracts

CachedObservationRow

Purpose: timeline/list display.

Required fields: - observationID; - observedAt; - status; - triggerReason; - timeZoneIdentifier; - trackedTypeCount; - visibleRecordCount; - appearedCount; - disappearedCount; - representationChangedCount; - archiveSchemaVersion; - cacheSchemaVersion; - sourceAggregateHash; - computedAt.

CachedTypeSummary

Purpose: per-observation/per-type summary cards and reports.

Required fields: - observationID; - sampleTypeIdentifier; - displayName; - visibleRecordCount; - appearedCount; - disappearedCount; - representationChangedCount; - earliestStartDate; - latestEndDate; - valueSum; - valueMax; - aggregateHash; - computedAt.

CachedDailyAggregate

Purpose: charts and report tables.

Required fields: - observationID; - sampleTypeIdentifier; - bucketStart; - bucketEnd; - timeZoneIdentifier; - visibleRecordCount; - valueSum; - valueMax; - sourceRevisionDisplayHash; - aggregateHash; - computedAt.

CachedDiffSummary

Purpose: observation comparison list/detail.

Required fields: - fromObservationID; - toObservationID; - sampleTypeIdentifier; - appearedCount; - disappearedCount; - representationChangedCount; - consolidationLikely; - uncertaintyReason; - sourceAggregateHash; - computedAt.

CachedExportManifest

Purpose: export history/status display.

Required fields: - exportID; - exportKind; - createdAt; - fromObservationID; - toObservationID; - filterSummary; - recordCount; - manifestHash; - fileURLBookmarkData; - status; - computedAt.

CachedArchiveHealth

Purpose: archive status screen.

Required fields: - archiveSchemaVersion; - cacheSchemaVersion; - lastIntegrityCheckAt; - lastIntegrityStatus; - lastErrorKind; - lastErrorMessageHash; - cacheBuildID; - computedAt.

4. Invalidation

Invalidate/rebuild cache rows when: - archive schema version changes; - archive reset/reinitialization occurs; - selected type registry changes; - a new observation commits in SQLite; - aggregate hashes change; - cache schema version changes.

Rebuild order: 1. archive health/status; 2. observation rows; 3. type summaries; 4. daily/monthly aggregates; 5. diff summaries; 6. export status rows.

Partial rebuild is allowed when SQLite can identify affected observations/types. Full rebuild must remain available for repair and tests.

Implementation note, 2026-05-24: CoreDataArchiveCacheStore defines the cache model programmatically and can rebuild all cache entities from the SQLite archive. The first implementation rebuilds observation rows, type summaries, daily aggregates, adjacent-observation diff summaries, export manifest rows, and archive health rows. It is intentionally rebuildable: deleting the Core Data cache must not touch the SQLite archive.

5. Legacy Device Mode

Legacy or low-memory UI should still use the same Core Data cache. It may reduce: - chart density; - default date range; - preview row count; - simultaneous loaded detail panes.

It must preserve: - capture; - cached summaries; - report generation; - paged SQLite detail/export access.