systemprompt_database/lifecycle/installation/report.rs
1//! Outcome of a schema installation that succeeded but left typed drift
2//! behind: a declared foreign key an established database could not create.
3//! Callers surface the report — health endpoints, `infra db migrate` — rather
4//! than reading it from the log.
5//!
6//! Copyright (c) systemprompt.io — Business Source License 1.1.
7//! See <https://systemprompt.io> for licensing details.
8
9use serde::Serialize;
10use systemprompt_identifiers::ExtensionId;
11
12use super::undeclared::SchemaResidue;
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
15pub struct ForeignKeyDrift {
16 pub extension: ExtensionId,
17 pub table: String,
18 pub constraint: String,
19 pub sql: String,
20 pub cause: String,
21}
22
23/// What `install_extension_schemas*` applied and what it could not.
24///
25/// `foreign_key_drift` is non-empty only for an established extension whose
26/// declarative foreign key cannot be created; the install still committed
27/// every other statement. A fresh database never reports drift — the same
28/// condition fails the install there. `residue` is what the database holds
29/// that no registered extension declares (tables and migration ledgers a
30/// deleted crate left behind); it never fails an install and is reported so
31/// a drop migration can be written.
32#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
33pub struct SchemaInstallReport {
34 pub foreign_key_drift: Vec<ForeignKeyDrift>,
35 pub residue: SchemaResidue,
36}
37
38impl SchemaInstallReport {
39 #[must_use]
40 pub const fn is_clean(&self) -> bool {
41 self.foreign_key_drift.is_empty()
42 }
43
44 #[must_use]
45 pub const fn is_tidy(&self) -> bool {
46 self.residue.is_empty()
47 }
48}