@crvouga/atlas 1.18.0 → 1.20.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 +14 -1
- package/dist/reports/src/evidence-detail.js +13 -3
- package/dist/reports/src/evidence-types.d.ts +4 -0
- package/dist/schema/src/api.d.ts +105 -0
- package/dist/schema/src/api.js +35 -0
- package/dist/server/src/app.js +3 -1
- package/dist/server/src/openapi.d.ts +1 -1
- package/dist/server/src/openapi.js +24 -2
- package/dist/server/src/recording-verification.d.ts +34 -0
- package/dist/server/src/recording-verification.js +118 -0
- package/docs/reference/http-api.md +52 -0
- package/docs/reference/reports.md +4 -0
- package/docs/reference/schema.md +41 -0
- package/docs/reference/server.md +39 -0
- package/docs/rich-evidence.md +13 -0
- package/docs/server.md +12 -0
- package/docs/ui.md +40 -1
- package/llms-full.txt +117 -1
- package/package.json +1 -1
- package/packages/schema/schemas/effective-delta.schema.json +18 -0
- package/packages/schema/schemas/effective-evidence.schema.json +18 -0
- package/packages/schema/schemas/evidence-page.schema.json +9 -0
- package/packages/schema/schemas/layer-rows.schema.json +9 -0
- package/packages/schema/schemas/report-run.schema.json +9 -0
- package/packages/schema/schemas/review-collection.schema.json +9 -0
- package/packages/schema/schemas/review-manifest.schema.json +9 -0
- package/packages/schema/schemas/test-catalog.schema.json +9 -0
- package/packages/schema/schemas/test-history.schema.json +18 -0
- package/packages/server/openapi.json +653 -1
- package/packages/visualizer/src/app/AppShell.tsx +2 -2
- package/packages/visualizer/src/app/router.tsx +25 -1
- package/packages/visualizer/src/components/Header.tsx +15 -4
- package/packages/visualizer/src/evidence/behavior-index.test.ts +119 -0
- package/packages/visualizer/src/evidence/behavior-index.ts +162 -0
- package/packages/visualizer/src/evidence/behavior-panel.tsx +36 -22
- package/packages/visualizer/src/evidence/behavior-return.test.ts +41 -0
- package/packages/visualizer/src/evidence/behavior-return.ts +59 -0
- package/packages/visualizer/src/evidence/behavior.ts +32 -1
- package/packages/visualizer/src/evidence/behaviors-page.tsx +465 -0
- package/packages/visualizer/src/evidence/feature-page.tsx +5 -26
- package/packages/visualizer/src/evidence/scoped-summary-view.tsx +110 -0
- package/packages/visualizer/src/evidence/scoped-summary.test.ts +62 -0
- package/packages/visualizer/src/evidence/scoped-summary.ts +118 -0
- package/packages/visualizer/src/evidence/spec-texts.ts +88 -0
- package/packages/visualizer/src/explorer/ArtifactsView.tsx +4 -4
- package/packages/visualizer/src/explorer/Explorer.tsx +1 -1
- package/packages/visualizer/src/explorer/RunsView.tsx +36 -10
- package/packages/visualizer/src/explorer/catalog.tsx +24 -1
- package/packages/visualizer/src/explorer/collections.tsx +5 -5
- package/packages/visualizer/src/explorer/navigate.ts +17 -0
- package/packages/visualizer/src/explorer/playlist-entries.test.ts +10 -1
- package/packages/visualizer/src/explorer/playlist-entries.ts +10 -0
- package/packages/visualizer/src/explorer/playlist.tsx +43 -8
- package/packages/visualizer/src/explorer/recording-verification.ts +58 -0
- package/packages/visualizer/src/explorer/search.ts +7 -1
- package/packages/visualizer/src/find/Finder.tsx +1 -62
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Atlas server API",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.7.0",
|
|
6
6
|
"summary": "Take in test results from every environment, keep them, and show everyone the combined report, live.",
|
|
7
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": {
|
|
@@ -4802,6 +4802,394 @@
|
|
|
4802
4802
|
}
|
|
4803
4803
|
}
|
|
4804
4804
|
},
|
|
4805
|
+
"/api/reports/recordings/verification": {
|
|
4806
|
+
"get": {
|
|
4807
|
+
"operationId": "getRecordingVerification",
|
|
4808
|
+
"tags": [
|
|
4809
|
+
"Report"
|
|
4810
|
+
],
|
|
4811
|
+
"summary": "Which stored recordings the server last read back, and which were gone or damaged",
|
|
4812
|
+
"description": "The newest read-back the server did of stored videos, per layer: how many it checked, how many passed and the `gaps` (a blob that is gone, bytes of another size or hash than were published, or a file that does not begin like its container), each naming the check that holds the video. `run` is the key of the run the layer belongs to (a `RunSummary.key`), so a viewer can mark that run's recordings as stored-then-unavailable beside its test results.\n\nThis route never reads a blob: it returns what a publish token's `POST` found earlier. A layer that was never read back is absent, which means \"not verified\", not \"fine\"; the result is kept in the server's memory only, so a restart empties it. Only layers a store still holds are listed (one removed by garbage collection drops out). No status, slot or winner depends on it. It checks stored bytes, not browser playback. Narrow with `?run=` (a run key) and `?layer=` (an id prefix of at least 7 hex digits, repeatable).\n\nRole needed: `read`.",
|
|
4813
|
+
"x-atlas-role": "read",
|
|
4814
|
+
"security": [
|
|
4815
|
+
{
|
|
4816
|
+
"bearer": []
|
|
4817
|
+
},
|
|
4818
|
+
{
|
|
4819
|
+
"basic": []
|
|
4820
|
+
}
|
|
4821
|
+
],
|
|
4822
|
+
"parameters": [
|
|
4823
|
+
{
|
|
4824
|
+
"required": false,
|
|
4825
|
+
"name": "run",
|
|
4826
|
+
"in": "query",
|
|
4827
|
+
"description": "Only layers of this run (a key from `GET /api/reports/runs`).",
|
|
4828
|
+
"schema": {
|
|
4829
|
+
"type": "string"
|
|
4830
|
+
}
|
|
4831
|
+
},
|
|
4832
|
+
{
|
|
4833
|
+
"required": false,
|
|
4834
|
+
"name": "layer",
|
|
4835
|
+
"in": "query",
|
|
4836
|
+
"description": "Only layers whose id starts with this prefix. Repeatable or comma-separated.",
|
|
4837
|
+
"schema": {
|
|
4838
|
+
"type": "string"
|
|
4839
|
+
}
|
|
4840
|
+
},
|
|
4841
|
+
{
|
|
4842
|
+
"required": false,
|
|
4843
|
+
"name": "project",
|
|
4844
|
+
"in": "query",
|
|
4845
|
+
"description": "Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.",
|
|
4846
|
+
"example": "todo-app",
|
|
4847
|
+
"schema": {
|
|
4848
|
+
"type": "string",
|
|
4849
|
+
"pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
|
|
4850
|
+
"maxLength": 64
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
],
|
|
4854
|
+
"responses": {
|
|
4855
|
+
"200": {
|
|
4856
|
+
"description": "The held read-backs.",
|
|
4857
|
+
"content": {
|
|
4858
|
+
"application/json": {
|
|
4859
|
+
"schema": {
|
|
4860
|
+
"$ref": "#/components/schemas/RecordingVerification"
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
},
|
|
4865
|
+
"401": {
|
|
4866
|
+
"description": "No token, or an unknown one. Send `Authorization: Bearer <token>`.",
|
|
4867
|
+
"content": {
|
|
4868
|
+
"application/problem+json": {
|
|
4869
|
+
"schema": {
|
|
4870
|
+
"$ref": "#/components/schemas/Problem"
|
|
4871
|
+
}
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
},
|
|
4877
|
+
"post": {
|
|
4878
|
+
"operationId": "verifyRecordings",
|
|
4879
|
+
"tags": [
|
|
4880
|
+
"Report"
|
|
4881
|
+
],
|
|
4882
|
+
"summary": "Read stored recordings back and check them (publish token)",
|
|
4883
|
+
"description": "Reads the videos of the newest layers (`limit`, default 20, at most 200; or the layers `layers` names) back from storage and checks that each is still stored, still has the size and SHA-256 published, and still begins like its media type's container. This reads blobs, so it needs a publish (or admin) token in a Bearer header; a reader-only token, a browser sign-in box and an anonymous reader are refused. One read-back runs at a time (`409` otherwise). It writes nothing to storage and changes no status. The answer is the same document `GET` returns, with `verified`: how many layers this pass read back.\n\nRole needed: `publish`.",
|
|
4884
|
+
"x-atlas-role": "publish",
|
|
4885
|
+
"security": [
|
|
4886
|
+
{
|
|
4887
|
+
"bearer": []
|
|
4888
|
+
}
|
|
4889
|
+
],
|
|
4890
|
+
"parameters": [
|
|
4891
|
+
{
|
|
4892
|
+
"required": false,
|
|
4893
|
+
"name": "project",
|
|
4894
|
+
"in": "query",
|
|
4895
|
+
"description": "Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.",
|
|
4896
|
+
"example": "todo-app",
|
|
4897
|
+
"schema": {
|
|
4898
|
+
"type": "string",
|
|
4899
|
+
"pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
|
|
4900
|
+
"maxLength": 64
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
],
|
|
4904
|
+
"requestBody": {
|
|
4905
|
+
"required": false,
|
|
4906
|
+
"description": "Optional `layers` (id prefixes) and `limit`. An empty body reads back the newest layers.",
|
|
4907
|
+
"content": {
|
|
4908
|
+
"application/json": {
|
|
4909
|
+
"schema": {
|
|
4910
|
+
"$ref": "#/components/schemas/RecordingVerifyRequest"
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
},
|
|
4915
|
+
"responses": {
|
|
4916
|
+
"200": {
|
|
4917
|
+
"description": "The read-backs now held.",
|
|
4918
|
+
"content": {
|
|
4919
|
+
"application/json": {
|
|
4920
|
+
"schema": {
|
|
4921
|
+
"$ref": "#/components/schemas/RecordingVerification"
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
},
|
|
4926
|
+
"401": {
|
|
4927
|
+
"description": "No token, or an unknown one. Send `Authorization: Bearer <token>`.",
|
|
4928
|
+
"content": {
|
|
4929
|
+
"application/problem+json": {
|
|
4930
|
+
"schema": {
|
|
4931
|
+
"$ref": "#/components/schemas/Problem"
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
},
|
|
4936
|
+
"403": {
|
|
4937
|
+
"description": "The token is known but its role may not do this.",
|
|
4938
|
+
"content": {
|
|
4939
|
+
"application/problem+json": {
|
|
4940
|
+
"schema": {
|
|
4941
|
+
"$ref": "#/components/schemas/Problem"
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
},
|
|
4946
|
+
"409": {
|
|
4947
|
+
"description": "A read-back is already running.",
|
|
4948
|
+
"content": {
|
|
4949
|
+
"application/problem+json": {
|
|
4950
|
+
"schema": {
|
|
4951
|
+
"$ref": "#/components/schemas/Problem"
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
},
|
|
4956
|
+
"413": {
|
|
4957
|
+
"description": "Request too large.",
|
|
4958
|
+
"content": {
|
|
4959
|
+
"application/problem+json": {
|
|
4960
|
+
"schema": {
|
|
4961
|
+
"$ref": "#/components/schemas/Problem"
|
|
4962
|
+
}
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
},
|
|
4966
|
+
"422": {
|
|
4967
|
+
"description": "Not a verification request.",
|
|
4968
|
+
"content": {
|
|
4969
|
+
"application/problem+json": {
|
|
4970
|
+
"schema": {
|
|
4971
|
+
"$ref": "#/components/schemas/Problem"
|
|
4972
|
+
}
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4975
|
+
},
|
|
4976
|
+
"502": {
|
|
4977
|
+
"description": "A store could not be read.",
|
|
4978
|
+
"content": {
|
|
4979
|
+
"application/problem+json": {
|
|
4980
|
+
"schema": {
|
|
4981
|
+
"$ref": "#/components/schemas/Problem"
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
},
|
|
4986
|
+
"503": {
|
|
4987
|
+
"description": "The server is still reading its backends. Retry after the number of seconds in `Retry-After`.",
|
|
4988
|
+
"content": {
|
|
4989
|
+
"application/problem+json": {
|
|
4990
|
+
"schema": {
|
|
4991
|
+
"$ref": "#/components/schemas/Problem"
|
|
4992
|
+
}
|
|
4993
|
+
}
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
}
|
|
4998
|
+
},
|
|
4999
|
+
"/api/projects/{project}/reports/recordings/verification": {
|
|
5000
|
+
"get": {
|
|
5001
|
+
"operationId": "getRecordingVerificationForProject",
|
|
5002
|
+
"tags": [
|
|
5003
|
+
"Report"
|
|
5004
|
+
],
|
|
5005
|
+
"summary": "Which stored recordings the server last read back, and which were gone or damaged",
|
|
5006
|
+
"description": "The newest read-back the server did of stored videos, per layer: how many it checked, how many passed and the `gaps` (a blob that is gone, bytes of another size or hash than were published, or a file that does not begin like its container), each naming the check that holds the video. `run` is the key of the run the layer belongs to (a `RunSummary.key`), so a viewer can mark that run's recordings as stored-then-unavailable beside its test results.\n\nThis route never reads a blob: it returns what a publish token's `POST` found earlier. A layer that was never read back is absent, which means \"not verified\", not \"fine\"; the result is kept in the server's memory only, so a restart empties it. Only layers a store still holds are listed (one removed by garbage collection drops out). No status, slot or winner depends on it. It checks stored bytes, not browser playback. Narrow with `?run=` (a run key) and `?layer=` (an id prefix of at least 7 hex digits, repeatable).\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: `read`.",
|
|
5007
|
+
"x-atlas-role": "read",
|
|
5008
|
+
"security": [
|
|
5009
|
+
{
|
|
5010
|
+
"bearer": []
|
|
5011
|
+
},
|
|
5012
|
+
{
|
|
5013
|
+
"basic": []
|
|
5014
|
+
}
|
|
5015
|
+
],
|
|
5016
|
+
"parameters": [
|
|
5017
|
+
{
|
|
5018
|
+
"required": true,
|
|
5019
|
+
"name": "project",
|
|
5020
|
+
"in": "path",
|
|
5021
|
+
"description": "Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.",
|
|
5022
|
+
"example": "todo-app",
|
|
5023
|
+
"schema": {
|
|
5024
|
+
"type": "string",
|
|
5025
|
+
"pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
|
|
5026
|
+
"maxLength": 64
|
|
5027
|
+
}
|
|
5028
|
+
},
|
|
5029
|
+
{
|
|
5030
|
+
"required": false,
|
|
5031
|
+
"name": "run",
|
|
5032
|
+
"in": "query",
|
|
5033
|
+
"description": "Only layers of this run (a key from `GET /api/reports/runs`).",
|
|
5034
|
+
"schema": {
|
|
5035
|
+
"type": "string"
|
|
5036
|
+
}
|
|
5037
|
+
},
|
|
5038
|
+
{
|
|
5039
|
+
"required": false,
|
|
5040
|
+
"name": "layer",
|
|
5041
|
+
"in": "query",
|
|
5042
|
+
"description": "Only layers whose id starts with this prefix. Repeatable or comma-separated.",
|
|
5043
|
+
"schema": {
|
|
5044
|
+
"type": "string"
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
],
|
|
5048
|
+
"responses": {
|
|
5049
|
+
"200": {
|
|
5050
|
+
"description": "The held read-backs.",
|
|
5051
|
+
"content": {
|
|
5052
|
+
"application/json": {
|
|
5053
|
+
"schema": {
|
|
5054
|
+
"$ref": "#/components/schemas/RecordingVerification"
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
}
|
|
5058
|
+
},
|
|
5059
|
+
"401": {
|
|
5060
|
+
"description": "No token, or an unknown one. Send `Authorization: Bearer <token>`.",
|
|
5061
|
+
"content": {
|
|
5062
|
+
"application/problem+json": {
|
|
5063
|
+
"schema": {
|
|
5064
|
+
"$ref": "#/components/schemas/Problem"
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
}
|
|
5070
|
+
},
|
|
5071
|
+
"post": {
|
|
5072
|
+
"operationId": "verifyRecordingsForProject",
|
|
5073
|
+
"tags": [
|
|
5074
|
+
"Report"
|
|
5075
|
+
],
|
|
5076
|
+
"summary": "Read stored recordings back and check them (publish token)",
|
|
5077
|
+
"description": "Reads the videos of the newest layers (`limit`, default 20, at most 200; or the layers `layers` names) back from storage and checks that each is still stored, still has the size and SHA-256 published, and still begins like its media type's container. This reads blobs, so it needs a publish (or admin) token in a Bearer header; a reader-only token, a browser sign-in box and an anonymous reader are refused. One read-back runs at a time (`409` otherwise). It writes nothing to storage and changes no status. The answer is the same document `GET` returns, with `verified`: how many layers this pass read back.\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: `publish`.",
|
|
5078
|
+
"x-atlas-role": "publish",
|
|
5079
|
+
"security": [
|
|
5080
|
+
{
|
|
5081
|
+
"bearer": []
|
|
5082
|
+
}
|
|
5083
|
+
],
|
|
5084
|
+
"parameters": [
|
|
5085
|
+
{
|
|
5086
|
+
"required": true,
|
|
5087
|
+
"name": "project",
|
|
5088
|
+
"in": "path",
|
|
5089
|
+
"description": "Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.",
|
|
5090
|
+
"example": "todo-app",
|
|
5091
|
+
"schema": {
|
|
5092
|
+
"type": "string",
|
|
5093
|
+
"pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
|
|
5094
|
+
"maxLength": 64
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
],
|
|
5098
|
+
"requestBody": {
|
|
5099
|
+
"required": false,
|
|
5100
|
+
"description": "Optional `layers` (id prefixes) and `limit`. An empty body reads back the newest layers.",
|
|
5101
|
+
"content": {
|
|
5102
|
+
"application/json": {
|
|
5103
|
+
"schema": {
|
|
5104
|
+
"$ref": "#/components/schemas/RecordingVerifyRequest"
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
},
|
|
5109
|
+
"responses": {
|
|
5110
|
+
"200": {
|
|
5111
|
+
"description": "The read-backs now held.",
|
|
5112
|
+
"content": {
|
|
5113
|
+
"application/json": {
|
|
5114
|
+
"schema": {
|
|
5115
|
+
"$ref": "#/components/schemas/RecordingVerification"
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
},
|
|
5120
|
+
"401": {
|
|
5121
|
+
"description": "No token, or an unknown one. Send `Authorization: Bearer <token>`.",
|
|
5122
|
+
"content": {
|
|
5123
|
+
"application/problem+json": {
|
|
5124
|
+
"schema": {
|
|
5125
|
+
"$ref": "#/components/schemas/Problem"
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
},
|
|
5130
|
+
"403": {
|
|
5131
|
+
"description": "The token is known but its role may not do this.",
|
|
5132
|
+
"content": {
|
|
5133
|
+
"application/problem+json": {
|
|
5134
|
+
"schema": {
|
|
5135
|
+
"$ref": "#/components/schemas/Problem"
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
},
|
|
5140
|
+
"409": {
|
|
5141
|
+
"description": "A read-back is already running.",
|
|
5142
|
+
"content": {
|
|
5143
|
+
"application/problem+json": {
|
|
5144
|
+
"schema": {
|
|
5145
|
+
"$ref": "#/components/schemas/Problem"
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
},
|
|
5150
|
+
"413": {
|
|
5151
|
+
"description": "Request too large.",
|
|
5152
|
+
"content": {
|
|
5153
|
+
"application/problem+json": {
|
|
5154
|
+
"schema": {
|
|
5155
|
+
"$ref": "#/components/schemas/Problem"
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
},
|
|
5160
|
+
"422": {
|
|
5161
|
+
"description": "Not a verification request.",
|
|
5162
|
+
"content": {
|
|
5163
|
+
"application/problem+json": {
|
|
5164
|
+
"schema": {
|
|
5165
|
+
"$ref": "#/components/schemas/Problem"
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
},
|
|
5170
|
+
"502": {
|
|
5171
|
+
"description": "A store could not be read.",
|
|
5172
|
+
"content": {
|
|
5173
|
+
"application/problem+json": {
|
|
5174
|
+
"schema": {
|
|
5175
|
+
"$ref": "#/components/schemas/Problem"
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
},
|
|
5180
|
+
"503": {
|
|
5181
|
+
"description": "The server is still reading its backends. Retry after the number of seconds in `Retry-After`.",
|
|
5182
|
+
"content": {
|
|
5183
|
+
"application/problem+json": {
|
|
5184
|
+
"schema": {
|
|
5185
|
+
"$ref": "#/components/schemas/Problem"
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
}
|
|
5192
|
+
},
|
|
4805
5193
|
"/api/reports/review-collections": {
|
|
4806
5194
|
"get": {
|
|
4807
5195
|
"operationId": "listReviewCollections",
|
|
@@ -10752,6 +11140,15 @@
|
|
|
10752
11140
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
10753
11141
|
"type": "string"
|
|
10754
11142
|
},
|
|
11143
|
+
"durationMs": {
|
|
11144
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
11145
|
+
"type": "number",
|
|
11146
|
+
"minimum": 0
|
|
11147
|
+
},
|
|
11148
|
+
"poster": {
|
|
11149
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
11150
|
+
"type": "string"
|
|
11151
|
+
},
|
|
10755
11152
|
"scope": {
|
|
10756
11153
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
10757
11154
|
"type": "object",
|
|
@@ -11235,6 +11632,15 @@
|
|
|
11235
11632
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
11236
11633
|
"type": "string"
|
|
11237
11634
|
},
|
|
11635
|
+
"durationMs": {
|
|
11636
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
11637
|
+
"type": "number",
|
|
11638
|
+
"minimum": 0
|
|
11639
|
+
},
|
|
11640
|
+
"poster": {
|
|
11641
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
11642
|
+
"type": "string"
|
|
11643
|
+
},
|
|
11238
11644
|
"scope": {
|
|
11239
11645
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
11240
11646
|
"type": "object",
|
|
@@ -11753,6 +12159,15 @@
|
|
|
11753
12159
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
11754
12160
|
"type": "string"
|
|
11755
12161
|
},
|
|
12162
|
+
"durationMs": {
|
|
12163
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
12164
|
+
"type": "number",
|
|
12165
|
+
"minimum": 0
|
|
12166
|
+
},
|
|
12167
|
+
"poster": {
|
|
12168
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
12169
|
+
"type": "string"
|
|
12170
|
+
},
|
|
11756
12171
|
"scope": {
|
|
11757
12172
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
11758
12173
|
"type": "object",
|
|
@@ -12236,6 +12651,15 @@
|
|
|
12236
12651
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
12237
12652
|
"type": "string"
|
|
12238
12653
|
},
|
|
12654
|
+
"durationMs": {
|
|
12655
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
12656
|
+
"type": "number",
|
|
12657
|
+
"minimum": 0
|
|
12658
|
+
},
|
|
12659
|
+
"poster": {
|
|
12660
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
12661
|
+
"type": "string"
|
|
12662
|
+
},
|
|
12239
12663
|
"scope": {
|
|
12240
12664
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
12241
12665
|
"type": "object",
|
|
@@ -15648,6 +16072,15 @@
|
|
|
15648
16072
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
15649
16073
|
"type": "string"
|
|
15650
16074
|
},
|
|
16075
|
+
"durationMs": {
|
|
16076
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
16077
|
+
"type": "number",
|
|
16078
|
+
"minimum": 0
|
|
16079
|
+
},
|
|
16080
|
+
"poster": {
|
|
16081
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
16082
|
+
"type": "string"
|
|
16083
|
+
},
|
|
15651
16084
|
"scope": {
|
|
15652
16085
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
15653
16086
|
"type": "object",
|
|
@@ -16146,6 +16579,15 @@
|
|
|
16146
16579
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
16147
16580
|
"type": "string"
|
|
16148
16581
|
},
|
|
16582
|
+
"durationMs": {
|
|
16583
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
16584
|
+
"type": "number",
|
|
16585
|
+
"minimum": 0
|
|
16586
|
+
},
|
|
16587
|
+
"poster": {
|
|
16588
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
16589
|
+
"type": "string"
|
|
16590
|
+
},
|
|
16149
16591
|
"scope": {
|
|
16150
16592
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
16151
16593
|
"type": "object",
|
|
@@ -18760,6 +19202,15 @@
|
|
|
18760
19202
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
18761
19203
|
"type": "string"
|
|
18762
19204
|
},
|
|
19205
|
+
"durationMs": {
|
|
19206
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
19207
|
+
"type": "number",
|
|
19208
|
+
"minimum": 0
|
|
19209
|
+
},
|
|
19210
|
+
"poster": {
|
|
19211
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
19212
|
+
"type": "string"
|
|
19213
|
+
},
|
|
18763
19214
|
"scope": {
|
|
18764
19215
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
18765
19216
|
"type": "object",
|
|
@@ -19246,6 +19697,15 @@
|
|
|
19246
19697
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
19247
19698
|
"type": "string"
|
|
19248
19699
|
},
|
|
19700
|
+
"durationMs": {
|
|
19701
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
19702
|
+
"type": "number",
|
|
19703
|
+
"minimum": 0
|
|
19704
|
+
},
|
|
19705
|
+
"poster": {
|
|
19706
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
19707
|
+
"type": "string"
|
|
19708
|
+
},
|
|
19249
19709
|
"scope": {
|
|
19250
19710
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
19251
19711
|
"type": "object",
|
|
@@ -19892,6 +20352,15 @@
|
|
|
19892
20352
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
19893
20353
|
"type": "string"
|
|
19894
20354
|
},
|
|
20355
|
+
"durationMs": {
|
|
20356
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
20357
|
+
"type": "number",
|
|
20358
|
+
"minimum": 0
|
|
20359
|
+
},
|
|
20360
|
+
"poster": {
|
|
20361
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
20362
|
+
"type": "string"
|
|
20363
|
+
},
|
|
19895
20364
|
"scope": {
|
|
19896
20365
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
19897
20366
|
"type": "object",
|
|
@@ -20144,6 +20613,144 @@
|
|
|
20144
20613
|
],
|
|
20145
20614
|
"additionalProperties": {}
|
|
20146
20615
|
},
|
|
20616
|
+
"RecordingVerification": {
|
|
20617
|
+
"type": "object",
|
|
20618
|
+
"properties": {
|
|
20619
|
+
"schemaVersion": {
|
|
20620
|
+
"type": "number",
|
|
20621
|
+
"const": 1
|
|
20622
|
+
},
|
|
20623
|
+
"layers": {
|
|
20624
|
+
"type": "array",
|
|
20625
|
+
"items": {
|
|
20626
|
+
"type": "object",
|
|
20627
|
+
"properties": {
|
|
20628
|
+
"layer": {
|
|
20629
|
+
"type": "string",
|
|
20630
|
+
"description": "The layer id"
|
|
20631
|
+
},
|
|
20632
|
+
"run": {
|
|
20633
|
+
"type": "string",
|
|
20634
|
+
"description": "The key of the run the layer belongs to (a `RunSummary.key`)"
|
|
20635
|
+
},
|
|
20636
|
+
"verifiedAtMs": {
|
|
20637
|
+
"type": "number",
|
|
20638
|
+
"description": "When the server read the videos back, epoch milliseconds"
|
|
20639
|
+
},
|
|
20640
|
+
"checked": {
|
|
20641
|
+
"type": "integer",
|
|
20642
|
+
"minimum": -9007199254740991,
|
|
20643
|
+
"maximum": 9007199254740991,
|
|
20644
|
+
"description": "Videos read back: those that name a bundle key"
|
|
20645
|
+
},
|
|
20646
|
+
"ok": {
|
|
20647
|
+
"type": "integer",
|
|
20648
|
+
"minimum": -9007199254740991,
|
|
20649
|
+
"maximum": 9007199254740991,
|
|
20650
|
+
"description": "Of those, the ones that passed every check"
|
|
20651
|
+
},
|
|
20652
|
+
"referenced": {
|
|
20653
|
+
"type": "integer",
|
|
20654
|
+
"minimum": -9007199254740991,
|
|
20655
|
+
"maximum": 9007199254740991,
|
|
20656
|
+
"description": "Videos given only by address, which Atlas cannot read back and so does not vouch for"
|
|
20657
|
+
},
|
|
20658
|
+
"gaps": {
|
|
20659
|
+
"type": "array",
|
|
20660
|
+
"items": {
|
|
20661
|
+
"type": "object",
|
|
20662
|
+
"properties": {
|
|
20663
|
+
"check": {
|
|
20664
|
+
"description": "The id of the check that holds the video, or null for a video attached to the run or a part",
|
|
20665
|
+
"type": [
|
|
20666
|
+
"string",
|
|
20667
|
+
"null"
|
|
20668
|
+
]
|
|
20669
|
+
},
|
|
20670
|
+
"name": {
|
|
20671
|
+
"type": "string",
|
|
20672
|
+
"description": "The attachment's name"
|
|
20673
|
+
},
|
|
20674
|
+
"bundleKey": {
|
|
20675
|
+
"type": "string",
|
|
20676
|
+
"description": "The key the layer names the file by"
|
|
20677
|
+
},
|
|
20678
|
+
"problem": {
|
|
20679
|
+
"type": "string",
|
|
20680
|
+
"description": "`not-in-bundle`, `blob-missing`, `unreadable`, `size-mismatch`, `checksum-mismatch` or `undecodable`. An open vocabulary: treat an unknown value as a gap"
|
|
20681
|
+
},
|
|
20682
|
+
"reason": {
|
|
20683
|
+
"type": "string",
|
|
20684
|
+
"description": "A short explanation without secrets or paths"
|
|
20685
|
+
}
|
|
20686
|
+
},
|
|
20687
|
+
"required": [
|
|
20688
|
+
"check",
|
|
20689
|
+
"name",
|
|
20690
|
+
"bundleKey",
|
|
20691
|
+
"problem",
|
|
20692
|
+
"reason"
|
|
20693
|
+
],
|
|
20694
|
+
"additionalProperties": {}
|
|
20695
|
+
},
|
|
20696
|
+
"description": "The videos that did not pass. Never a test result: statuses are unchanged"
|
|
20697
|
+
}
|
|
20698
|
+
},
|
|
20699
|
+
"required": [
|
|
20700
|
+
"layer",
|
|
20701
|
+
"run",
|
|
20702
|
+
"verifiedAtMs",
|
|
20703
|
+
"checked",
|
|
20704
|
+
"ok",
|
|
20705
|
+
"referenced",
|
|
20706
|
+
"gaps"
|
|
20707
|
+
],
|
|
20708
|
+
"additionalProperties": {}
|
|
20709
|
+
},
|
|
20710
|
+
"description": "Layers the server has read back and still holds, newest first"
|
|
20711
|
+
},
|
|
20712
|
+
"notices": {
|
|
20713
|
+
"type": "array",
|
|
20714
|
+
"items": {
|
|
20715
|
+
"type": "string"
|
|
20716
|
+
},
|
|
20717
|
+
"description": "Layers the last pass could not read at all: their recordings are unknown, not verified"
|
|
20718
|
+
},
|
|
20719
|
+
"verified": {
|
|
20720
|
+
"description": "POST only: how many layers this pass read back",
|
|
20721
|
+
"type": "integer",
|
|
20722
|
+
"minimum": -9007199254740991,
|
|
20723
|
+
"maximum": 9007199254740991
|
|
20724
|
+
}
|
|
20725
|
+
},
|
|
20726
|
+
"required": [
|
|
20727
|
+
"schemaVersion",
|
|
20728
|
+
"layers",
|
|
20729
|
+
"notices"
|
|
20730
|
+
],
|
|
20731
|
+
"additionalProperties": {}
|
|
20732
|
+
},
|
|
20733
|
+
"RecordingVerifyRequest": {
|
|
20734
|
+
"type": "object",
|
|
20735
|
+
"properties": {
|
|
20736
|
+
"layers": {
|
|
20737
|
+
"description": "Only layers whose id starts with one of these (at least 7 hex digits)",
|
|
20738
|
+
"maxItems": 50,
|
|
20739
|
+
"type": "array",
|
|
20740
|
+
"items": {
|
|
20741
|
+
"type": "string",
|
|
20742
|
+
"pattern": "^[0-9a-f]{7,64}$"
|
|
20743
|
+
}
|
|
20744
|
+
},
|
|
20745
|
+
"limit": {
|
|
20746
|
+
"description": "How many of the newest layers to read back. Default 20, at most 200",
|
|
20747
|
+
"type": "integer",
|
|
20748
|
+
"minimum": 1,
|
|
20749
|
+
"maximum": 200
|
|
20750
|
+
}
|
|
20751
|
+
},
|
|
20752
|
+
"additionalProperties": {}
|
|
20753
|
+
},
|
|
20147
20754
|
"TestCatalog": {
|
|
20148
20755
|
"type": "object",
|
|
20149
20756
|
"properties": {
|
|
@@ -21151,6 +21758,15 @@
|
|
|
21151
21758
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
21152
21759
|
"type": "string"
|
|
21153
21760
|
},
|
|
21761
|
+
"durationMs": {
|
|
21762
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
21763
|
+
"type": "number",
|
|
21764
|
+
"minimum": 0
|
|
21765
|
+
},
|
|
21766
|
+
"poster": {
|
|
21767
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
21768
|
+
"type": "string"
|
|
21769
|
+
},
|
|
21154
21770
|
"scope": {
|
|
21155
21771
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
21156
21772
|
"type": "object",
|
|
@@ -22346,6 +22962,15 @@
|
|
|
22346
22962
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
22347
22963
|
"type": "string"
|
|
22348
22964
|
},
|
|
22965
|
+
"durationMs": {
|
|
22966
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
22967
|
+
"type": "number",
|
|
22968
|
+
"minimum": 0
|
|
22969
|
+
},
|
|
22970
|
+
"poster": {
|
|
22971
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
22972
|
+
"type": "string"
|
|
22973
|
+
},
|
|
22349
22974
|
"scope": {
|
|
22350
22975
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
22351
22976
|
"type": "object",
|
|
@@ -23021,6 +23646,15 @@
|
|
|
23021
23646
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
23022
23647
|
"type": "string"
|
|
23023
23648
|
},
|
|
23649
|
+
"durationMs": {
|
|
23650
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
23651
|
+
"type": "number",
|
|
23652
|
+
"minimum": 0
|
|
23653
|
+
},
|
|
23654
|
+
"poster": {
|
|
23655
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
23656
|
+
"type": "string"
|
|
23657
|
+
},
|
|
23024
23658
|
"scope": {
|
|
23025
23659
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
23026
23660
|
"type": "object",
|
|
@@ -24600,6 +25234,15 @@
|
|
|
24600
25234
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
24601
25235
|
"type": "string"
|
|
24602
25236
|
},
|
|
25237
|
+
"durationMs": {
|
|
25238
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
25239
|
+
"type": "number",
|
|
25240
|
+
"minimum": 0
|
|
25241
|
+
},
|
|
25242
|
+
"poster": {
|
|
25243
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
25244
|
+
"type": "string"
|
|
25245
|
+
},
|
|
24603
25246
|
"scope": {
|
|
24604
25247
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
24605
25248
|
"type": "object",
|
|
@@ -26136,6 +26779,15 @@
|
|
|
26136
26779
|
"description": "Why it is unavailable, when the report can tell: `not-in-bundle` is a file the layer names but does not hold (stored, then gone). An open vocabulary: treat an unknown reason as plain unavailable",
|
|
26137
26780
|
"type": "string"
|
|
26138
26781
|
},
|
|
26782
|
+
"durationMs": {
|
|
26783
|
+
"description": "How long the recording is, in milliseconds, as its producer declared it: a hint to show before the file is opened, never a latency. Absent when none was declared, and in documents of older servers",
|
|
26784
|
+
"type": "number",
|
|
26785
|
+
"minimum": 0
|
|
26786
|
+
},
|
|
26787
|
+
"poster": {
|
|
26788
|
+
"description": "The bundle key, in the same layer, of the image the producer named as this recording's poster: a hint to show before the file is opened. Absent when there is none or the layer's bundle does not hold it, and in documents of older servers",
|
|
26789
|
+
"type": "string"
|
|
26790
|
+
},
|
|
26139
26791
|
"scope": {
|
|
26140
26792
|
"description": "What this recording shows as its producer declared it: its own `scope`, else its attempt's, check's, part's or layer's. Absent: the scope is unknown, never live, physical or audible",
|
|
26141
26793
|
"type": "object",
|