Files
geointel/docs/DATA_OPERATIONS_RUNBOOK.md
T
Codex 6a72c14c57
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Separate RC10 manifest provenance warnings
2026-07-18 07:32:57 +02:00

5.9 KiB

Data Operations and Retention Runbook

Purpose

This runbook governs persistent GeoIntel data for Belgium and the Belgian North Sea. It covers raw, normalized, derived, export, AI and release-evidence artifacts. No command in this runbook schedules itself and no source is downloaded implicitly.

Lifecycle classes

Class Paths Retention
Raw and normalized source originals/, uploads/, operator-data/ Protected; replace no official edition in place
Derived and cache derived/, rasters/derived/, previews/, tiles/, masks/ Eligible only when old and not referenced by persisted provenance
Exports exports/ Retain persisted exports; unreferenced old files may be candidates
AI models /app/models and storage/models/ Protected; activation and promotion evidence govern removal
Immutable evidence release-evidence/, operator-evidence/ Never a cleanup candidate
Unknown every unclassified path Protected by default

Dataset, DatasetVersion, Export, Detection, Segmentation, Job and AnalysisRun paths and nested provenance are treated as references. Failed work remains audit provenance. Project archival remains reversible and does not physically delete its datasets or files.

Read-only audit

Run the complete local storage, database-reference, disk-pressure and national/regional/maritime source-family report:

docker exec geointel python /app/scripts/audit_data_operations.py \
  --minimum-age-days 7 \
  --output /app/storage/release-evidence/rc-current/data-operations.json

The command:

  • inventories storage without following symlinks;
  • reports bytes and file counts per lifecycle class;
  • reports free disk bytes and percentage before new acquisition;
  • reports missing persisted path references;
  • identifies only old, unreferenced files inside the explicit cleanup allowlist;
  • summarizes national, regional and maritime source names, versions and latest import dates;
  • reports old failed Jobs and AnalysisRuns without deleting them.

Use --fail-on-pressure warning for a stricter acquisition preflight and --fail-on-missing-reference for release gates. critical disk pressure blocks acquisition by default. Critical means less than 10 GiB free. Warning means less than 50 GiB free, or less than 2% and less than 250 GiB free. The combined percentage/absolute rule avoids falsely blocking a large Unraid array that still has hundreds of GiB available.

The existing project-level freshness policy remains authoritative:

docker exec geointel python /app/scripts/audit_source_freshness.py \
  --project-id <belgium-and-north-sea-project-id> \
  --api-url http://127.0.0.1/api/v1 \
  --json \
  --output /app/storage/release-evidence/rc-current/source-freshness.json

Together, these reports cover the national workbench, regional source families and Belgian North Sea datasets without performing an external refresh. Catalog probes remain separate, explicit and read-only.

Cleanup dry run

docker exec geointel python /app/scripts/cleanup_storage_artifacts.py \
  --minimum-age-days 7 \
  --max-delete 25

This is always a dry run unless --apply is present. Review every candidate. Release evidence, operator evidence, official source material, uploads, models, unknown paths and every persisted path reference are excluded.

Technical benchmark projects can be archived reversibly:

docker exec geointel python /app/scripts/archive_technical_projects.py --show-names

The normal project lifecycle archive path does not need destructive confirmation because it changes only status=archived and preserves all data.

Destructive apply gate

First create a fresh backup with a SHA-256 storage inventory on the host:

bash scripts/backup_release_state.sh \
  --container geointel \
  --release-id rc10-before-cleanup-$(date -u +%Y%m%dT%H%M%SZ) \
  --output-root /mnt/user/appdata/geointel/backups \
  --storage-path /mnt/user/appdata/geointel/storage \
  --models-path /mnt/user/appdata/geointel/models \
  --inventory-mode sha256

Verify it read-only:

bash scripts/verify_release_backup.sh \
  --backup-dir /mnt/user/appdata/geointel/backups/<release-id> \
  --container geointel

The Unraid runtime mounts GEOINTEL_BACKUPS_PATH read-only at /app/backups. Only after reviewing the dry run may an operator execute:

docker exec geointel python /app/scripts/cleanup_storage_artifacts.py \
  --minimum-age-days 7 \
  --max-delete <reviewed-candidate-count> \
  --backup-dir /app/backups/<release-id> \
  --backup-max-age-hours 24 \
  --confirm DELETE_STORAGE_ARTIFACTS \
  --apply

The command re-runs the audit immediately before deletion. It refuses the operation when the exact token is absent, the candidate count exceeds the operator limit, the backup is stale/incomplete, checksums differ, the storage inventory is not SHA-256, or the path is outside the cleanup allowlist.

The older demo-export cleanup has the same gate and uses confirmation token DELETE_DEMO_EXPORTS.

Failure meaning

  • disk_pressure=critical: stop new source acquisition and resolve capacity.
  • missing_referenced_path_count>0: persisted provenance points to absent files; investigate before cleanup or release.
  • missing_manifest_artifact_count>0: a retained operator manifest names an absent non-authoritative intermediate. The direct database artifacts remain the release gate; retain this warning as provenance debt and do not delete the protected manifest or its other evidence.
  • checksum or backup-age failure: create and verify a new backup.
  • candidate count above --max-delete: keep dry-run mode and review; never increase the limit blindly.
  • symlink listed as skipped: inspect manually; the audit will not traverse or delete it.

No automatic cron or background cleanup is installed. Operators may schedule the read-only audit externally, but destructive commands must remain manual.