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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! The descriptor-provider boundary (#370).
//! Descriptor-dependent CLI commands (`compose`/`verify`/`schema`/`docs`)
//! need the `#[derive(Model)]` descriptors compiled into the *running*
//! binary. The published standalone `djogi` binary links no adopter
//! model crates, so reading the global `inventory` registry directly
//! yields zero adopter models. Injecting a [`DescriptorProvider`] lets an
//! adopter-linked binary supply its own models in place of an empty
//! inventory, while the published binary keeps today's behavior via
//! [`InventoryDescriptorProvider`].
use crate;
use crate;
/// Source of the `#[derive(Model)]` descriptors a descriptor-dependent
/// command operates on.
/// # What
/// Supplies the four descriptor streams the migration projection +
/// docs renderer consume: models, enums, apps, and FK-deferrability
/// sidecars.
/// # Why
/// Injecting this is what lets an adopter-linked `djogi` binary supply
/// its own models in place of `djogi-cli`'s empty inventory (the
/// standalone published binary links no model crates). It is the
/// boundary between "djogi works in its own test suite" and "djogi
/// works for someone who `cargo add djogi`s it".
/// # How
/// The only shipped implementation is [`InventoryDescriptorProvider`],
/// which reads the link-time `inventory` registry — exactly the
/// descriptors compiled into the calling binary. Pass it to
/// [`super::project_from_provider`] /
/// [`super::generate_docs_with_provider`].
/// # Where
/// `djogi_cli::run_with_provider` threads a `&dyn DescriptorProvider`
/// to the per-command functions that need it. Adopters do not implement
/// this trait — they link their model crates and the inventory provider
/// sees them.
/// # Trust
/// This trait is intentionally **open** (not sealed) so tests and future
/// providers (e.g. a fixture provider returning a fixed model set) may
/// implement it. A custom provider is **trusted, framework-shaped
/// code**, not an untrusted-input surface: it only supplies descriptors
/// to the adopter's *own* CLI invocation, where the adopter already
/// controls the linked code. It cannot reach or corrupt any other
/// process's state.
/// # Boundary completeness
/// `project_from_provider` reads models/enums/apps/deferrability through
/// this trait, so a non-inventory provider yields a *complete*
/// projection. The relation-accessor collision gate
/// (`ReverseRelationMarker`) is a link-time validation of the binary's
/// Rust accessors — not descriptor data — and stays an ambient pre-gate
/// inside `project_from_provider`, documented as the one deliberate
/// ambient read.
/// The link-time inventory-backed [`DescriptorProvider`] — the only
/// shipped implementation.
/// # What
/// Reads the `inventory` registry: exactly the `#[derive(Model)]` /
/// `#[derive(DjogiEnum)]` / `djogi::apps!` items compiled into the
/// calling binary.
/// # Why
/// Reproduces today's CLI behavior under dependency injection. The
/// published standalone `djogi` binary uses it and sees zero adopter
/// models; an adopter-linked binary uses the same type and sees its own
/// models, because they are linked into *that* binary's inventory.
/// # How
/// ```no_run
/// use djogi::migrate::{DescriptorProvider, InventoryDescriptorProvider};
/// let provider = InventoryDescriptorProvider::new();
/// let models = provider.models(); // every #[derive(Model)] in this binary
/// ```
;