diff --git a/docs/privacy/data-inventory.md b/docs/privacy/data-inventory.md index f606360..828331b 100644 --- a/docs/privacy/data-inventory.md +++ b/docs/privacy/data-inventory.md @@ -164,19 +164,19 @@ Appointments track client and third-party meetings scheduled by the studio owner Proposals track pre-contractual commercial quotations, package/add-on option selections, and formal client contract acceptances or declines. -| Data Field / Entity | Purpose | Lawful Basis (GDPR) | Retention Period | Deletion / Export | -| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `proposals.id` | Monotonic UUIDv7 entity identifier | Art. 6(1)(b) Contract / pre-contractual steps | Retained with proposal record | Hard-deleted on project deletion or client erasure (unaccepted proposals) | -| `proposals.project_id` | FK to `projects.id` associating quotation with specific photography engagement | Art. 6(1)(b) Contract / pre-contractual steps | Lifetime of project profile | Cascade deleted on project deletion; unaccepted proposals deleted on client erasure (Art. 17) | -| `proposals.client_id` | FK to `clients.id` linking commercial agreement to client profile | Art. 6(1)(b) Contract / pre-contractual steps | Lifetime of client profile; accepted proposals held under §147 AO / §257 HGB | Unaccepted proposals erased on client erasure (Art. 17); accepted proposals held under statutory commercial hold (TASK-0059) | -| `proposals.title` | Descriptive title of the proposal | Art. 6(1)(b) Pre-contractual steps | Retained with proposal record | Included in DSAR export; erased on client erasure (unaccepted) | -| `proposals.status` | State machine status (`draft`, `sent`, `accepted`, `declined`, `expired`, `superseded`) | Art. 6(1)(b) Pre-contractual steps | Dictates statutory hold: `accepted` triggers 8-year commercial retention (§147 AO / §257 HGB); unaccepted proposals follow client retention | Included in DSAR export; erased on client erasure if not accepted | -| `proposals.token_hash` | SHA-256 digest of secret token for secure customer portal access | Art. 6(1)(b) Pre-contractual steps / Art. 32 Security of processing | Retained while proposal is active / valid | Invalidated on revocation (`token_revoked_at`); erased with proposal record | -| `proposals.accepted_by_name` | Full name of client or authorized representative who accepted proposal | Art. 6(1)(b) Contract / Art. 6(1)(c) Legal obligation (§147 AO) | 8 years from close of calendar year in which proposal was accepted (§147(3) AO, §257(4) HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during mandatory statutory commercial retention period (§147 AO / §257 HGB; TASK-0059); never logged in audit metadata | -| `proposals.accepted_by_email` | Email address of person who accepted proposal (used for confirmation) | Art. 6(1)(b) Contract / Art. 6(1)(c) Legal obligation (§147 AO) | 8 years from close of calendar year in which proposal was accepted (§147(3) AO, §257(4) HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during mandatory statutory commercial retention period (§147 AO / §257 HGB; TASK-0059); never logged in audit metadata | -| `proposals.acceptance_ip_anonymized` | Truncated IP address (IPv4 `/24`, IPv6 `/48`) proving acceptance without persistent single-device identification | Art. 6(1)(f) Legitimate interest (fraud prevention / proof) | 8 years matching accepted contract record | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during statutory hold; never logged in audit metadata | -| `proposals.acceptance_user_agent` | Browser / device user-agent string at time of acceptance | Art. 6(1)(f) Legitimate interest (evidentiary integrity) | 8 years matching accepted contract record | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during statutory hold; never logged in audit metadata | -| `proposals.accepted_options_snapshot` | Immutable JSON snapshot of accepted line items, quantities, and financial totals | Art. 6(1)(b) Contract / Art. 6(1)(c) Statutory commercial record | 8 years matching commercial agreement (§147 AO / §257 HGB) | Included in client DSAR export; permanently locked against modification; held under statutory retention (TASK-0059) | -| `proposals.decline_reason` | Optional free-text reason provided by client when declining proposal | Art. 6(1)(b) Pre-contractual steps | Retained until proposal purge or client erasure | Included in client DSAR export; deleted on lead/client erasure; never logged in audit metadata (only boolean `has_decline_reason` logged in audit metadata) | -| `proposals.internal_notes` | Photographer internal pricing and negotiation notes | Art. 6(1)(f) Legitimate interest (studio business management) | Retained with proposal record | Excluded from client portal and public token view (`internalNotes: null`); included in owner audit export; deleted on client erasure if not subject to statutory hold | -| `proposal_line_items.*` | Quotation line items (package/catalogue snapshots, unit prices, tax rates, quantities) | Art. 6(1)(b) Pre-contractual steps / Contract | Follows parent proposal lifecycle | Included in DSAR export; cascade deleted on parent proposal deletion | +| Data Field / Entity | Purpose | Lawful Basis (GDPR) | Retention Period | Deletion / Export | +| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `proposals.id` | Monotonic UUIDv7 entity identifier | Art. 6(1)(b) Contract / pre-contractual steps | Retained with proposal record | Hard-deleted on project deletion or client erasure (unaccepted proposals) | +| `proposals.project_id` | FK to `projects.id` associating quotation with specific photography engagement | Art. 6(1)(b) Contract / pre-contractual steps | Lifetime of project profile | Cascade deleted on project deletion; unaccepted proposals deleted on client erasure (Art. 17) | +| `proposals.client_id` | FK to `clients.id` linking commercial agreement to client profile | Art. 6(1)(b) Contract / pre-contractual steps | Lifetime of client profile; accepted proposals held under §147 AO / §257 HGB | Unaccepted proposals erased on client erasure (Art. 17); accepted proposals held under statutory commercial hold (TASK-0059) | +| `proposals.title` | Descriptive title of the proposal | Art. 6(1)(b) Pre-contractual steps | Retained with proposal record | Included in DSAR export; erased on client erasure (unaccepted) | +| `proposals.status` | State machine status (`draft`, `sent`, `accepted`, `declined`, `expired`, `superseded`) | Art. 6(1)(b) Pre-contractual steps / §147 AO | Dictates statutory hold: `accepted` triggers 10-year commercial retention (§147 AO / §257 HGB); unaccepted proposals follow client retention | Included in DSAR export; erased on client erasure if not accepted | +| `proposals.token_hash` | SHA-256 digest of secret token for secure customer portal access | Art. 6(1)(b) Pre-contractual steps / Art. 32 Security of processing | Retained while proposal is active / valid | Invalidated on revocation (`token_revoked_at`); erased with proposal record | +| `proposals.accepted_by_name` | Full name of client or authorized representative who accepted proposal | Art. 6(1)(b) / §147 AO (Contract / statutory legal obligation) | 10-year statutory retention from close of calendar year in which proposal was accepted (§147(3) AO, §257(4) HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during mandatory statutory commercial retention period (§147 AO / §257 HGB; TASK-0059); never logged in audit metadata | +| `proposals.accepted_by_email` | Email address of person who accepted proposal (used for confirmation) | Art. 6(1)(b) / §147 AO (Contract / statutory legal obligation) | 10-year statutory retention from close of calendar year in which proposal was accepted (§147(3) AO, §257(4) HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during mandatory statutory commercial retention period (§147 AO / §257 HGB; TASK-0059); never logged in audit metadata | +| `proposals.acceptance_ip_anonymized` | Truncated IP address (IPv4 `/24`, IPv6 `/48`) proving acceptance without persistent single-device identification | Art. 6(1)(b) / §147 AO / Art. 6(1)(f) Legitimate interest | 10-year statutory retention matching accepted contract record (§147 AO / §257 HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during statutory hold; never logged in audit metadata | +| `proposals.acceptance_user_agent` | Browser / device user-agent string at time of acceptance | Art. 6(1)(b) / §147 AO / Art. 6(1)(f) Legitimate interest | 10-year statutory retention matching accepted contract record (§147 AO / §257 HGB) | Included in client DSAR export (Art. 15); exempt from Art. 17 erasure during statutory hold; never logged in audit metadata | +| `proposals.accepted_options_snapshot` | Immutable JSON snapshot of accepted line items, quantities, and financial totals | Art. 6(1)(b) / §147 AO (Statutory commercial agreement record) | 10-year statutory retention matching commercial agreement (§147 AO / §257 HGB) | Included in client DSAR export; permanently locked against modification; held under statutory retention (TASK-0059) | +| `proposals.decline_reason` | Optional free-text reason provided by client when declining proposal | Art. 6(1)(b) Pre-contractual steps | Retained until proposal purge or client erasure | Included in client DSAR export; deleted on lead/client erasure; never logged in audit metadata (only boolean `has_decline_reason` logged in audit metadata) | +| `proposals.internal_notes` | Photographer internal pricing and negotiation notes | Art. 6(1)(f) Legitimate interest (studio business management) | Retained with proposal record | Excluded from client portal and public token view (`internalNotes: null`); included in owner audit export; deleted on client erasure if not subject to statutory hold | +| `proposal_line_items.*` | Quotation line items (package/catalogue snapshots, unit prices, tax rates, quantities) | Art. 6(1)(b) Pre-contractual steps / Contract | Follows parent proposal lifecycle | Included in DSAR export; cascade deleted on parent proposal deletion | diff --git a/messages/de.json b/messages/de.json index d153738..e59e3d8 100644 --- a/messages/de.json +++ b/messages/de.json @@ -1381,6 +1381,9 @@ "holds": { "active_project": "Laufendes Projekt / Auftrag", "upcoming_shoot": "Bevorstehendes geplantes Shooting", + "statutory": { + "commercial_document": "Gesetzliche Aufbewahrungspflicht für Handelsdokumente (§ 147 AO, § 257 HGB)" + }, "manual": { "dispute": "Rechtsstreitigkeit", "statutory": "Gesetzliche Anforderung", diff --git a/messages/en.json b/messages/en.json index a960fdf..fb58902 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1381,6 +1381,9 @@ "holds": { "active_project": "Active commission / project", "upcoming_shoot": "Upcoming scheduled shoot", + "statutory": { + "commercial_document": "Statutory commercial agreement (§147 AO, §257 HGB)" + }, "manual": { "dispute": "Dispute resolution", "statutory": "Statutory requirement", diff --git a/src/components/clients/erasure-dialog.tsx b/src/components/clients/erasure-dialog.tsx index 7c558fd..8dfd400 100644 --- a/src/components/clients/erasure-dialog.tsx +++ b/src/components/clients/erasure-dialog.tsx @@ -263,7 +263,12 @@ export function ErasureDialogInner({