Skip to content

F24: CSV export / manual backup — per-dataset CSVs, full account export (zip), self-host dump instructions #95

Closed

Description

@mforce

Spec §17.5 (Backup/recovery, Phase 1): manual CSV export, full account export, database dump instructions for self-hosted deployment.

Scope

API (AdminOnly — export is a bulk-exfiltration surface and several datasets are money data, which is admin-gated end-to-end):

  • GET /api/v1/export/{dataset} → text/csv, streamed. Datasets (19): flocks, bird-movements, daily-entries, daily-entry-grades, egg-grades, egg-lots, customers, sales-orders, sales-order-items, sales-order-allocations, payments, inventory-items, inventory-lots, inventory-movements, feed-usages, water-usages, expense-categories, expenses, audit-events. Unknown dataset → 404.
  • GET /api/v1/export/all → application/zip: one CSV per dataset + manifest.json (exportedAtUtc, dataset row counts).
  • Tenant-scoped via the standard global query filters — an export contains only the caller's account rows.

CSV rules:

  • RFC 4180 quoting/escaping; UTF-8 with BOM (Excel compatibility); CRLF line endings.
  • ISO-8601 dates/timestamps (UTC); money as *MinorUnits + currencyCode/currencyMinorUnit columns — no locale formatting, no decimal conversion.
  • Formula-injection guard: any cell starting with =, +, -, @ gets a leading ' (spreadsheet apps execute formulas in untrusted CSVs; reason/note/name fields are user input).

Docs / deploy:

  • Self-hosted backup instructions (pg_dump / restore) in the deploy README.

SPA:

  • Export page (admin-only nav, same gating as Audit): per-dataset download buttons + "Download full backup (zip)".

Sync: GLOSSARY.md (Export, Full account export) + Help page section.

Tests

  • Worker → 403 on both routes; admin → 200.
  • CSV shape: header row, RFC 4180 escaping (embedded quote/comma/newline), formula-injection prefix.
  • Zip: contains all 19 CSVs + manifest with correct counts.
  • Tenant isolation: tenant B's export never contains tenant A's rows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions