cairn_mod/report.rs
1//! Report domain type — flat projection of the `reports` table
2//! (§F11 intake schema in migrations/0001_init.sql).
3//!
4//! Kept flat (string columns for `subject_type` / `status` rather
5//! than enums) so callers can map directly from `sqlx` rows without
6//! a conversion step, and so the writer's `ResolvedReport` response
7//! and the admin `listReports` / `getReport` handlers share one
8//! type instead of reserializing across three layers.
9
10/// A row from the `reports` table. Field names / types match the
11/// schema 1:1; see `lexicons/tools/cairn/admin/defs.json#reportView`
12/// for the wire projection that admin handlers build from this.
13#[derive(Debug, Clone, sqlx::FromRow)]
14pub struct Report {
15 /// Report row primary key. Stable across a deployment; used
16 /// as the opaque handle by `getReport` / `resolveReport`.
17 pub id: i64,
18 /// RFC-3339 Z with ms precision (§6.1 wire format).
19 pub created_at: String,
20 /// DID of the caller whose service-auth JWT verified at
21 /// `createReport` intake.
22 pub reported_by: String,
23 /// `com.atproto.moderation.defs#reason*` value — see §F11 for
24 /// the accepted set.
25 pub reason_type: String,
26 /// Report body. §F11: never returned by public endpoints,
27 /// never written to logs. Admin handlers enforce via
28 /// `project_for_list` vs `project_for_fetch` in
29 /// `src/server/admin/report_view.rs`.
30 pub reason: Option<String>,
31 /// One of `"account"` / `"record"` per the schema CHECK.
32 pub subject_type: String,
33 /// Subject identifier: for `"account"` this is the DID of the
34 /// account being reported; for `"record"` this is the DID
35 /// portion of the `at://` URI.
36 pub subject_did: String,
37 /// For record subjects, the full `at://` URI. `None` when
38 /// `subject_type == "account"`.
39 pub subject_uri: Option<String>,
40 /// For record subjects, the content-addressed ID pinning the
41 /// reported record version. `None` when `subject_type ==
42 /// "account"`.
43 pub subject_cid: Option<String>,
44 /// One of `"pending"` / `"resolved"` per the schema CHECK.
45 pub status: String,
46 /// When `status == "resolved"`, the RFC-3339 Z timestamp of
47 /// the resolution. `None` while pending.
48 pub resolved_at: Option<String>,
49 /// When resolved, the moderator DID that issued the
50 /// resolution. `None` while pending.
51 pub resolved_by: Option<String>,
52 /// If the resolution emitted a label, its value (the `val`
53 /// field on the emitted label). `None` if resolved without
54 /// labeling.
55 pub resolution_label: Option<String>,
56 /// Free-text resolution rationale (not the same as the
57 /// `reason` — this is the MODERATOR's rationale, recorded at
58 /// resolve time).
59 pub resolution_reason: Option<String>,
60}