anvilsign in

collin/anvil

1//! Persisted domain types, defined as Toasty models. Tables are created from
2//! these definitions via [`crate::db`]'s `push_schema`.
3//!
4//! Foreign keys are kept as plain scalar fields (`owner_id`, `user_id`) and
5//! queried explicitly, rather than declaring Toasty relations — simpler and a
6//! good fit for our small schema.
7
8/// A registered user account.
9#[derive(Debug, toasty::Model)]
10pub struct User {
11 #[key]
12 #[auto]
13 pub id: i64,
14 #[unique]
15 pub username: String,
16 pub email: String,
17 /// Argon2 PHC-format password hash.
18 pub password_hash: String,
19 pub is_admin: bool,
20 /// Unix timestamp (seconds) of account creation.
21 pub created_at: i64,
22}
23
24/// A hosted repository, owned by a [`User`].
25#[derive(Debug, toasty::Model)]
26pub struct Repository {
27 #[key]
28 #[auto]
29 pub id: i64,
30 #[index]
31 pub owner_id: i64,
32 pub name: String,
33 pub description: String,
34 pub is_private: bool,
35 /// Short name of the default branch, e.g. `main`.
36 pub default_branch: String,
37 pub created_at: i64,
38 /// Push-mirror remote: after every successful push, refs are mirrored to
39 /// this git URL (`git push --mirror`). Empty disables mirroring. New
40 /// columns go last so `ALTER TABLE ADD COLUMN` on existing databases
41 /// agrees with the fresh-schema column order.
42 pub mirror_url: String,
43}
44
45/// A CI run for a pushed commit.
46///
47/// `status` is one of `queued`, `running`, `success`, `failure` (a step exited
48/// non-zero), or `error` (the runner itself failed). `started_at`/`finished_at`
49/// are 0 until they occur.
50#[derive(Clone, Debug, toasty::Model)]
51pub struct CiRun {
52 #[key]
53 #[auto]
54 pub id: i64,
55 #[index]
56 pub repo_id: i64,
57 /// Full commit SHA the run is for.
58 pub commit: String,
59 /// Short branch name that was pushed (e.g. `main`).
60 pub ref_name: String,
61 pub status: String,
62 /// Accumulated run log.
63 pub log: String,
64 pub created_at: i64,
65 pub started_at: i64,
66 pub finished_at: i64,
67}
68
69/// One artifact produced by a CI run, stored on disk under
70/// `data_dir/artifacts/{repo_id}/{commit}/` (see `docs/ci-artifacts.md`).
71///
72/// `commit` is denormalized from the run so per-commit lookups (the
73/// latest-on-branch alias) don't join through runs.
74#[derive(Clone, Debug, toasty::Model)]
75pub struct CiArtifact {
76 #[key]
77 #[auto]
78 pub id: i64,
79 #[index]
80 pub run_id: i64,
81 #[index]
82 pub repo_id: i64,
83 /// Full commit SHA the producing run was for.
84 pub commit: String,
85 /// Declared artifact name (unique within a pipeline, not globally).
86 pub name: String,
87 /// Total size in bytes (summed over files for directory artifacts).
88 pub size: i64,
89 /// Directory artifact (stored as a tarball, or extracted when `browse`).
90 pub is_dir: bool,
91 /// Served as a browsable static site rather than a download.
92 pub browse: bool,
93 /// JSON object of metadata-extractor key → output.
94 pub meta: String,
95 pub created_at: i64,
96}
97
98/// An issue on a repository. `number` is the user-facing per-repo sequence
99/// (`#1`, `#2`, …); `id` stays the global key. `state` is `open` or `closed`.
100///
101/// Numbering is assigned as max+1 at creation; with a single server process
102/// (our deployment shape) that cannot race.
103#[derive(Clone, Debug, toasty::Model)]
104pub struct Issue {
105 #[key]
106 #[auto]
107 pub id: i64,
108 #[index]
109 pub repo_id: i64,
110 pub number: i64,
111 pub title: String,
112 /// Markdown body (may be empty).
113 pub body: String,
114 pub author_id: i64,
115 pub state: String,
116 pub created_at: i64,
117 /// Bumped on comments and state changes, for "recently active" ordering.
118 pub updated_at: i64,
119}
120
121/// A comment on an [`Issue`].
122#[derive(Clone, Debug, toasty::Model)]
123pub struct IssueComment {
124 #[key]
125 #[auto]
126 pub id: i64,
127 #[index]
128 pub issue_id: i64,
129 pub author_id: i64,
130 /// Markdown body.
131 pub body: String,
132 pub created_at: i64,
133}
134
135/// A web login session, keyed by an opaque random token stored in a cookie.
136#[derive(Debug, toasty::Model)]
137pub struct Session {
138 #[key]
139 pub token: String,
140 #[index]
141 pub user_id: i64,
142 pub created_at: i64,
143 /// Unix timestamp (seconds) after which the session is invalid.
144 pub expires_at: i64,
145}
146
147/// An uploaded file (e.g. an image pasted into the file editor), stored
148/// outside git at `data_dir/attachments/{repo_id}/{hash}` so large binaries
149/// never enter the repository's history. Markdown carries only the serve URL.
150///
151/// Content-addressed: `hash` is the lowercase hex SHA-256 of the bytes, so the
152/// same content uploaded twice to a repo dedupes to one file. Lookups and GC
153/// scope by `repo_id`, which also gates serving by the repo's read access.
154#[derive(Clone, Debug, toasty::Model)]
155pub struct Attachment {
156 #[key]
157 #[auto]
158 pub id: i64,
159 #[index]
160 pub repo_id: i64,
161 /// Lowercase hex SHA-256 of the content — both the dedup key and the path
162 /// component under the repo's attachment directory.
163 pub hash: String,
164 /// MIME type to serve the bytes with (e.g. `image/png`).
165 pub content_type: String,
166 pub size: i64,
167 /// The user who first uploaded this content to the repo.
168 pub uploader_id: i64,
169 pub created_at: i64,
170}
171
172/// A registered SSH public key, used to authenticate git-over-SSH connections.
173#[derive(Debug, toasty::Model)]
174pub struct SshKey {
175 #[key]
176 #[auto]
177 pub id: i64,
178 #[index]
179 pub user_id: i64,
180 pub title: String,
181 /// Canonical SHA256 fingerprint, e.g. `SHA256:…`.
182 #[unique]
183 pub fingerprint: String,
184 /// Normalized OpenSSH public-key line.
185 pub content: String,
186 pub created_at: i64,
187}