1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! `cratefield-module-privacy`: what this deployment holds about a person, and
//! everything it holds about one.
//!
//! The module knows no venture's schema. Every table it reads is one another
//! module declared through
//! [`Module::personal_data`](cratefield_core::Module::personal_data), composed
//! at build into the
//! [`PersonalDataCatalog`](cratefield_core::PersonalDataCatalog) this reads. Compose it and a
//! venture gets subject access over whatever else it composed, with no wiring:
//!
//! ```no_run
//! use cratefield_module_privacy::Privacy;
//!
//! let module = Privacy::new();
//! ```
//!
//! **Four routes: two read, two erase.**
//!
//! - `GET /v1/privacy/manifest` — the table a privacy page publishes: every
//! declaration, its kind, what erasure would do to it, and the sentence the
//! owning module wrote. No database, no subject, no authentication: it
//! describes the deployment, not a person.
//! - `GET /v1/privacy/export?subject=<id>` — every row every module holds for
//! one subject. Admin-guarded, because it returns somebody's data.
//! - `POST /v1/privacy/erase` — the preview: per table, the action erasure
//! takes (`erase`, `anonymise` or `retain`) and the rows it matches, plus a
//! signed confirmation token that lives 15 minutes. Writes nothing.
//! Admin-guarded.
//! - `POST /v1/privacy/erase/confirm` — carries out the erasure the token
//! names, in one atomic batch, then re-counts every table whose action is
//! `erase` and fails if any rows remain. The subject comes from the token,
//! never the body. Admin-guarded.
//!
//! Erasure is two steps because it cannot be undone and one HTTP call is easy
//! to send by mistake: the preview is the moment an operator reads what would
//! go, and what would be kept, before anything does.
//!
//! **The manifest is the point.** A privacy page written beside the schema
//! drifts from it the first time a migration lands and nobody remembers the
//! page. A page rendered from this endpoint cannot: the sentence a member reads
//! is the sentence the module that owns the table wrote.
//!
//! What catches a table nobody declared is `cratefield_core::undeclared_tables`,
//! through `cratefield_testing::conformance` — a **kit check, not a build
//! error** (issue #268). This comment said "build error" until #268 made the
//! opposite choice deliberately: silence is legitimate for a module with no
//! tables, and a venture should not be unable to boot because some module's
//! author has not got to this yet. The place a module is supposed to be
//! complete is its own test suite. Declaring a table the module does *not*
//! own is still a build error, which is the rule this one was confused with.
use ;
use Arc;
/// Subject access and erasure over whatever the venture composed.