@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.
- package/CHANGELOG.md +100 -0
- package/LICENSE +21 -0
- package/README.md +506 -0
- package/dist/__fixtures__/review.d.ts +47 -0
- package/dist/__fixtures__/review.js +145 -0
- package/dist/__fixtures__/review.js.map +1 -0
- package/dist/bindings.d.ts +134 -0
- package/dist/bindings.js +88 -0
- package/dist/bindings.js.map +1 -0
- package/dist/changelog.d.ts +132 -0
- package/dist/changelog.js +129 -0
- package/dist/changelog.js.map +1 -0
- package/dist/history-queries.d.ts +82 -0
- package/dist/history-queries.js +200 -0
- package/dist/history-queries.js.map +1 -0
- package/dist/history-rows.d.ts +42 -0
- package/dist/history-rows.js +148 -0
- package/dist/history-rows.js.map +1 -0
- package/dist/history.d.ts +40 -0
- package/dist/history.js +186 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/migration-steps.d.ts +32 -0
- package/dist/migration-steps.js +303 -0
- package/dist/migration-steps.js.map +1 -0
- package/dist/migrations.d.ts +58 -0
- package/dist/migrations.js +283 -0
- package/dist/migrations.js.map +1 -0
- package/dist/next.d.ts +94 -0
- package/dist/next.js +44 -0
- package/dist/next.js.map +1 -0
- package/dist/node/bin.d.ts +120 -0
- package/dist/node/bin.js +337 -0
- package/dist/node/bin.js.map +1 -0
- package/dist/node/bucket.d.ts +58 -0
- package/dist/node/bucket.js +142 -0
- package/dist/node/bucket.js.map +1 -0
- package/dist/node/database.d.ts +33 -0
- package/dist/node/database.js +157 -0
- package/dist/node/database.js.map +1 -0
- package/dist/node/index.d.ts +43 -0
- package/dist/node/index.js +43 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/serve.d.ts +81 -0
- package/dist/node/serve.js +193 -0
- package/dist/node/serve.js.map +1 -0
- package/dist/node/ui-assets.d.ts +47 -0
- package/dist/node/ui-assets.js +60 -0
- package/dist/node/ui-assets.js.map +1 -0
- package/dist/review-ingest.d.ts +24 -0
- package/dist/review-ingest.js +184 -0
- package/dist/review-ingest.js.map +1 -0
- package/dist/review-read.d.ts +87 -0
- package/dist/review-read.js +361 -0
- package/dist/review-read.js.map +1 -0
- package/dist/review-rows.d.ts +30 -0
- package/dist/review-rows.js +67 -0
- package/dist/review-rows.js.map +1 -0
- package/dist/review-types.d.ts +414 -0
- package/dist/review-types.js +2 -0
- package/dist/review-types.js.map +1 -0
- package/dist/review-write.d.ts +35 -0
- package/dist/review-write.js +86 -0
- package/dist/review-write.js.map +1 -0
- package/dist/review.d.ts +53 -0
- package/dist/review.fixtures.d.ts +47 -0
- package/dist/review.fixtures.js +145 -0
- package/dist/review.fixtures.js.map +1 -0
- package/dist/review.js +245 -0
- package/dist/review.js.map +1 -0
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +39 -0
- package/dist/schema.js.map +1 -0
- package/dist/store.d.ts +58 -0
- package/dist/store.js +278 -0
- package/dist/store.js.map +1 -0
- package/dist/testing.d.ts +38 -0
- package/dist/testing.js +92 -0
- package/dist/testing.js.map +1 -0
- package/dist/ui/__probe.d.ts +3 -0
- package/dist/ui/__probe.js +5 -0
- package/dist/ui/__probe.js.map +1 -0
- package/dist/ui/attribution.d.ts +46 -0
- package/dist/ui/attribution.js +79 -0
- package/dist/ui/attribution.js.map +1 -0
- package/dist/ui/because.d.ts +51 -0
- package/dist/ui/because.js +52 -0
- package/dist/ui/because.js.map +1 -0
- package/dist/ui/browser-entry.d.ts +2 -0
- package/dist/ui/browser-entry.js +34 -0
- package/dist/ui/browser-entry.js.map +1 -0
- package/dist/ui/builds.d.ts +43 -0
- package/dist/ui/builds.js +79 -0
- package/dist/ui/builds.js.map +1 -0
- package/dist/ui/carried.d.ts +73 -0
- package/dist/ui/carried.js +63 -0
- package/dist/ui/carried.js.map +1 -0
- package/dist/ui/cause.d.ts +73 -0
- package/dist/ui/cause.js +133 -0
- package/dist/ui/cause.js.map +1 -0
- package/dist/ui/change-story.d.ts +153 -0
- package/dist/ui/change-story.js +253 -0
- package/dist/ui/change-story.js.map +1 -0
- package/dist/ui/change.d.ts +51 -0
- package/dist/ui/change.js +125 -0
- package/dist/ui/change.js.map +1 -0
- package/dist/ui/client.d.ts +74 -0
- package/dist/ui/client.js +88 -0
- package/dist/ui/client.js.map +1 -0
- package/dist/ui/consumers.d.ts +80 -0
- package/dist/ui/consumers.js +125 -0
- package/dist/ui/consumers.js.map +1 -0
- package/dist/ui/control.d.ts +63 -0
- package/dist/ui/control.js +39 -0
- package/dist/ui/control.js.map +1 -0
- package/dist/ui/crossing.d.ts +55 -0
- package/dist/ui/crossing.js +74 -0
- package/dist/ui/crossing.js.map +1 -0
- package/dist/ui/declarations.d.ts +36 -0
- package/dist/ui/declarations.js +73 -0
- package/dist/ui/declarations.js.map +1 -0
- package/dist/ui/distance.d.ts +154 -0
- package/dist/ui/distance.js +180 -0
- package/dist/ui/distance.js.map +1 -0
- package/dist/ui/divergence.d.ts +40 -0
- package/dist/ui/divergence.js +176 -0
- package/dist/ui/divergence.js.map +1 -0
- package/dist/ui/docket.d.ts +39 -0
- package/dist/ui/docket.js +172 -0
- package/dist/ui/docket.js.map +1 -0
- package/dist/ui/findings.d.ts +42 -0
- package/dist/ui/findings.js +110 -0
- package/dist/ui/findings.js.map +1 -0
- package/dist/ui/foreseen.d.ts +55 -0
- package/dist/ui/foreseen.js +91 -0
- package/dist/ui/foreseen.js.map +1 -0
- package/dist/ui/glance.d.ts +101 -0
- package/dist/ui/glance.js +101 -0
- package/dist/ui/glance.js.map +1 -0
- package/dist/ui/grouping.d.ts +158 -0
- package/dist/ui/grouping.js +187 -0
- package/dist/ui/grouping.js.map +1 -0
- package/dist/ui/handed.d.ts +60 -0
- package/dist/ui/handed.js +122 -0
- package/dist/ui/handed.js.map +1 -0
- package/dist/ui/history.d.ts +88 -0
- package/dist/ui/history.js +170 -0
- package/dist/ui/history.js.map +1 -0
- package/dist/ui/holding.d.ts +84 -0
- package/dist/ui/holding.js +90 -0
- package/dist/ui/holding.js.map +1 -0
- package/dist/ui/impact.d.ts +31 -0
- package/dist/ui/impact.js +132 -0
- package/dist/ui/impact.js.map +1 -0
- package/dist/ui/index.d.ts +21 -0
- package/dist/ui/index.js +21 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/lead.d.ts +35 -0
- package/dist/ui/lead.js +34 -0
- package/dist/ui/lead.js.map +1 -0
- package/dist/ui/look.d.ts +109 -0
- package/dist/ui/look.js +248 -0
- package/dist/ui/look.js.map +1 -0
- package/dist/ui/mark.d.ts +11 -0
- package/dist/ui/mark.js +13 -0
- package/dist/ui/mark.js.map +1 -0
- package/dist/ui/moved.d.ts +121 -0
- package/dist/ui/moved.js +143 -0
- package/dist/ui/moved.js.map +1 -0
- package/dist/ui/navigation.d.ts +26 -0
- package/dist/ui/navigation.js +53 -0
- package/dist/ui/navigation.js.map +1 -0
- package/dist/ui/order.d.ts +113 -0
- package/dist/ui/order.js +226 -0
- package/dist/ui/order.js.map +1 -0
- package/dist/ui/origins.d.ts +42 -0
- package/dist/ui/origins.js +149 -0
- package/dist/ui/origins.js.map +1 -0
- package/dist/ui/outcome.d.ts +93 -0
- package/dist/ui/outcome.js +162 -0
- package/dist/ui/outcome.js.map +1 -0
- package/dist/ui/parted.d.ts +68 -0
- package/dist/ui/parted.js +101 -0
- package/dist/ui/parted.js.map +1 -0
- package/dist/ui/rail.d.ts +31 -0
- package/dist/ui/rail.js +21 -0
- package/dist/ui/rail.js.map +1 -0
- package/dist/ui/reach.d.ts +66 -0
- package/dist/ui/reach.js +185 -0
- package/dist/ui/reach.js.map +1 -0
- package/dist/ui/regions.d.ts +82 -0
- package/dist/ui/regions.js +67 -0
- package/dist/ui/regions.js.map +1 -0
- package/dist/ui/review.bundle.js +69 -0
- package/dist/ui/review.d.ts +97 -0
- package/dist/ui/review.js +39 -0
- package/dist/ui/review.js.map +1 -0
- package/dist/ui/root.d.ts +72 -0
- package/dist/ui/root.js +102 -0
- package/dist/ui/root.js.map +1 -0
- package/dist/ui/route.d.ts +95 -0
- package/dist/ui/route.js +114 -0
- package/dist/ui/route.js.map +1 -0
- package/dist/ui/run.d.ts +26 -0
- package/dist/ui/run.js +12 -0
- package/dist/ui/run.js.map +1 -0
- package/dist/ui/sense.d.ts +187 -0
- package/dist/ui/sense.js +222 -0
- package/dist/ui/sense.js.map +1 -0
- package/dist/ui/settled.d.ts +43 -0
- package/dist/ui/settled.js +59 -0
- package/dist/ui/settled.js.map +1 -0
- package/dist/ui/shell.d.ts +76 -0
- package/dist/ui/shell.js +65 -0
- package/dist/ui/shell.js.map +1 -0
- package/dist/ui/shift.d.ts +52 -0
- package/dist/ui/shift.js +98 -0
- package/dist/ui/shift.js.map +1 -0
- package/dist/ui/styles-docket.d.ts +18 -0
- package/dist/ui/styles-docket.js +281 -0
- package/dist/ui/styles-docket.js.map +1 -0
- package/dist/ui/styles-stage.d.ts +18 -0
- package/dist/ui/styles-stage.js +92 -0
- package/dist/ui/styles-stage.js.map +1 -0
- package/dist/ui/styles.d.ts +12 -0
- package/dist/ui/styles.js +482 -0
- package/dist/ui/styles.js.map +1 -0
- package/dist/ui/subject.d.ts +36 -0
- package/dist/ui/subject.js +138 -0
- package/dist/ui/subject.js.map +1 -0
- package/dist/ui/text.d.ts +129 -0
- package/dist/ui/text.js +164 -0
- package/dist/ui/text.js.map +1 -0
- package/dist/ui/variations.d.ts +37 -0
- package/dist/ui/variations.js +60 -0
- package/dist/ui/variations.js.map +1 -0
- package/dist/ui/viewer.d.ts +67 -0
- package/dist/ui/viewer.js +246 -0
- package/dist/ui/viewer.js.map +1 -0
- package/dist/worker-auth.d.ts +48 -0
- package/dist/worker-auth.js +74 -0
- package/dist/worker-auth.js.map +1 -0
- package/dist/worker-entry.d.ts +58 -0
- package/dist/worker-entry.js +36 -0
- package/dist/worker-entry.js.map +1 -0
- package/dist/worker-http.d.ts +39 -0
- package/dist/worker-http.js +111 -0
- package/dist/worker-http.js.map +1 -0
- package/dist/worker-input.d.ts +81 -0
- package/dist/worker-input.js +296 -0
- package/dist/worker-input.js.map +1 -0
- package/dist/worker.d.ts +91 -0
- package/dist/worker.js +287 -0
- package/dist/worker.js.map +1 -0
- package/mark.svg +30 -0
- package/migrations/0001_initial.sql +193 -0
- package/migrations/0002_changelog.sql +30 -0
- package/migrations/0003_accessibility.sql +8 -0
- package/migrations/0004_variations.sql +19 -0
- package/migrations/0005_reach.sql +26 -0
- package/migrations/0006_baseline-size.sql +7 -0
- package/migrations/0007_declarations.sql +7 -0
- package/migrations/0008_green-because.sql +7 -0
- package/migrations/0009_moved-bands.sql +6 -0
- package/migrations/0010_composition.sql +15 -0
- package/migrations/0011_movements.sql +21 -0
- package/migrations/0012_control-size.sql +6 -0
- package/package.json +110 -0
- 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
|