@variance-authority/tribunal 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/LICENSE +21 -0
  3. package/README.md +506 -0
  4. package/dist/__fixtures__/review.d.ts +47 -0
  5. package/dist/__fixtures__/review.js +145 -0
  6. package/dist/__fixtures__/review.js.map +1 -0
  7. package/dist/bindings.d.ts +134 -0
  8. package/dist/bindings.js +88 -0
  9. package/dist/bindings.js.map +1 -0
  10. package/dist/changelog.d.ts +132 -0
  11. package/dist/changelog.js +129 -0
  12. package/dist/changelog.js.map +1 -0
  13. package/dist/history-queries.d.ts +82 -0
  14. package/dist/history-queries.js +200 -0
  15. package/dist/history-queries.js.map +1 -0
  16. package/dist/history-rows.d.ts +42 -0
  17. package/dist/history-rows.js +148 -0
  18. package/dist/history-rows.js.map +1 -0
  19. package/dist/history.d.ts +40 -0
  20. package/dist/history.js +186 -0
  21. package/dist/history.js.map +1 -0
  22. package/dist/index.d.ts +13 -0
  23. package/dist/index.js +12 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/migration-steps.d.ts +32 -0
  26. package/dist/migration-steps.js +303 -0
  27. package/dist/migration-steps.js.map +1 -0
  28. package/dist/migrations.d.ts +58 -0
  29. package/dist/migrations.js +283 -0
  30. package/dist/migrations.js.map +1 -0
  31. package/dist/next.d.ts +94 -0
  32. package/dist/next.js +44 -0
  33. package/dist/next.js.map +1 -0
  34. package/dist/node/bin.d.ts +120 -0
  35. package/dist/node/bin.js +337 -0
  36. package/dist/node/bin.js.map +1 -0
  37. package/dist/node/bucket.d.ts +58 -0
  38. package/dist/node/bucket.js +142 -0
  39. package/dist/node/bucket.js.map +1 -0
  40. package/dist/node/database.d.ts +33 -0
  41. package/dist/node/database.js +157 -0
  42. package/dist/node/database.js.map +1 -0
  43. package/dist/node/index.d.ts +43 -0
  44. package/dist/node/index.js +43 -0
  45. package/dist/node/index.js.map +1 -0
  46. package/dist/node/serve.d.ts +81 -0
  47. package/dist/node/serve.js +193 -0
  48. package/dist/node/serve.js.map +1 -0
  49. package/dist/node/ui-assets.d.ts +47 -0
  50. package/dist/node/ui-assets.js +60 -0
  51. package/dist/node/ui-assets.js.map +1 -0
  52. package/dist/review-ingest.d.ts +24 -0
  53. package/dist/review-ingest.js +184 -0
  54. package/dist/review-ingest.js.map +1 -0
  55. package/dist/review-read.d.ts +87 -0
  56. package/dist/review-read.js +361 -0
  57. package/dist/review-read.js.map +1 -0
  58. package/dist/review-rows.d.ts +30 -0
  59. package/dist/review-rows.js +67 -0
  60. package/dist/review-rows.js.map +1 -0
  61. package/dist/review-types.d.ts +414 -0
  62. package/dist/review-types.js +2 -0
  63. package/dist/review-types.js.map +1 -0
  64. package/dist/review-write.d.ts +35 -0
  65. package/dist/review-write.js +86 -0
  66. package/dist/review-write.js.map +1 -0
  67. package/dist/review.d.ts +53 -0
  68. package/dist/review.fixtures.d.ts +47 -0
  69. package/dist/review.fixtures.js +145 -0
  70. package/dist/review.fixtures.js.map +1 -0
  71. package/dist/review.js +245 -0
  72. package/dist/review.js.map +1 -0
  73. package/dist/schema.d.ts +36 -0
  74. package/dist/schema.js +39 -0
  75. package/dist/schema.js.map +1 -0
  76. package/dist/store.d.ts +58 -0
  77. package/dist/store.js +278 -0
  78. package/dist/store.js.map +1 -0
  79. package/dist/testing.d.ts +38 -0
  80. package/dist/testing.js +92 -0
  81. package/dist/testing.js.map +1 -0
  82. package/dist/ui/__probe.d.ts +3 -0
  83. package/dist/ui/__probe.js +5 -0
  84. package/dist/ui/__probe.js.map +1 -0
  85. package/dist/ui/attribution.d.ts +46 -0
  86. package/dist/ui/attribution.js +79 -0
  87. package/dist/ui/attribution.js.map +1 -0
  88. package/dist/ui/because.d.ts +51 -0
  89. package/dist/ui/because.js +52 -0
  90. package/dist/ui/because.js.map +1 -0
  91. package/dist/ui/browser-entry.d.ts +2 -0
  92. package/dist/ui/browser-entry.js +34 -0
  93. package/dist/ui/browser-entry.js.map +1 -0
  94. package/dist/ui/builds.d.ts +43 -0
  95. package/dist/ui/builds.js +79 -0
  96. package/dist/ui/builds.js.map +1 -0
  97. package/dist/ui/carried.d.ts +73 -0
  98. package/dist/ui/carried.js +63 -0
  99. package/dist/ui/carried.js.map +1 -0
  100. package/dist/ui/cause.d.ts +73 -0
  101. package/dist/ui/cause.js +133 -0
  102. package/dist/ui/cause.js.map +1 -0
  103. package/dist/ui/change-story.d.ts +153 -0
  104. package/dist/ui/change-story.js +253 -0
  105. package/dist/ui/change-story.js.map +1 -0
  106. package/dist/ui/change.d.ts +51 -0
  107. package/dist/ui/change.js +125 -0
  108. package/dist/ui/change.js.map +1 -0
  109. package/dist/ui/client.d.ts +74 -0
  110. package/dist/ui/client.js +88 -0
  111. package/dist/ui/client.js.map +1 -0
  112. package/dist/ui/consumers.d.ts +80 -0
  113. package/dist/ui/consumers.js +125 -0
  114. package/dist/ui/consumers.js.map +1 -0
  115. package/dist/ui/control.d.ts +63 -0
  116. package/dist/ui/control.js +39 -0
  117. package/dist/ui/control.js.map +1 -0
  118. package/dist/ui/crossing.d.ts +55 -0
  119. package/dist/ui/crossing.js +74 -0
  120. package/dist/ui/crossing.js.map +1 -0
  121. package/dist/ui/declarations.d.ts +36 -0
  122. package/dist/ui/declarations.js +73 -0
  123. package/dist/ui/declarations.js.map +1 -0
  124. package/dist/ui/distance.d.ts +154 -0
  125. package/dist/ui/distance.js +180 -0
  126. package/dist/ui/distance.js.map +1 -0
  127. package/dist/ui/divergence.d.ts +40 -0
  128. package/dist/ui/divergence.js +176 -0
  129. package/dist/ui/divergence.js.map +1 -0
  130. package/dist/ui/docket.d.ts +39 -0
  131. package/dist/ui/docket.js +172 -0
  132. package/dist/ui/docket.js.map +1 -0
  133. package/dist/ui/findings.d.ts +42 -0
  134. package/dist/ui/findings.js +110 -0
  135. package/dist/ui/findings.js.map +1 -0
  136. package/dist/ui/foreseen.d.ts +55 -0
  137. package/dist/ui/foreseen.js +91 -0
  138. package/dist/ui/foreseen.js.map +1 -0
  139. package/dist/ui/glance.d.ts +101 -0
  140. package/dist/ui/glance.js +101 -0
  141. package/dist/ui/glance.js.map +1 -0
  142. package/dist/ui/grouping.d.ts +158 -0
  143. package/dist/ui/grouping.js +187 -0
  144. package/dist/ui/grouping.js.map +1 -0
  145. package/dist/ui/handed.d.ts +60 -0
  146. package/dist/ui/handed.js +122 -0
  147. package/dist/ui/handed.js.map +1 -0
  148. package/dist/ui/history.d.ts +88 -0
  149. package/dist/ui/history.js +170 -0
  150. package/dist/ui/history.js.map +1 -0
  151. package/dist/ui/holding.d.ts +84 -0
  152. package/dist/ui/holding.js +90 -0
  153. package/dist/ui/holding.js.map +1 -0
  154. package/dist/ui/impact.d.ts +31 -0
  155. package/dist/ui/impact.js +132 -0
  156. package/dist/ui/impact.js.map +1 -0
  157. package/dist/ui/index.d.ts +21 -0
  158. package/dist/ui/index.js +21 -0
  159. package/dist/ui/index.js.map +1 -0
  160. package/dist/ui/lead.d.ts +35 -0
  161. package/dist/ui/lead.js +34 -0
  162. package/dist/ui/lead.js.map +1 -0
  163. package/dist/ui/look.d.ts +109 -0
  164. package/dist/ui/look.js +248 -0
  165. package/dist/ui/look.js.map +1 -0
  166. package/dist/ui/mark.d.ts +11 -0
  167. package/dist/ui/mark.js +13 -0
  168. package/dist/ui/mark.js.map +1 -0
  169. package/dist/ui/moved.d.ts +121 -0
  170. package/dist/ui/moved.js +143 -0
  171. package/dist/ui/moved.js.map +1 -0
  172. package/dist/ui/navigation.d.ts +26 -0
  173. package/dist/ui/navigation.js +53 -0
  174. package/dist/ui/navigation.js.map +1 -0
  175. package/dist/ui/order.d.ts +113 -0
  176. package/dist/ui/order.js +226 -0
  177. package/dist/ui/order.js.map +1 -0
  178. package/dist/ui/origins.d.ts +42 -0
  179. package/dist/ui/origins.js +149 -0
  180. package/dist/ui/origins.js.map +1 -0
  181. package/dist/ui/outcome.d.ts +93 -0
  182. package/dist/ui/outcome.js +162 -0
  183. package/dist/ui/outcome.js.map +1 -0
  184. package/dist/ui/parted.d.ts +68 -0
  185. package/dist/ui/parted.js +101 -0
  186. package/dist/ui/parted.js.map +1 -0
  187. package/dist/ui/rail.d.ts +31 -0
  188. package/dist/ui/rail.js +21 -0
  189. package/dist/ui/rail.js.map +1 -0
  190. package/dist/ui/reach.d.ts +66 -0
  191. package/dist/ui/reach.js +185 -0
  192. package/dist/ui/reach.js.map +1 -0
  193. package/dist/ui/regions.d.ts +82 -0
  194. package/dist/ui/regions.js +67 -0
  195. package/dist/ui/regions.js.map +1 -0
  196. package/dist/ui/review.bundle.js +69 -0
  197. package/dist/ui/review.d.ts +97 -0
  198. package/dist/ui/review.js +39 -0
  199. package/dist/ui/review.js.map +1 -0
  200. package/dist/ui/root.d.ts +72 -0
  201. package/dist/ui/root.js +102 -0
  202. package/dist/ui/root.js.map +1 -0
  203. package/dist/ui/route.d.ts +95 -0
  204. package/dist/ui/route.js +114 -0
  205. package/dist/ui/route.js.map +1 -0
  206. package/dist/ui/run.d.ts +26 -0
  207. package/dist/ui/run.js +12 -0
  208. package/dist/ui/run.js.map +1 -0
  209. package/dist/ui/sense.d.ts +187 -0
  210. package/dist/ui/sense.js +222 -0
  211. package/dist/ui/sense.js.map +1 -0
  212. package/dist/ui/settled.d.ts +43 -0
  213. package/dist/ui/settled.js +59 -0
  214. package/dist/ui/settled.js.map +1 -0
  215. package/dist/ui/shell.d.ts +76 -0
  216. package/dist/ui/shell.js +65 -0
  217. package/dist/ui/shell.js.map +1 -0
  218. package/dist/ui/shift.d.ts +52 -0
  219. package/dist/ui/shift.js +98 -0
  220. package/dist/ui/shift.js.map +1 -0
  221. package/dist/ui/styles-docket.d.ts +18 -0
  222. package/dist/ui/styles-docket.js +281 -0
  223. package/dist/ui/styles-docket.js.map +1 -0
  224. package/dist/ui/styles-stage.d.ts +18 -0
  225. package/dist/ui/styles-stage.js +92 -0
  226. package/dist/ui/styles-stage.js.map +1 -0
  227. package/dist/ui/styles.d.ts +12 -0
  228. package/dist/ui/styles.js +482 -0
  229. package/dist/ui/styles.js.map +1 -0
  230. package/dist/ui/subject.d.ts +36 -0
  231. package/dist/ui/subject.js +138 -0
  232. package/dist/ui/subject.js.map +1 -0
  233. package/dist/ui/text.d.ts +129 -0
  234. package/dist/ui/text.js +164 -0
  235. package/dist/ui/text.js.map +1 -0
  236. package/dist/ui/variations.d.ts +37 -0
  237. package/dist/ui/variations.js +60 -0
  238. package/dist/ui/variations.js.map +1 -0
  239. package/dist/ui/viewer.d.ts +67 -0
  240. package/dist/ui/viewer.js +246 -0
  241. package/dist/ui/viewer.js.map +1 -0
  242. package/dist/worker-auth.d.ts +48 -0
  243. package/dist/worker-auth.js +74 -0
  244. package/dist/worker-auth.js.map +1 -0
  245. package/dist/worker-entry.d.ts +58 -0
  246. package/dist/worker-entry.js +36 -0
  247. package/dist/worker-entry.js.map +1 -0
  248. package/dist/worker-http.d.ts +39 -0
  249. package/dist/worker-http.js +111 -0
  250. package/dist/worker-http.js.map +1 -0
  251. package/dist/worker-input.d.ts +81 -0
  252. package/dist/worker-input.js +296 -0
  253. package/dist/worker-input.js.map +1 -0
  254. package/dist/worker.d.ts +91 -0
  255. package/dist/worker.js +287 -0
  256. package/dist/worker.js.map +1 -0
  257. package/mark.svg +30 -0
  258. package/migrations/0001_initial.sql +193 -0
  259. package/migrations/0002_changelog.sql +30 -0
  260. package/migrations/0003_accessibility.sql +8 -0
  261. package/migrations/0004_variations.sql +19 -0
  262. package/migrations/0005_reach.sql +26 -0
  263. package/migrations/0006_baseline-size.sql +7 -0
  264. package/migrations/0007_declarations.sql +7 -0
  265. package/migrations/0008_green-because.sql +7 -0
  266. package/migrations/0009_moved-bands.sql +6 -0
  267. package/migrations/0010_composition.sql +15 -0
  268. package/migrations/0011_movements.sql +21 -0
  269. package/migrations/0012_control-size.sql +6 -0
  270. package/package.json +110 -0
  271. package/wrangler.jsonc +45 -0
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Every shape this database has taken since it shipped, one entry per version.
3
+ *
4
+ * Apart from [`migrations.ts`](./migrations.js), which holds the frozen initial
5
+ * set, because the two are edited under opposite rules: that file must never
6
+ * change again, and this one only ever grows. Keeping them in one module meant
7
+ * every new table was appended a screen below a block carrying a comment saying
8
+ * it was frozen.
9
+ *
10
+ * The reading of both — which version they land on, and the batch that applies
11
+ * them — is in [`schema.ts`](./schema.js).
12
+ */
13
+ /**
14
+ * One entry per version after `INITIAL_VERSION`, in order.
15
+ *
16
+ * A database that is already deployed cannot be given a new table by editing the
17
+ * statements that created it — `wrangler d1 migrations apply` tracks which files
18
+ * it has run, and a rewritten `0001` is a file it will never run again. So the
19
+ * initial set is frozen at the version it shipped at and every later shape is a
20
+ * step, generated into its own `.sql` beside it.
21
+ *
22
+ * Each step ends by writing its own version, so a database is never at a version
23
+ * whose shape it does not have — and a fresh database applying the initial set
24
+ * and every step in order arrives at exactly the same place as one that was
25
+ * deployed three versions ago.
26
+ *
27
+ * Additive only. A step that dropped or rewrote a column would be asking an
28
+ * append-only store to forget something, which is the one thing every trigger in
29
+ * this file exists to refuse.
30
+ */
31
+ export const MIGRATIONS = [
32
+ // 3 → 4: why a baseline in this database is what it is.
33
+ [
34
+ // Why a baseline in this database is what it is. One row per **approval**, and
35
+ // the columns are copies rather than a join on purpose: `builds` and
36
+ // `build_subjects` expire under `sweep`, and the explanation of a baseline has
37
+ // to last exactly as long as the baseline, which is forever. A view over those
38
+ // tables would answer correctly right up until the retention window passed and
39
+ // then answer "nothing was ever explained" — the one failure this whole
40
+ // subsystem exists to refuse. It is the same trade the git-LFS half makes by
41
+ // writing the explanation into the commit message instead of a sidecar.
42
+ `CREATE TABLE changelog (
43
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
44
+ project TEXT NOT NULL,
45
+ build TEXT NOT NULL,
46
+ subject TEXT NOT NULL,
47
+ "commit" TEXT NOT NULL,
48
+ intent TEXT,
49
+ decided_by TEXT NOT NULL,
50
+ note TEXT,
51
+ -- The region list the build reported, frozen. Shapes are grouped when
52
+ -- somebody reads: approval here is per subject, so there is no batch at
53
+ -- write time to cluster, and a shape approved across three sessions should
54
+ -- still read as one change.
55
+ regions TEXT NOT NULL,
56
+ at TEXT NOT NULL,
57
+ at_ms INTEGER NOT NULL
58
+ ) STRICT`,
59
+ `CREATE INDEX changelog_recent ON changelog (project, at_ms DESC)`,
60
+ `CREATE INDEX changelog_subject ON changelog (project, subject, at_ms DESC)`,
61
+ `CREATE TRIGGER changelog_is_append_only BEFORE UPDATE ON changelog BEGIN
62
+ SELECT RAISE(ABORT, 'the changelog is append-only: an edited explanation is an explanation of a baseline that was promoted for a different reason');
63
+ END`,
64
+ `CREATE TRIGGER changelog_is_permanent BEFORE DELETE ON changelog BEGIN
65
+ SELECT RAISE(ABORT, 'the changelog is append-only: a deleted entry leaves a baseline nobody can account for, which is the state this table exists to end');
66
+ END`,
67
+ `UPDATE schema_version SET version = 4`,
68
+ ],
69
+ // 4 → 5: browser accessibility evidence is verdict-bearing baseline state.
70
+ [
71
+ `ALTER TABLE baselines ADD COLUMN accessibility TEXT`,
72
+ `ALTER TABLE build_subjects ADD COLUMN signals TEXT`,
73
+ `ALTER TABLE build_subjects ADD COLUMN candidate_accessibility TEXT`,
74
+ `UPDATE schema_version SET version = 5`,
75
+ ],
76
+ // 5 → 6: what a run read about its own subjects, with no baseline in it.
77
+ [
78
+ // A table rather than columns on `build_subjects`, because a variation is
79
+ // about a *pair*: the row belongs to the subject, but what it says is how
80
+ // that subject stands against another subject in the same run. A subject can
81
+ // also be a variation while having no observation at all — a story added
82
+ // behind a flag is `new`, and the flag's effect is exactly what this row
83
+ // carries — so the two are not the same set.
84
+ //
85
+ // Every optional field is nullable and none of them is defaulted. `identical`
86
+ // has three states and they are three different claims: `1` the pair renders
87
+ // to one hash, `0` it does not, `NULL` nothing compared them, because the
88
+ // parent the declaration named is not in this run. Writing `0` for the third
89
+ // would report a broken link as a measured difference.
90
+ `CREATE TABLE build_variations (
91
+ project TEXT NOT NULL,
92
+ build TEXT NOT NULL,
93
+ subject TEXT NOT NULL,
94
+ parent TEXT,
95
+ identical INTEGER,
96
+ bands TEXT,
97
+ unobserved TEXT,
98
+ components TEXT,
99
+ digest TEXT,
100
+ how TEXT,
101
+ because TEXT NOT NULL,
102
+ PRIMARY KEY (project, build, subject)
103
+ ) STRICT`,
104
+ `UPDATE schema_version SET version = 6`,
105
+ ],
106
+ // 6 → 7: what the commit reaches, which is the only thing here that names a
107
+ // file somebody edited.
108
+ [
109
+ // Two tables rather than one, and the split is the whole point of the shape.
110
+ //
111
+ // The build row exists whenever a run had a diff to read, *including* when
112
+ // the walk refused to attribute it — a changed file the graph does not hold,
113
+ // a diff entirely outside the graph, a diff reaching no component. In that
114
+ // case `whole` carries the reason and there are no subject rows.
115
+ //
116
+ // So zero subject rows has two meanings and `whole` is what separates them:
117
+ // with a reason, nothing could be attributed and every subject must be read
118
+ // as possibly reached; without one, the commit was understood and simply
119
+ // reached none of the subjects whose baselines said what they were made of.
120
+ // Those support opposite decisions, and one table could not hold both.
121
+ `CREATE TABLE build_reach (
122
+ project TEXT NOT NULL,
123
+ build TEXT NOT NULL,
124
+ against_ref TEXT NOT NULL,
125
+ changed TEXT NOT NULL,
126
+ components TEXT NOT NULL,
127
+ whole TEXT,
128
+ unscanned TEXT,
129
+ opaque TEXT,
130
+ PRIMARY KEY (project, build)
131
+ ) STRICT`,
132
+ // `through` and `trail` are nullable together with `reached = 0`: a subject
133
+ // this diff does not reach has no chain to print, and an empty array stored
134
+ // where a chain belongs would render as a trail of no hops rather than as no
135
+ // trail. A subject whose baseline recorded no component list is not a row at
136
+ // all — the run cannot say what it is made of, and `reached = 0` would be an
137
+ // assertion nobody made.
138
+ `CREATE TABLE build_reach_subjects (
139
+ project TEXT NOT NULL,
140
+ build TEXT NOT NULL,
141
+ subject TEXT NOT NULL,
142
+ reached INTEGER NOT NULL,
143
+ through TEXT,
144
+ trail TEXT,
145
+ because TEXT NOT NULL,
146
+ PRIMARY KEY (project, build, subject)
147
+ ) STRICT`,
148
+ `UPDATE schema_version SET version = 7`,
149
+ ],
150
+ // 7 → 8: how large the baseline was, which is sometimes the change itself.
151
+ [
152
+ // Nullable, and left null on every row written before this step. A number
153
+ // backfilled from `candidate_width` would be an invention that reads exactly
154
+ // like a measurement, and the whole point of the column is to be able to say
155
+ // the two differ.
156
+ `ALTER TABLE build_subjects ADD COLUMN baseline_width INTEGER`,
157
+ `ALTER TABLE build_subjects ADD COLUMN baseline_height INTEGER`,
158
+ `UPDATE schema_version SET version = 8`,
159
+ ],
160
+ // 8 → 9: what the config declared, and what each declaration did.
161
+ [
162
+ // The audit that makes an ignore safe to have, kept where it outlives the run.
163
+ // A mask grows over a real regression silently, and the only thing that catches
164
+ // it is a rule absorbing nothing *again* — a comparison a CI log cannot answer.
165
+ //
166
+ // Two columns rather than a row per rule: the ledger is small, is always read
167
+ // with its build, and a table here would be a second vocabulary for one fact.
168
+ //
169
+ // Null is *the writer said nothing*, which on this format is also what a
170
+ // config with no rules produces — one absence, and the store invents no
171
+ // second. What it must not become is a ledger of zero rules: an unaudited
172
+ // build, reported as an audited one that found nothing.
173
+ `ALTER TABLE builds ADD COLUMN ignores TEXT`,
174
+ `ALTER TABLE builds ADD COLUMN sensitivities TEXT`,
175
+ `UPDATE schema_version SET version = 9`,
176
+ ],
177
+ // 9 → 10: which declaration decided each green subject.
178
+ [
179
+ // The ledger added at step 9 says what each rule absorbed *across the run*.
180
+ // It cannot say which rule absorbed *this subject*, and that is the sentence
181
+ // the report prints beside every green-by-declaration name. Without these
182
+ // two columns a service reading its own store had to answer `the run did not
183
+ // record which rule absorbed it` about a run that recorded it — the store's
184
+ // own omission, rendered as the observer's.
185
+ //
186
+ // Null keeps meaning the writer said nothing: `ignored: {pixels: 0, boxes: 2}`
187
+ // is a rule that caught nothing here, which is not the same fact and is the
188
+ // one that turns a mask into a blind spot.
189
+ `ALTER TABLE build_subjects ADD COLUMN ignored TEXT`,
190
+ `ALTER TABLE build_subjects ADD COLUMN relaxed TEXT`,
191
+ `UPDATE schema_version SET version = 10`,
192
+ ],
193
+ // 10 → 11: which component moved, and in which band.
194
+ [
195
+ // `regions` is the raster tier's answer, and it loses the name exactly where
196
+ // a reviewer needs it: a difference that reflows its neighbours merges into
197
+ // one blob, the blob fits no component, and the region resolves to the
198
+ // document root. The semantic tier never lost it — it compares digests, not
199
+ // pixels — but the store had no column for it, so the service could report
200
+ // only what the picture happened to be able to say.
201
+ //
202
+ // Null keeps meaning the run wrote nothing — here, a baseline with no
203
+ // component hashes. `'[]'` is both sides read and every digest matched.
204
+ `ALTER TABLE build_subjects ADD COLUMN moved TEXT`,
205
+ `UPDATE schema_version SET version = 11`,
206
+ ],
207
+ // 11 → 12: what draws what, which is the only record that can answer *why did
208
+ // this move* for a component no file in the diff declares.
209
+ [
210
+ // The import graph climbs. `build_reach` walks from a changed file through
211
+ // its importers, so it names what an edit *could* have reached and can never
212
+ // name anything a changed file draws: `ProductCard` renders `Card`, `Card`
213
+ // renders `CardFooter`, and a walk that only goes upward arrives at none of
214
+ // them. The page was left saying "no rung above holds them" — true, and not
215
+ // a reason.
216
+ //
217
+ // The run already wrote the other direction. `composition.components`
218
+ // carries `within` and `renders` per component, folded over every subject,
219
+ // and the store dropped it at the door.
220
+ //
221
+ // One row per component, not a JSON blob on `builds`: the page asks *who
222
+ // draws this one*, and a census of four hundred components read whole to
223
+ // answer it is the shape that makes a reviewer wait.
224
+ //
225
+ // Every column NOT NULL, including the empty lists. A census that named a
226
+ // component knows all three, and the one ambiguity in them — an empty
227
+ // `created_by` is *this was a production build*, not *nothing mounted it* —
228
+ // belongs to the report that wrote it. A store that answered it with NULL
229
+ // would be inventing a distinction upstream declined to make.
230
+ `CREATE TABLE build_composition (
231
+ project TEXT NOT NULL,
232
+ build TEXT NOT NULL,
233
+ component TEXT NOT NULL,
234
+ subjects TEXT NOT NULL,
235
+ within TEXT NOT NULL,
236
+ created_by TEXT NOT NULL,
237
+ renders TEXT NOT NULL,
238
+ PRIMARY KEY (project, build, component)
239
+ ) STRICT`,
240
+ `UPDATE schema_version SET version = 12`,
241
+ ],
242
+ // 12 → 13: the attribution itself. The census above says who draws what; this
243
+ // says what the run concluded from it about each thing that moved.
244
+ [
245
+ // The store kept the graph and dropped the answer. A run walks the diff,
246
+ // finds the file that declares each moved component, climbs to an edited
247
+ // ancestor when nothing declares it, and writes one sentence per movement
248
+ // into `composition.movements` — and every one of them stopped at the ingest
249
+ // door. The review page then rebuilt a worse version of the same walk out of
250
+ // the census, with no access to the props digests or the control group the
251
+ // run had used, and printed *no rung above holds them* about components the
252
+ // run had already attributed to an edited parent.
253
+ //
254
+ // One row per movement, keyed by the pair it is about. A component moves for
255
+ // its own reason in each subject it moved in — the same `Button` can be
256
+ // `edited` on one page and `upstream` on another — so a table keyed by
257
+ // component alone would keep whichever row was written last and call it the
258
+ // cause everywhere.
259
+ //
260
+ // `also_in` is not a column. It is the subjects of the sibling rows for the
261
+ // same component, and a stored copy is a second answer that can disagree
262
+ // with the first.
263
+ //
264
+ // Nullable is *the rung does not apply*: `file` on anything but `edited`,
265
+ // `upstream` and `through` on anything but `upstream`, `standing` on
266
+ // anything explained. `bands` and `held` are NOT NULL and can be `'[]'`,
267
+ // which in both cases means what the report means by it — for `bands`, that
268
+ // the comparison was name-only and no band is known; for `held`, that the
269
+ // suite offered no control.
270
+ `CREATE TABLE build_movements (
271
+ project TEXT NOT NULL,
272
+ build TEXT NOT NULL,
273
+ subject TEXT NOT NULL,
274
+ component TEXT NOT NULL,
275
+ cause TEXT NOT NULL,
276
+ because TEXT NOT NULL,
277
+ bands TEXT NOT NULL,
278
+ held TEXT NOT NULL,
279
+ file TEXT,
280
+ tokens TEXT,
281
+ upstream TEXT,
282
+ through TEXT,
283
+ standing TEXT,
284
+ PRIMARY KEY (project, build, subject, component)
285
+ ) STRICT`,
286
+ `UPDATE schema_version SET version = 13`,
287
+ ],
288
+ // 13 → 14: the denominator the control group is a numerator of.
289
+ [
290
+ // `held` alone is two opposite findings under one shape. Empty because the
291
+ // component renders nowhere else with these inputs is a suite with nothing to
292
+ // say; empty because it renders in four other places and moved in all four is
293
+ // the suite saying the loudest thing it can — the change reached everything
294
+ // this component draws. The page had to guess, and on any run where the edit
295
+ // landed everywhere it guessed the weak one.
296
+ //
297
+ // Nullable, and null is *the run never said*: reports written before this
298
+ // carry no answer, and `0` is an answer.
299
+ `ALTER TABLE build_movements ADD COLUMN compared INTEGER`,
300
+ `UPDATE schema_version SET version = 14`,
301
+ ],
302
+ ];
303
+ //# sourceMappingURL=migration-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-steps.js","sourceRoot":"","sources":["../src/migration-steps.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Every shape this database has taken since it shipped, one entry per version.\n *\n * Apart from [`migrations.ts`](./migrations.js), which holds the frozen initial\n * set, because the two are edited under opposite rules: that file must never\n * change again, and this one only ever grows. Keeping them in one module meant\n * every new table was appended a screen below a block carrying a comment saying\n * it was frozen.\n *\n * The reading of both — which version they land on, and the batch that applies\n * them — is in [`schema.ts`](./schema.js).\n */\n\n\n/**\n * One entry per version after `INITIAL_VERSION`, in order.\n *\n * A database that is already deployed cannot be given a new table by editing the\n * statements that created it — `wrangler d1 migrations apply` tracks which files\n * it has run, and a rewritten `0001` is a file it will never run again. So the\n * initial set is frozen at the version it shipped at and every later shape is a\n * step, generated into its own `.sql` beside it.\n *\n * Each step ends by writing its own version, so a database is never at a version\n * whose shape it does not have — and a fresh database applying the initial set\n * and every step in order arrives at exactly the same place as one that was\n * deployed three versions ago.\n *\n * Additive only. A step that dropped or rewrote a column would be asking an\n * append-only store to forget something, which is the one thing every trigger in\n * this file exists to refuse.\n */\nexport const MIGRATIONS: readonly (readonly string[])[] = [\n // 3 → 4: why a baseline in this database is what it is.\n [\n // Why a baseline in this database is what it is. One row per **approval**, and\n // the columns are copies rather than a join on purpose: `builds` and\n // `build_subjects` expire under `sweep`, and the explanation of a baseline has\n // to last exactly as long as the baseline, which is forever. A view over those\n // tables would answer correctly right up until the retention window passed and\n // then answer \"nothing was ever explained\" — the one failure this whole\n // subsystem exists to refuse. It is the same trade the git-LFS half makes by\n // writing the explanation into the commit message instead of a sidecar.\n `CREATE TABLE changelog (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n subject TEXT NOT NULL,\n \"commit\" TEXT NOT NULL,\n intent TEXT,\n decided_by TEXT NOT NULL,\n note TEXT,\n -- The region list the build reported, frozen. Shapes are grouped when\n -- somebody reads: approval here is per subject, so there is no batch at\n -- write time to cluster, and a shape approved across three sessions should\n -- still read as one change.\n regions TEXT NOT NULL,\n at TEXT NOT NULL,\n at_ms INTEGER NOT NULL\n ) STRICT`,\n `CREATE INDEX changelog_recent ON changelog (project, at_ms DESC)`,\n `CREATE INDEX changelog_subject ON changelog (project, subject, at_ms DESC)`,\n\n `CREATE TRIGGER changelog_is_append_only BEFORE UPDATE ON changelog BEGIN\n SELECT RAISE(ABORT, 'the changelog is append-only: an edited explanation is an explanation of a baseline that was promoted for a different reason');\n END`,\n `CREATE TRIGGER changelog_is_permanent BEFORE DELETE ON changelog BEGIN\n SELECT RAISE(ABORT, 'the changelog is append-only: a deleted entry leaves a baseline nobody can account for, which is the state this table exists to end');\n END`,\n `UPDATE schema_version SET version = 4`,\n ],\n // 4 → 5: browser accessibility evidence is verdict-bearing baseline state.\n [\n `ALTER TABLE baselines ADD COLUMN accessibility TEXT`,\n `ALTER TABLE build_subjects ADD COLUMN signals TEXT`,\n `ALTER TABLE build_subjects ADD COLUMN candidate_accessibility TEXT`,\n `UPDATE schema_version SET version = 5`,\n ],\n // 5 → 6: what a run read about its own subjects, with no baseline in it.\n [\n // A table rather than columns on `build_subjects`, because a variation is\n // about a *pair*: the row belongs to the subject, but what it says is how\n // that subject stands against another subject in the same run. A subject can\n // also be a variation while having no observation at all — a story added\n // behind a flag is `new`, and the flag's effect is exactly what this row\n // carries — so the two are not the same set.\n //\n // Every optional field is nullable and none of them is defaulted. `identical`\n // has three states and they are three different claims: `1` the pair renders\n // to one hash, `0` it does not, `NULL` nothing compared them, because the\n // parent the declaration named is not in this run. Writing `0` for the third\n // would report a broken link as a measured difference.\n `CREATE TABLE build_variations (\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n subject TEXT NOT NULL,\n parent TEXT,\n identical INTEGER,\n bands TEXT,\n unobserved TEXT,\n components TEXT,\n digest TEXT,\n how TEXT,\n because TEXT NOT NULL,\n PRIMARY KEY (project, build, subject)\n ) STRICT`,\n `UPDATE schema_version SET version = 6`,\n ],\n // 6 → 7: what the commit reaches, which is the only thing here that names a\n // file somebody edited.\n [\n // Two tables rather than one, and the split is the whole point of the shape.\n //\n // The build row exists whenever a run had a diff to read, *including* when\n // the walk refused to attribute it — a changed file the graph does not hold,\n // a diff entirely outside the graph, a diff reaching no component. In that\n // case `whole` carries the reason and there are no subject rows.\n //\n // So zero subject rows has two meanings and `whole` is what separates them:\n // with a reason, nothing could be attributed and every subject must be read\n // as possibly reached; without one, the commit was understood and simply\n // reached none of the subjects whose baselines said what they were made of.\n // Those support opposite decisions, and one table could not hold both.\n `CREATE TABLE build_reach (\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n against_ref TEXT NOT NULL,\n changed TEXT NOT NULL,\n components TEXT NOT NULL,\n whole TEXT,\n unscanned TEXT,\n opaque TEXT,\n PRIMARY KEY (project, build)\n ) STRICT`,\n // `through` and `trail` are nullable together with `reached = 0`: a subject\n // this diff does not reach has no chain to print, and an empty array stored\n // where a chain belongs would render as a trail of no hops rather than as no\n // trail. A subject whose baseline recorded no component list is not a row at\n // all — the run cannot say what it is made of, and `reached = 0` would be an\n // assertion nobody made.\n `CREATE TABLE build_reach_subjects (\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n subject TEXT NOT NULL,\n reached INTEGER NOT NULL,\n through TEXT,\n trail TEXT,\n because TEXT NOT NULL,\n PRIMARY KEY (project, build, subject)\n ) STRICT`,\n `UPDATE schema_version SET version = 7`,\n ],\n // 7 → 8: how large the baseline was, which is sometimes the change itself.\n [\n // Nullable, and left null on every row written before this step. A number\n // backfilled from `candidate_width` would be an invention that reads exactly\n // like a measurement, and the whole point of the column is to be able to say\n // the two differ.\n `ALTER TABLE build_subjects ADD COLUMN baseline_width INTEGER`,\n `ALTER TABLE build_subjects ADD COLUMN baseline_height INTEGER`,\n `UPDATE schema_version SET version = 8`,\n ],\n // 8 → 9: what the config declared, and what each declaration did.\n [\n // The audit that makes an ignore safe to have, kept where it outlives the run.\n // A mask grows over a real regression silently, and the only thing that catches\n // it is a rule absorbing nothing *again* — a comparison a CI log cannot answer.\n //\n // Two columns rather than a row per rule: the ledger is small, is always read\n // with its build, and a table here would be a second vocabulary for one fact.\n //\n // Null is *the writer said nothing*, which on this format is also what a\n // config with no rules produces — one absence, and the store invents no\n // second. What it must not become is a ledger of zero rules: an unaudited\n // build, reported as an audited one that found nothing.\n `ALTER TABLE builds ADD COLUMN ignores TEXT`,\n `ALTER TABLE builds ADD COLUMN sensitivities TEXT`,\n `UPDATE schema_version SET version = 9`,\n ],\n // 9 → 10: which declaration decided each green subject.\n [\n // The ledger added at step 9 says what each rule absorbed *across the run*.\n // It cannot say which rule absorbed *this subject*, and that is the sentence\n // the report prints beside every green-by-declaration name. Without these\n // two columns a service reading its own store had to answer `the run did not\n // record which rule absorbed it` about a run that recorded it — the store's\n // own omission, rendered as the observer's.\n //\n // Null keeps meaning the writer said nothing: `ignored: {pixels: 0, boxes: 2}`\n // is a rule that caught nothing here, which is not the same fact and is the\n // one that turns a mask into a blind spot.\n `ALTER TABLE build_subjects ADD COLUMN ignored TEXT`,\n `ALTER TABLE build_subjects ADD COLUMN relaxed TEXT`,\n `UPDATE schema_version SET version = 10`,\n ],\n // 10 → 11: which component moved, and in which band.\n [\n // `regions` is the raster tier's answer, and it loses the name exactly where\n // a reviewer needs it: a difference that reflows its neighbours merges into\n // one blob, the blob fits no component, and the region resolves to the\n // document root. The semantic tier never lost it — it compares digests, not\n // pixels — but the store had no column for it, so the service could report\n // only what the picture happened to be able to say.\n //\n // Null keeps meaning the run wrote nothing — here, a baseline with no\n // component hashes. `'[]'` is both sides read and every digest matched.\n `ALTER TABLE build_subjects ADD COLUMN moved TEXT`,\n `UPDATE schema_version SET version = 11`,\n ],\n // 11 → 12: what draws what, which is the only record that can answer *why did\n // this move* for a component no file in the diff declares.\n [\n // The import graph climbs. `build_reach` walks from a changed file through\n // its importers, so it names what an edit *could* have reached and can never\n // name anything a changed file draws: `ProductCard` renders `Card`, `Card`\n // renders `CardFooter`, and a walk that only goes upward arrives at none of\n // them. The page was left saying \"no rung above holds them\" — true, and not\n // a reason.\n //\n // The run already wrote the other direction. `composition.components`\n // carries `within` and `renders` per component, folded over every subject,\n // and the store dropped it at the door.\n //\n // One row per component, not a JSON blob on `builds`: the page asks *who\n // draws this one*, and a census of four hundred components read whole to\n // answer it is the shape that makes a reviewer wait.\n //\n // Every column NOT NULL, including the empty lists. A census that named a\n // component knows all three, and the one ambiguity in them — an empty\n // `created_by` is *this was a production build*, not *nothing mounted it* —\n // belongs to the report that wrote it. A store that answered it with NULL\n // would be inventing a distinction upstream declined to make.\n `CREATE TABLE build_composition (\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n component TEXT NOT NULL,\n subjects TEXT NOT NULL,\n within TEXT NOT NULL,\n created_by TEXT NOT NULL,\n renders TEXT NOT NULL,\n PRIMARY KEY (project, build, component)\n ) STRICT`,\n `UPDATE schema_version SET version = 12`,\n ],\n // 12 → 13: the attribution itself. The census above says who draws what; this\n // says what the run concluded from it about each thing that moved.\n [\n // The store kept the graph and dropped the answer. A run walks the diff,\n // finds the file that declares each moved component, climbs to an edited\n // ancestor when nothing declares it, and writes one sentence per movement\n // into `composition.movements` — and every one of them stopped at the ingest\n // door. The review page then rebuilt a worse version of the same walk out of\n // the census, with no access to the props digests or the control group the\n // run had used, and printed *no rung above holds them* about components the\n // run had already attributed to an edited parent.\n //\n // One row per movement, keyed by the pair it is about. A component moves for\n // its own reason in each subject it moved in — the same `Button` can be\n // `edited` on one page and `upstream` on another — so a table keyed by\n // component alone would keep whichever row was written last and call it the\n // cause everywhere.\n //\n // `also_in` is not a column. It is the subjects of the sibling rows for the\n // same component, and a stored copy is a second answer that can disagree\n // with the first.\n //\n // Nullable is *the rung does not apply*: `file` on anything but `edited`,\n // `upstream` and `through` on anything but `upstream`, `standing` on\n // anything explained. `bands` and `held` are NOT NULL and can be `'[]'`,\n // which in both cases means what the report means by it — for `bands`, that\n // the comparison was name-only and no band is known; for `held`, that the\n // suite offered no control.\n `CREATE TABLE build_movements (\n project TEXT NOT NULL,\n build TEXT NOT NULL,\n subject TEXT NOT NULL,\n component TEXT NOT NULL,\n cause TEXT NOT NULL,\n because TEXT NOT NULL,\n bands TEXT NOT NULL,\n held TEXT NOT NULL,\n file TEXT,\n tokens TEXT,\n upstream TEXT,\n through TEXT,\n standing TEXT,\n PRIMARY KEY (project, build, subject, component)\n ) STRICT`,\n `UPDATE schema_version SET version = 13`,\n ],\n // 13 → 14: the denominator the control group is a numerator of.\n [\n // `held` alone is two opposite findings under one shape. Empty because the\n // component renders nowhere else with these inputs is a suite with nothing to\n // say; empty because it renders in four other places and moved in all four is\n // the suite saying the loudest thing it can — the change reached everything\n // this component draws. The page had to guess, and on any run where the edit\n // landed everywhere it guessed the weak one.\n //\n // Nullable, and null is *the run never said*: reports written before this\n // carry no answer, and `0` is an answer.\n `ALTER TABLE build_movements ADD COLUMN compared INTEGER`,\n `UPDATE schema_version SET version = 14`,\n ],\n];\n"]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The database as it first shipped, as statements rather than as a script.
3
+ *
4
+ * D1's `exec` accepts multiple statements only when each one is on a single
5
+ * line, which a trigger body cannot be, and splitting a script on `;` would cut
6
+ * every trigger in half — the semicolons inside `BEGIN … END` are part of the
7
+ * statement. So the schema is a list from the start, applied with `batch`, and
8
+ * there is no parser here that could get it wrong.
9
+ *
10
+ * ## Two halves
11
+ *
12
+ * The first half is this spec's own: baselines, the render cache, builds,
13
+ * per-subject verdicts, and decisions. The second half is
14
+ * [spec 0002](../../../docs/specs/0002-history-store.md)'s, and it is a
15
+ * deliberate transcription of
16
+ * [`server/backend-sqlite.ts`](../../server/src/backend-sqlite.ts) — the same
17
+ * columns, the same indexes, and above all the same append-only triggers with
18
+ * the same wording. Two backends that disagree about what a row is are two
19
+ * different records wearing one name, and the trigger messages are the part an
20
+ * operator actually reads, so they are copied rather than paraphrased.
21
+ *
22
+ * ## Two rules the tables enforce that no code has to remember
23
+ *
24
+ * **The identity partition is the primary key.** `baselines` is keyed by
25
+ * `(project, identity_digest, subject, label)`. A baseline written by one
26
+ * machine is not reachable as this machine's, because it is a different row —
27
+ * the same argument [ADR-0011](../../../docs/context/adr/0011-durable-and-ephemeral-retention.md)
28
+ * makes about the directory store's layout, and with the same absence of a check
29
+ * somebody could forget to write.
30
+ *
31
+ * **Instants are stored twice.** The original text, and its parsed
32
+ * milliseconds; every window is compared on the number. ISO-8601 sorts lexically
33
+ * only while every timestamp shares one offset, and a store fed by CI jobs in
34
+ * two regions does not.
35
+ */
36
+ /**
37
+ * The version the frozen initial set lands a database on.
38
+ *
39
+ * Exported because the step list in
40
+ * [`migration-steps.ts`](./migration-steps.js) is indexed against it: step `i`
41
+ * lands on `INITIAL_VERSION + i + 1`. An operator holding a deployed database
42
+ * reads its `schema_version`, and without this the only way to line that number
43
+ * up with a step is to derive it from `SCHEMA_VERSION - MIGRATIONS.length`.
44
+ */
45
+ export declare const INITIAL_VERSION = 3;
46
+ /**
47
+ * What a run kept, and what a review decided, in order — as this database first
48
+ * shipped.
49
+ *
50
+ * Order matters: tables before their indexes, and both before the triggers that
51
+ * reference them.
52
+ *
53
+ * Frozen at {@link INITIAL_VERSION}. Everything since is a step in
54
+ * [`migration-steps.ts`](./migration-steps.js), for the reason given there; a
55
+ * new table added here would reach a fresh deployment and no existing one.
56
+ */
57
+ export declare const INITIAL: readonly string[];
58
+ //# sourceMappingURL=migrations.d.ts.map