Skip to main content

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}