---
url: https://docs.nemo12.com/reference/data-dictionary/privacy-audit.md
description: >-
  Từ điển dữ liệu D1, domain Quyền riêng tư & Audit: 3 bảng, consents tới
  retention_policies; cột, kiểu, khoá ngoại, index.
---

# Data Dictionary · Quyền riêng tư & Audit

> ⚙️ **Trang này sinh tự động** từ source code bằng `scripts/gen-reference.mjs` — đừng sửa tay, sửa code rồi chạy `npm run gen:reference`.

Thuộc [Data Dictionary](../data-dictionary.md). 3 bảng, `consents` tới `retention_policies`.

## `consents`

\--------------------------------------------------------------------------- 2. consents — đồng thuận parent-first theo từng scope (AS-07.3.2 🔴) --------------------------------------------------------------------------- Không có dòng granted=1 cho scope nào thì tính năng thu thập dữ liệu của scope đó KHÔNG được bật. Đồng thuận là bản ghi có thời điểm và có phiên bản chính sách — rút lại được (revoked_at), không phải một cờ boolean bị ghi đè mất dấu.

migration: `0033_audit_privacy.sql`

| Cột | Kiểu | Ràng buộc / ghi chú |
| --- | --- | --- |
| `id` | TEXT | PRIMARY KEY |
| `family_id` | TEXT | NOT NULL REFERENCES families(id) |
| `learner_id` | TEXT | REFERENCES learners(id),   -- NULL = đồng thuận ở mức gia đình |
| `guardian_user_id` | TEXT | NOT NULL REFERENCES users(id),  -- người lớn đã bấm đồng ý |
| `scope` | TEXT | NOT NULL CHECK (scope IN ( |
| `granted` | INTEGER | NOT NULL DEFAULT 0,        -- 1 = đang đồng ý, 0 = từ chối/đã rút |
| `granted_at` | TEXT | — |
| `revoked_at` | TEXT | — |
| `policy_version` | TEXT | NOT NULL,              -- phiên bản văn bản chính sách lúc bấm đồng ý |
| `evidence_json` | TEXT | ,                        -- ip, user_agent, màn hình nào, nút nào |
| `created_at` | TEXT | NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) |

**Khóa ngoại:** `family_id` → `families` · `learner_id` → `learners` · `guardian_user_id` → `users`

**Index:** `idx_consents_scope`(family_id, COALESCE(learner_id,'') UNIQUE · `idx_consents_learner`(learner_id, granted)

## `data_deletion_requests`

\--------------------------------------------------------------------------- 3. data_deletion_requests — đường xoá dữ liệu theo yêu cầu (AS-04.5.2) ---------------------------------------------------------------------------

migration: `0033_audit_privacy.sql`

| Cột | Kiểu | Ràng buộc / ghi chú |
| --- | --- | --- |
| `id` | TEXT | PRIMARY KEY |
| `subject_type` | TEXT | NOT NULL CHECK (subject_type IN ('learner','user','family')) |
| `subject_id` | TEXT | NOT NULL |
| `requested_by` | TEXT | NOT NULL,                -- user id của người yêu cầu (phải là phụ huynh/chủ tài khoản) |
| `requested_at` | TEXT | NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) |
| `status` | TEXT | NOT NULL DEFAULT 'pending' |
| — | *table constraint* | `CHECK (status IN ('pending','in_progress','completed','rejected'))` |
| `completed_at` | TEXT | — |
| `note` | TEXT | -- đã xoá những gì, giữ lại gì và vì sao (vd nghĩa vụ kế toán) |

**Index:** `idx_deletion_status`(status, requested_at) · `idx_deletion_subject`(subject_type, subject_id)

## `retention_policies`

\--------------------------------------------------------------------------- 4. retention_policies — chính sách giữ dữ liệu khai báo được (AS-04.5.1/.5.3/.5.4) --------------------------------------------------------------------------- Cột `rationale` là phần quan trọng nhất: mỗi vùng dữ liệu phải nói được VÌ SAO cần giữ và giữ bao lâu. Đây là nguồn cho data dictionary trả lời AS-04.5.4 (data minimization).

migration: `0033_audit_privacy.sql`

| Cột | Kiểu | Ràng buộc / ghi chú |
| --- | --- | --- |
| `id` | TEXT | PRIMARY KEY |
| `data_domain` | TEXT | NOT NULL,                 -- nhóm dữ liệu theo ngôn ngữ sản phẩm |
| `table_name` | TEXT | NOT NULL |
| `keep_days` | INTEGER | ,                         -- NULL = giữ đến khi tài khoản bị xoá |
| `rationale` | TEXT | NOT NULL,                   -- vì sao giữ, vì sao chừng đó ngày |
| `pii` | INTEGER | NOT NULL DEFAULT 0,            -- 1 = có dữ liệu định danh được |
| `created_at` | TEXT | NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) |

**Index:** `idx_retention_table`(table_name) UNIQUE
