@crvouga/atlas 1.12.0 → 1.13.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 +7 -1
- package/dist/critics/src/contract.d.ts +113 -0
- package/dist/critics/src/contract.js +48 -0
- package/dist/critics/src/credentials.d.ts +72 -0
- package/dist/critics/src/credentials.js +136 -0
- package/dist/critics/src/critique.d.ts +128 -0
- package/dist/critics/src/critique.js +163 -0
- package/dist/critics/src/index.d.ts +21 -0
- package/dist/critics/src/index.js +21 -0
- package/dist/critics/src/judging.d.ts +153 -0
- package/dist/critics/src/judging.js +145 -0
- package/dist/critics/src/publish.d.ts +23 -0
- package/dist/critics/src/publish.js +21 -0
- package/dist/critics/src/runner.d.ts +104 -0
- package/dist/critics/src/runner.js +202 -0
- package/dist/critics/src/scope.d.ts +8 -0
- package/dist/critics/src/scope.js +26 -0
- package/dist/reports/src/compose.d.ts +2 -2
- package/dist/reports/src/compose.js +6 -5
- package/dist/reports/src/evidence-view.d.ts +2 -1
- package/dist/reports/src/evidence-view.js +5 -2
- package/dist/reports/src/layer-merge.d.ts +11 -3
- package/dist/reports/src/layer-merge.js +14 -3
- package/dist/reports/src/report-status.d.ts +1 -1
- package/dist/reports/src/report-status.js +6 -4
- package/dist/schema/src/api.d.ts +1 -0
- package/dist/schema/src/api.js +1 -1
- package/dist/schema/src/critique.d.ts +144 -0
- package/dist/schema/src/critique.js +96 -0
- package/dist/schema/src/index.d.ts +2 -1
- package/dist/schema/src/index.js +2 -1
- package/dist/schema/src/server-config.d.ts +7 -1
- package/dist/schema/src/server-config.js +6 -3
- package/dist/server/src/auth.d.ts +1 -1
- package/dist/server/src/auth.js +2 -2
- package/dist/server/src/config.js +2 -2
- package/dist/server/src/openapi.d.ts +3 -3
- package/dist/server/src/openapi.js +7 -4
- package/dist/server/src/store-api.js +39 -1
- package/docs/agents.md +1 -0
- package/docs/critics.md +190 -0
- package/docs/extending.md +1 -0
- package/docs/reference/critics.md +840 -0
- package/docs/reference/http-api.md +6 -2
- package/docs/reference/reports.md +20 -7
- package/docs/reference/schema.md +119 -2
- package/docs/reference/server.md +3 -3
- package/docs/report-contract.md +4 -0
- package/docs/server.md +6 -4
- package/llms-full.txt +211 -6
- package/llms.txt +2 -0
- package/package.json +7 -2
- package/packages/critics/README.md +18 -0
- package/packages/schema/schemas/critique.schema.json +254 -0
- package/packages/schema/schemas/server-config.schema.json +2 -1
- package/packages/schema/schemas/server-info.schema.json +1 -0
- package/packages/server/openapi.json +7 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/atlas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Atlas: specs of any kind, reported as layered evidence. Publish checks from any runner (JUnit, CTRF, a script), combine them across nodes, branches, environments and backends, gate CI on the result, and run statecharts against the real app.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -85,6 +85,10 @@
|
|
|
85
85
|
"types": "./dist/server/src/index.d.ts",
|
|
86
86
|
"default": "./dist/server/src/index.js"
|
|
87
87
|
},
|
|
88
|
+
"./critics": {
|
|
89
|
+
"types": "./dist/critics/src/index.d.ts",
|
|
90
|
+
"default": "./dist/critics/src/index.js"
|
|
91
|
+
},
|
|
88
92
|
"./reports/*": {
|
|
89
93
|
"types": "./dist/reports/src/*.d.ts",
|
|
90
94
|
"default": "./dist/reports/src/*.js"
|
|
@@ -155,7 +159,8 @@
|
|
|
155
159
|
"docs/runners.md",
|
|
156
160
|
"packages/runners/compat",
|
|
157
161
|
"docs/ui.md",
|
|
158
|
-
"docs/workspaces.md"
|
|
162
|
+
"docs/workspaces.md",
|
|
163
|
+
"docs/critics.md"
|
|
159
164
|
],
|
|
160
165
|
"scripts": {
|
|
161
166
|
"build": "bun scripts/build-package.ts",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @crvouga/atlas/critics
|
|
2
|
+
|
|
3
|
+
Automated reviewers of the UI catalog that mark which UIs need polish. A critic judges one captured UI through one small
|
|
4
|
+
contract; the runner owns caching, retries, rate limits, timeouts and budgets; opinions are stored as ordinary layers of
|
|
5
|
+
parts of kind `critique` and never change whether a report passes.
|
|
6
|
+
|
|
7
|
+
Read [the critics guide](../../docs/critics.md). The function-level reference is generated from the code:
|
|
8
|
+
[critics](../../docs/reference/critics.md).
|
|
9
|
+
|
|
10
|
+
| Module | |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `contract` | `defineCritic`, the `Critic` type, `CriticError`, `RateLimitedError`, `InvalidOutputError` |
|
|
13
|
+
| `runner` | `runCritic`: skip what was judged, bounded concurrency, timeout, backoff, budgets, dry run |
|
|
14
|
+
| `critique` | build, read and key critiques; `critiqueLayer`, `readCritique`, `critiqueCurrency` |
|
|
15
|
+
| `publish` | `publishCritiques` |
|
|
16
|
+
| `judging` | `relativeVerdict`, `calibrate`, `gateDecision` (report, warn, gate) |
|
|
17
|
+
| `credentials` | references (`env:NAME`), literal-credential refusal, redaction |
|
|
18
|
+
| `scope` | the rule a critic-role token is held to |
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "https://github.com/crvouga/atlas/schemas/critique.schema.json",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"schema": {
|
|
7
|
+
"type": "integer",
|
|
8
|
+
"exclusiveMinimum": 0,
|
|
9
|
+
"maximum": 9007199254740991,
|
|
10
|
+
"description": "The version of this extension. 1"
|
|
11
|
+
},
|
|
12
|
+
"subject": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"entryKey": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1,
|
|
18
|
+
"description": "The catalog entry that was judged"
|
|
19
|
+
},
|
|
20
|
+
"imageSha256": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"description": "The hash of the exact image bytes that were judged. When the entry's image changes, this critique judged an earlier image"
|
|
24
|
+
},
|
|
25
|
+
"state": {
|
|
26
|
+
"description": "The kind of UI state: `screen`, `overlay`, `loading`, `error`, `empty`…",
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"required": [
|
|
32
|
+
"entryKey",
|
|
33
|
+
"imageSha256"
|
|
34
|
+
],
|
|
35
|
+
"additionalProperties": {}
|
|
36
|
+
},
|
|
37
|
+
"critic": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"name": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1
|
|
43
|
+
},
|
|
44
|
+
"version": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"minLength": 1,
|
|
47
|
+
"description": "Of the critic's own logic. A newer version replaces an older one"
|
|
48
|
+
},
|
|
49
|
+
"kind": {
|
|
50
|
+
"description": "Open vocabulary: `model`, `llm`, `ml`, `heuristic`…",
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"name",
|
|
57
|
+
"version"
|
|
58
|
+
],
|
|
59
|
+
"additionalProperties": {}
|
|
60
|
+
},
|
|
61
|
+
"model": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"id": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"minLength": 1
|
|
67
|
+
},
|
|
68
|
+
"provider": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"required": [
|
|
73
|
+
"id"
|
|
74
|
+
],
|
|
75
|
+
"additionalProperties": {}
|
|
76
|
+
},
|
|
77
|
+
"parameters": {
|
|
78
|
+
"description": "Everything else that explains the result: temperature, seed, the SHA-256 of the rubric",
|
|
79
|
+
"type": "object",
|
|
80
|
+
"propertyNames": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
},
|
|
83
|
+
"additionalProperties": {}
|
|
84
|
+
},
|
|
85
|
+
"verdict": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"score": {
|
|
89
|
+
"description": "A finite number. `scale` says what it means",
|
|
90
|
+
"type": "number"
|
|
91
|
+
},
|
|
92
|
+
"scale": {
|
|
93
|
+
"description": "For example `0..1, higher is better`",
|
|
94
|
+
"type": "string"
|
|
95
|
+
},
|
|
96
|
+
"label": {
|
|
97
|
+
"description": "Open vocabulary, conventionally `ok` or `needs-polish`",
|
|
98
|
+
"type": "string"
|
|
99
|
+
},
|
|
100
|
+
"confidence": {
|
|
101
|
+
"type": "number",
|
|
102
|
+
"minimum": 0,
|
|
103
|
+
"maximum": 1
|
|
104
|
+
},
|
|
105
|
+
"relative": {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"properties": {
|
|
108
|
+
"stateKind": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"minLength": 1,
|
|
111
|
+
"description": "The kind of UI state the score is relative to: `screen`, `overlay`, `loading`, `error`, `empty`…"
|
|
112
|
+
},
|
|
113
|
+
"percentile": {
|
|
114
|
+
"description": "Where the score falls among the project's scores of the same state kind, 0..100, higher is better",
|
|
115
|
+
"type": "number",
|
|
116
|
+
"minimum": 0,
|
|
117
|
+
"maximum": 100
|
|
118
|
+
},
|
|
119
|
+
"sampleSize": {
|
|
120
|
+
"description": "How many scores of that state kind the percentile is over",
|
|
121
|
+
"type": "integer",
|
|
122
|
+
"minimum": 0,
|
|
123
|
+
"maximum": 9007199254740991
|
|
124
|
+
},
|
|
125
|
+
"previousScore": {
|
|
126
|
+
"description": "The same entry's score for its previous image, from the same critic",
|
|
127
|
+
"type": "number"
|
|
128
|
+
},
|
|
129
|
+
"delta": {
|
|
130
|
+
"description": "`score` minus `previousScore`",
|
|
131
|
+
"type": "number"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"required": [
|
|
135
|
+
"stateKind"
|
|
136
|
+
],
|
|
137
|
+
"additionalProperties": {}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"additionalProperties": {}
|
|
141
|
+
},
|
|
142
|
+
"findings": {
|
|
143
|
+
"type": "array",
|
|
144
|
+
"items": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"id": {
|
|
148
|
+
"description": "Stable within the critique, so a reviewer can mark this finding valid or not",
|
|
149
|
+
"type": "string",
|
|
150
|
+
"minLength": 1
|
|
151
|
+
},
|
|
152
|
+
"category": {
|
|
153
|
+
"description": "Open vocabulary: `spacing`, `contrast`, `alignment`, `overflow`, `hierarchy`…",
|
|
154
|
+
"type": "string",
|
|
155
|
+
"minLength": 1
|
|
156
|
+
},
|
|
157
|
+
"severity": {
|
|
158
|
+
"description": "Open vocabulary, conventionally `info`, `minor`, `major`",
|
|
159
|
+
"type": "string",
|
|
160
|
+
"minLength": 1
|
|
161
|
+
},
|
|
162
|
+
"confidence": {
|
|
163
|
+
"type": "number",
|
|
164
|
+
"minimum": 0,
|
|
165
|
+
"maximum": 1
|
|
166
|
+
},
|
|
167
|
+
"region": {
|
|
168
|
+
"type": "object",
|
|
169
|
+
"properties": {
|
|
170
|
+
"unit": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"minLength": 1,
|
|
173
|
+
"description": "`px` (pixels of the stored image) or `normalized` (0..1 of its width and height). Open vocabulary"
|
|
174
|
+
},
|
|
175
|
+
"x": {
|
|
176
|
+
"type": "number"
|
|
177
|
+
},
|
|
178
|
+
"y": {
|
|
179
|
+
"type": "number"
|
|
180
|
+
},
|
|
181
|
+
"w": {
|
|
182
|
+
"type": "number",
|
|
183
|
+
"minimum": 0
|
|
184
|
+
},
|
|
185
|
+
"h": {
|
|
186
|
+
"type": "number",
|
|
187
|
+
"minimum": 0
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"required": [
|
|
191
|
+
"unit",
|
|
192
|
+
"x",
|
|
193
|
+
"y",
|
|
194
|
+
"w",
|
|
195
|
+
"h"
|
|
196
|
+
],
|
|
197
|
+
"additionalProperties": {}
|
|
198
|
+
},
|
|
199
|
+
"rationale": {
|
|
200
|
+
"type": "string"
|
|
201
|
+
},
|
|
202
|
+
"suggestion": {
|
|
203
|
+
"type": "string"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"additionalProperties": {}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
"failure": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"properties": {
|
|
212
|
+
"reason": {
|
|
213
|
+
"type": "string",
|
|
214
|
+
"minLength": 1
|
|
215
|
+
},
|
|
216
|
+
"message": {
|
|
217
|
+
"type": "string"
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"required": [
|
|
221
|
+
"reason"
|
|
222
|
+
],
|
|
223
|
+
"additionalProperties": {}
|
|
224
|
+
},
|
|
225
|
+
"usage": {
|
|
226
|
+
"type": "object",
|
|
227
|
+
"properties": {
|
|
228
|
+
"inputTokens": {
|
|
229
|
+
"type": "number",
|
|
230
|
+
"minimum": 0
|
|
231
|
+
},
|
|
232
|
+
"outputTokens": {
|
|
233
|
+
"type": "number",
|
|
234
|
+
"minimum": 0
|
|
235
|
+
},
|
|
236
|
+
"latencyMs": {
|
|
237
|
+
"type": "number",
|
|
238
|
+
"minimum": 0
|
|
239
|
+
},
|
|
240
|
+
"costUsd": {
|
|
241
|
+
"type": "number",
|
|
242
|
+
"minimum": 0
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"additionalProperties": {}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"required": [
|
|
249
|
+
"schema",
|
|
250
|
+
"subject",
|
|
251
|
+
"critic"
|
|
252
|
+
],
|
|
253
|
+
"additionalProperties": {}
|
|
254
|
+
}
|
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
"type": "string",
|
|
41
41
|
"enum": [
|
|
42
42
|
"read",
|
|
43
|
+
"critic",
|
|
43
44
|
"publish",
|
|
44
45
|
"admin"
|
|
45
46
|
],
|
|
46
|
-
"description": "`read` may look. `publish` may also upload. `admin` may also remove scratch objects"
|
|
47
|
+
"description": "`read` may look. `critic` may also publish critiques (layers of producer `critic.*` whose parts are all of kind `critique`). `publish` may also upload. `admin` may also remove scratch objects"
|
|
47
48
|
},
|
|
48
49
|
"token": {
|
|
49
50
|
"description": "The token. Prefer `tokenEnv`, so the file holds no secret",
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Atlas server API",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.6.0",
|
|
6
6
|
"summary": "Take in test results from every environment, keep them, and show everyone the combined report, live.",
|
|
7
|
-
"description": "One Atlas node serves multiple projects. Clients select a project using ?project=<slug>, X-Atlas-Project, or /api/projects/<slug>/… . Each project has independent specs, layers, recordings, status, and event streams. Within each project, the newest completed result of every check wins its slot. Unqualified requests address the legacy default project.\n\n**Authentication.** With tokens configured, send `Authorization: Bearer <token>`. Roles: `read` < `publish` < `admin`. Uploading needs a Bearer token; a browser's HTTP Basic sign-in (any user name, the token as the password) is accepted for reading only. A server with no tokens is open and listens on this machine only unless told otherwise.\n\n**Errors** are [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem documents (`application/problem+json`) with a `detail` that says what to do. `401` send a token, `403` that token may not, `409` upload what this depends on first or you are changing something immutable, `413` too large, `422` not valid, `503` still starting (retry after `Retry-After`).\n\n**Compatibility.** Within `/api` the API only grows: optional parameters, optional response fields, new events. Ignore what you do not know.\n\nGuides: `/llms.txt`. Source: https://github.com/crvouga/atlas.",
|
|
7
|
+
"description": "One Atlas node serves multiple projects. Clients select a project using ?project=<slug>, X-Atlas-Project, or /api/projects/<slug>/… . Each project has independent specs, layers, recordings, status, and event streams. Within each project, the newest completed result of every check wins its slot. Unqualified requests address the legacy default project.\n\n**Authentication.** With tokens configured, send `Authorization: Bearer <token>`. Roles: `read` < `critic` < `publish` < `admin`. A `critic` token may read, and publish critiques (layers of automated reviewers) and nothing else. Uploading needs a Bearer token; a browser's HTTP Basic sign-in (any user name, the token as the password) is accepted for reading only. A server with no tokens is open and listens on this machine only unless told otherwise.\n\n**Errors** are [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem documents (`application/problem+json`) with a `detail` that says what to do. `401` send a token, `403` that token may not, `409` upload what this depends on first or you are changing something immutable, `413` too large, `422` not valid, `503` still starting (retry after `Retry-After`).\n\n**Compatibility.** Within `/api` the API only grows: optional parameters, optional response fields, new events. Ignore what you do not know.\n\nGuides: `/llms.txt`. Source: https://github.com/crvouga/atlas.",
|
|
8
8
|
"license": {
|
|
9
9
|
"name": "MIT",
|
|
10
10
|
"identifier": "MIT"
|
|
@@ -2683,8 +2683,8 @@
|
|
|
2683
2683
|
"Store protocol"
|
|
2684
2684
|
],
|
|
2685
2685
|
"summary": "Upload an object",
|
|
2686
|
-
"description": "The write half of the `ObjectStore` interface. The server checks what it can from the bytes in hand and says no to what would corrupt the report for everyone:\n\n- a **layer manifest** (`layers/manifests/<id>.json`) must be a valid layer whose content hashes to `<id>`, and its blobs must already be there (`409` otherwise);\n- a **blob** (`layers/blobs/<sha256>.gz`) must be gzip of content whose SHA-256 is its name; a **spec file** likewise;\n- a **catalog entry** (`…/index/…`) must name something already uploaded (`409` otherwise): it is what makes a layer visible, so it is written last;\n- a **run manifest** must have passed its privacy scan;\n- keys are immutable: the same bytes again are `200` (a retry), other bytes under the same key are `409`.\n\nUpload in dependency order: blobs, then the manifest, then the catalog entry. `atlas report publish`, `atlas report stream` and `httpStore` do. Needs a `Bearer` token of role `publish` or `admin`; a browser's sign-in box is refused.\n\nRole needed: `
|
|
2687
|
-
"x-atlas-role": "
|
|
2686
|
+
"description": "The write half of the `ObjectStore` interface. The server checks what it can from the bytes in hand and says no to what would corrupt the report for everyone:\n\n- a **layer manifest** (`layers/manifests/<id>.json`) must be a valid layer whose content hashes to `<id>`, and its blobs must already be there (`409` otherwise);\n- a **blob** (`layers/blobs/<sha256>.gz`) must be gzip of content whose SHA-256 is its name; a **spec file** likewise;\n- a **catalog entry** (`…/index/…`) must name something already uploaded (`409` otherwise): it is what makes a layer visible, so it is written last;\n- a **run manifest** must have passed its privacy scan;\n- keys are immutable: the same bytes again are `200` (a retry), other bytes under the same key are `409`.\n\nUpload in dependency order: blobs, then the manifest, then the catalog entry. `atlas report publish`, `atlas report stream` and `httpStore` do. Needs a `Bearer` token of role `publish` or `admin`; a browser's sign-in box is refused.\n\nA token of role `critic` may upload only what a critic publishes: blobs, and layers (and their catalog entries) whose `producer` is `critic.<name>` and whose parts are all of kind `critique`. Anything else is `403` with the rule it broke, and nothing is stored.\n\nRole needed: `critic`.",
|
|
2687
|
+
"x-atlas-role": "critic",
|
|
2688
2688
|
"security": [
|
|
2689
2689
|
{
|
|
2690
2690
|
"bearer": []
|
|
@@ -3029,8 +3029,8 @@
|
|
|
3029
3029
|
"Store protocol"
|
|
3030
3030
|
],
|
|
3031
3031
|
"summary": "Upload an object",
|
|
3032
|
-
"description": "The write half of the `ObjectStore` interface. The server checks what it can from the bytes in hand and says no to what would corrupt the report for everyone:\n\n- a **layer manifest** (`layers/manifests/<id>.json`) must be a valid layer whose content hashes to `<id>`, and its blobs must already be there (`409` otherwise);\n- a **blob** (`layers/blobs/<sha256>.gz`) must be gzip of content whose SHA-256 is its name; a **spec file** likewise;\n- a **catalog entry** (`…/index/…`) must name something already uploaded (`409` otherwise): it is what makes a layer visible, so it is written last;\n- a **run manifest** must have passed its privacy scan;\n- keys are immutable: the same bytes again are `200` (a retry), other bytes under the same key are `409`.\n\nUpload in dependency order: blobs, then the manifest, then the catalog entry. `atlas report publish`, `atlas report stream` and `httpStore` do. Needs a `Bearer` token of role `publish` or `admin`; a browser's sign-in box is refused.\n\nScoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.\n\nRole needed: `
|
|
3033
|
-
"x-atlas-role": "
|
|
3032
|
+
"description": "The write half of the `ObjectStore` interface. The server checks what it can from the bytes in hand and says no to what would corrupt the report for everyone:\n\n- a **layer manifest** (`layers/manifests/<id>.json`) must be a valid layer whose content hashes to `<id>`, and its blobs must already be there (`409` otherwise);\n- a **blob** (`layers/blobs/<sha256>.gz`) must be gzip of content whose SHA-256 is its name; a **spec file** likewise;\n- a **catalog entry** (`…/index/…`) must name something already uploaded (`409` otherwise): it is what makes a layer visible, so it is written last;\n- a **run manifest** must have passed its privacy scan;\n- keys are immutable: the same bytes again are `200` (a retry), other bytes under the same key are `409`.\n\nUpload in dependency order: blobs, then the manifest, then the catalog entry. `atlas report publish`, `atlas report stream` and `httpStore` do. Needs a `Bearer` token of role `publish` or `admin`; a browser's sign-in box is refused.\n\nA token of role `critic` may upload only what a critic publishes: blobs, and layers (and their catalog entries) whose `producer` is `critic.<name>` and whose parts are all of kind `critique`. Anything else is `403` with the rule it broke, and nothing is stored.\n\nScoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.\n\nRole needed: `critic`.",
|
|
3033
|
+
"x-atlas-role": "critic",
|
|
3034
3034
|
"security": [
|
|
3035
3035
|
{
|
|
3036
3036
|
"bearer": []
|
|
@@ -10011,6 +10011,7 @@
|
|
|
10011
10011
|
"type": "string",
|
|
10012
10012
|
"enum": [
|
|
10013
10013
|
"read",
|
|
10014
|
+
"critic",
|
|
10014
10015
|
"publish",
|
|
10015
10016
|
"admin"
|
|
10016
10017
|
],
|