steam-data-schema 1.0.0.dev1__tar.gz

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.
@@ -0,0 +1,3 @@
1
+ # Package-only ignore rules; do not inherit private publisher configuration paths.
2
+ __pycache__/
3
+ *.pyc
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Steam Data contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: steam-data-schema
3
+ Version: 1.0.0.dev1
4
+ Summary: Independent current Steam catalog snapshot contract
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+
10
+ # Steam Data Schema
11
+
12
+ The shared, versioned contract for Steam Data Reader snapshots. This package contains
13
+ the field registry, transport-table definitions, manifest validation, compatibility
14
+ checks, JSON Schema, and canonicalization rules. It has no third-party dependencies.
15
+
16
+ Consumers normally install it automatically with `steam-data-reader`. Package
17
+ version, snapshot schema version, and dataset version are separate identifiers.
18
+ An increment must use exactly the schema of its baseline. An unsupported baseline
19
+ requires a compatible reader upgrade before downloading its data; installed data
20
+ remains available.
21
+
22
+ This software is licensed under MIT. That license applies to the software, not to
23
+ Steam data or other third-party content delivered in a snapshot.
@@ -0,0 +1,14 @@
1
+ # Steam Data Schema
2
+
3
+ The shared, versioned contract for Steam Data Reader snapshots. This package contains
4
+ the field registry, transport-table definitions, manifest validation, compatibility
5
+ checks, JSON Schema, and canonicalization rules. It has no third-party dependencies.
6
+
7
+ Consumers normally install it automatically with `steam-data-reader`. Package
8
+ version, snapshot schema version, and dataset version are separate identifiers.
9
+ An increment must use exactly the schema of its baseline. An unsupported baseline
10
+ requires a compatible reader upgrade before downloading its data; installed data
11
+ remains available.
12
+
13
+ This software is licensed under MIT. That license applies to the software, not to
14
+ Steam data or other third-party content delivered in a snapshot.
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27,<2"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "steam-data-schema"
7
+ version = "1.0.0.dev1"
8
+ description = "Independent current Steam catalog snapshot contract"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ dependencies = []
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["src/steam_data_schema"]
17
+ core-metadata-version = "2.4"
18
+
19
+ [tool.hatch.build.targets.sdist]
20
+ core-metadata-version = "2.4"
21
+ include = ["/src/steam_data_schema", "/README.md", "/LICENSE", "/pyproject.toml", "/.gitignore"]
22
+ exclude = ["**/__pycache__/**", "**/*.pyc"]
@@ -0,0 +1,359 @@
1
+ """Public contract. Standard library only; no acquisition or database dependencies."""
2
+
3
+ import hashlib
4
+ import json
5
+ import re
6
+ import unicodedata
7
+ from datetime import UTC, datetime
8
+
9
+ SCHEMA_VERSION = "1.0"
10
+ PROTOCOL_VERSION = 1
11
+ READER_VERSION = "1.0.0.dev1"
12
+ DATASET_ID = "steam-current"
13
+
14
+
15
+ def canonical(value):
16
+ return json.dumps(
17
+ value,
18
+ sort_keys=True,
19
+ ensure_ascii=False,
20
+ separators=(",", ":"),
21
+ allow_nan=False,
22
+ default=json_default,
23
+ ).encode("utf-8")
24
+
25
+
26
+ def json_default(value):
27
+ if isinstance(value, datetime):
28
+ if value.tzinfo is None:
29
+ raise ValueError("Timestamp needs a timezone")
30
+ return value.astimezone(UTC).isoformat(timespec="microseconds").replace("+00:00", "Z")
31
+ raise TypeError("Unsupported JSON value")
32
+
33
+
34
+ def sha256(body):
35
+ return hashlib.sha256(body).hexdigest()
36
+
37
+
38
+ def normalize_text(value):
39
+ if not isinstance(value, str) or not value:
40
+ raise ValueError("Search text must be a nonempty string")
41
+ return unicodedata.normalize("NFC", unicodedata.normalize("NFC", value).casefold())
42
+
43
+
44
+ def app_id(value):
45
+ if isinstance(value, bool) or not isinstance(value, int) or not 0 < value < 2**63:
46
+ raise ValueError("App IDs must be positive 64-bit integers")
47
+ return value
48
+
49
+
50
+ def identifier(value):
51
+ if not isinstance(value, str) or not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,127}", value):
52
+ raise ValueError("Invalid release identifier")
53
+ return value
54
+
55
+
56
+ def table(columns, key):
57
+ return {"columns": dict(columns), "key": key}
58
+
59
+
60
+ TEXT_FIELDS = [
61
+ "name",
62
+ "app_type",
63
+ "website",
64
+ "supported_languages",
65
+ "required_age",
66
+ "controller_support",
67
+ "header_image",
68
+ "capsule_image",
69
+ "capsule_imagev5",
70
+ ]
71
+ JSON_FIELDS = [
72
+ "platforms",
73
+ "pc_requirements",
74
+ "mac_requirements",
75
+ "linux_requirements",
76
+ "release_info",
77
+ "content_descriptors",
78
+ "support_info",
79
+ "ratings",
80
+ "extensions",
81
+ ]
82
+ DESCRIPTIONS = ["short_description", "detailed_description", "about_the_game"]
83
+ TABLES = {
84
+ "app_search": table(
85
+ [
86
+ ("steam_appid", "BIGINT"),
87
+ ("name_key", "VARCHAR"),
88
+ ("developer_keys", "VARCHAR[]"),
89
+ ("publisher_keys", "VARCHAR[]"),
90
+ ],
91
+ ["steam_appid"],
92
+ ),
93
+ "app_catalog": table(
94
+ [
95
+ ("steam_appid", "BIGINT"),
96
+ ("catalog_name", "VARCHAR"),
97
+ ("first_seen_at", "TIMESTAMPTZ"),
98
+ ("last_seen_at", "TIMESTAMPTZ"),
99
+ ],
100
+ ["steam_appid"],
101
+ ),
102
+ "app_details": table(
103
+ [
104
+ ("steam_appid", "BIGINT"),
105
+ *[(f, "VARCHAR") for f in TEXT_FIELDS],
106
+ ("is_free", "BOOLEAN"),
107
+ *[(f, "JSON") for f in JSON_FIELDS],
108
+ ],
109
+ ["steam_appid"],
110
+ ),
111
+ "app_descriptions": table(
112
+ [("steam_appid", "BIGINT"), *[(f, "VARCHAR") for f in DESCRIPTIONS]], ["steam_appid"]
113
+ ),
114
+ "app_sets": table(
115
+ [
116
+ ("steam_appid", "BIGINT"),
117
+ ("developers", "VARCHAR[]"),
118
+ ("publishers", "VARCHAR[]"),
119
+ ("genres", "JSON"),
120
+ ("categories", "JSON"),
121
+ ("tags", "JSON"),
122
+ ],
123
+ ["steam_appid"],
124
+ ),
125
+ "review_summaries": table(
126
+ [
127
+ ("steam_appid", "BIGINT"),
128
+ ("review_series_id", "VARCHAR"),
129
+ ("observed_at", "TIMESTAMPTZ"),
130
+ ("source_id", "VARCHAR"),
131
+ ("observation_id", "VARCHAR"),
132
+ ("total_positive", "BIGINT"),
133
+ ("total_negative", "BIGINT"),
134
+ ("total_reviews", "BIGINT"),
135
+ ("positive_percentage", "DOUBLE"),
136
+ ("review_score", "BIGINT"),
137
+ ("review_score_desc", "VARCHAR"),
138
+ ],
139
+ ["steam_appid", "review_series_id"],
140
+ ),
141
+ "review_series": table(
142
+ [("review_series_id", "VARCHAR"), ("definition_json", "JSON"), ("description", "VARCHAR")],
143
+ ["review_series_id"],
144
+ ),
145
+ "prices": table(
146
+ [
147
+ ("steam_appid", "BIGINT"),
148
+ ("country", "VARCHAR"),
149
+ ("language", "VARCHAR"),
150
+ ("currency", "VARCHAR"),
151
+ ("initial_minor", "BIGINT"),
152
+ ("final_minor", "BIGINT"),
153
+ ("discount_percentage", "BIGINT"),
154
+ ("observed_at", "TIMESTAMPTZ"),
155
+ ("source_id", "VARCHAR"),
156
+ ("observation_id", "VARCHAR"),
157
+ ],
158
+ ["steam_appid", "country", "language", "currency"],
159
+ ),
160
+ "app_organizations": table(
161
+ [
162
+ ("steam_appid", "BIGINT"),
163
+ ("role", "VARCHAR"),
164
+ ("organization_id", "VARCHAR"),
165
+ ("original_name", "VARCHAR"),
166
+ ("source_id", "VARCHAR"),
167
+ ("source_url", "VARCHAR"),
168
+ ("identity_quality", "VARCHAR"),
169
+ ],
170
+ ["steam_appid", "role", "organization_id"],
171
+ ),
172
+ "app_relationships": table(
173
+ [
174
+ ("steam_appid", "BIGINT"),
175
+ ("relation_type", "VARCHAR"),
176
+ ("target_appid", "BIGINT"),
177
+ ("source_id", "VARCHAR"),
178
+ ("observation_id", "VARCHAR"),
179
+ ("observed_at", "TIMESTAMPTZ"),
180
+ ],
181
+ ["steam_appid", "relation_type", "target_appid"],
182
+ ),
183
+ "field_provenance": table(
184
+ [
185
+ ("steam_appid", "BIGINT"),
186
+ ("field_name", "VARCHAR"),
187
+ ("context_id", "VARCHAR"),
188
+ ("provenance_id", "VARCHAR"),
189
+ ("source_id", "VARCHAR"),
190
+ ("observation_id", "VARCHAR"),
191
+ ("observed_at", "TIMESTAMPTZ"),
192
+ ("value_state", "VARCHAR"),
193
+ ("timestamp_quality", "VARCHAR"),
194
+ ("context_json", "JSON"),
195
+ ("parser_version", "VARCHAR"),
196
+ ("resolution_version", "VARCHAR"),
197
+ ("source_url", "VARCHAR"),
198
+ ],
199
+ ["steam_appid", "field_name", "context_id", "provenance_id"],
200
+ ),
201
+ "acquisition_status": table(
202
+ [
203
+ ("steam_appid", "BIGINT"),
204
+ ("source_id", "VARCHAR"),
205
+ ("data_family", "VARCHAR"),
206
+ ("context_id", "VARCHAR"),
207
+ ("context_json", "JSON"),
208
+ ("latest_attempt_at", "TIMESTAMPTZ"),
209
+ ("latest_attempt_status", "VARCHAR"),
210
+ ("last_success_at", "TIMESTAMPTZ"),
211
+ ("support_status", "VARCHAR"),
212
+ ],
213
+ ["steam_appid", "source_id", "data_family", "context_id"],
214
+ ),
215
+ }
216
+ for singular, plural in (("genre", "genres"), ("category", "categories"), ("tag", "tags")):
217
+ TABLES[plural] = table(
218
+ [(singular + "_id", "VARCHAR"), ("label", "VARCHAR")], [singular + "_id"]
219
+ )
220
+ TABLES["app_" + plural] = table(
221
+ [
222
+ ("steam_appid", "BIGINT"),
223
+ (singular + "_id", "VARCHAR"),
224
+ *(
225
+ [("source_rank", "BIGINT"), ("source_weight", "DOUBLE")]
226
+ if singular == "tag"
227
+ else []
228
+ ),
229
+ ],
230
+ ["steam_appid", singular + "_id"],
231
+ )
232
+
233
+ INFO_COLUMNS = {
234
+ "dataset_id": "VARCHAR",
235
+ "dataset_version": "VARCHAR",
236
+ "chain_id": "VARCHAR",
237
+ "baseline_version": "VARCHAR",
238
+ "increment_sequence": "BIGINT",
239
+ "schema_version": "VARCHAR",
240
+ "published_at": "TIMESTAMPTZ",
241
+ "input_boundary_at": "TIMESTAMPTZ",
242
+ "source_release_id": "VARCHAR",
243
+ "logical_state_sha256": "VARCHAR",
244
+ "app_count": "BIGINT",
245
+ "default_review_series_id": "VARCHAR",
246
+ "metadata_country": "VARCHAR",
247
+ "metadata_language": "VARCHAR",
248
+ "price_country": "VARCHAR",
249
+ "price_language": "VARCHAR",
250
+ "coverage_json": "JSON",
251
+ "feature_support_json": "JSON",
252
+ "freshness_json": "JSON",
253
+ }
254
+ APP_COLUMNS = {
255
+ "steam_appid": "BIGINT",
256
+ **{f: "VARCHAR" for f in TEXT_FIELDS},
257
+ "steam_url": "VARCHAR",
258
+ **{f: "VARCHAR" for f in DESCRIPTIONS},
259
+ "is_free": "BOOLEAN",
260
+ **{f: "JSON" for f in JSON_FIELDS},
261
+ "first_seen_at": "TIMESTAMPTZ",
262
+ "last_seen_at": "TIMESTAMPTZ",
263
+ "name_origin": "VARCHAR",
264
+ "developers": "VARCHAR[]",
265
+ "publishers": "VARCHAR[]",
266
+ "genres": "JSON",
267
+ "categories": "JSON",
268
+ "tags": "JSON",
269
+ "default_review_series_id": "VARCHAR",
270
+ "reviews_observed_at": "TIMESTAMPTZ",
271
+ "total_positive": "BIGINT",
272
+ "total_negative": "BIGINT",
273
+ "total_reviews": "BIGINT",
274
+ "positive_percentage": "DOUBLE",
275
+ "review_score": "BIGINT",
276
+ "review_score_desc": "VARCHAR",
277
+ "price_country": "VARCHAR",
278
+ "price_currency": "VARCHAR",
279
+ "price_initial_minor": "BIGINT",
280
+ "price_final_minor": "BIGINT",
281
+ "price_discount_percentage": "BIGINT",
282
+ "price_observed_at": "TIMESTAMPTZ",
283
+ }
284
+ SPECIAL_FIELDS = {"relationships": "JSON", "acquisition_status": "JSON", "provenance": "JSON"}
285
+ APP_FIELDS = {**APP_COLUMNS, **SPECIAL_FIELDS}
286
+ MINIMAL_FIELDS = ["steam_appid", "name", "developers", "publishers", "app_type"]
287
+
288
+
289
+ def reader_version(value):
290
+ """Protocol subset of PEP 440: X.Y.Z and X.Y.Z.devN, ordered before X.Y.Z.
291
+
292
+ Unknown version forms fail closed. This is a snapshot compatibility field,
293
+ not a general-purpose Python package requirement parser.
294
+ """
295
+ if not isinstance(value, str):
296
+ # Malformed manifest metadata follows the same upgrade/refusal path.
297
+ raise ValueError("Unsupported minimum reader version") # noqa: TRY004
298
+ match = re.fullmatch(r"([0-9]+)\.([0-9]+)\.([0-9]+)(?:\.dev([0-9]+))?", value)
299
+ if not match:
300
+ raise ValueError("Unsupported minimum reader version")
301
+ major, minor, patch, dev = match.groups()
302
+ return (int(major), int(minor), int(patch), 1 if dev is None else 0, int(dev or 0))
303
+
304
+
305
+ def check_compatibility(manifest):
306
+ if (
307
+ manifest.get("schema_version") != SCHEMA_VERSION
308
+ or manifest.get("protocol_version") != PROTOCOL_VERSION
309
+ or reader_version(manifest.get("minimum_reader_version", "0.0.0"))
310
+ > reader_version(READER_VERSION)
311
+ ):
312
+ raise ValueError("Reader upgrade required for schema/protocol/minimum reader version")
313
+
314
+
315
+ def validate_manifest(m):
316
+ check_compatibility(m)
317
+ if m["dataset_id"] != DATASET_ID:
318
+ raise ValueError("Unexpected dataset")
319
+ for name in ("dataset_version", "chain_id", "baseline_version"):
320
+ identifier(m[name])
321
+ baseline = m["kind"] == "baseline"
322
+ if m["kind"] not in ("baseline", "increment") or type(m["increment_sequence"]) is not int:
323
+ raise ValueError("Invalid release kind/sequence")
324
+ if baseline:
325
+ if (
326
+ m["increment_sequence"] != 0
327
+ or m["parent_version"] is not None
328
+ or m["dataset_version"] != m["baseline_version"]
329
+ ):
330
+ raise ValueError("Invalid baseline identity")
331
+ elif m["increment_sequence"] <= 0 or not m["parent_version"]:
332
+ raise ValueError("Invalid increment identity")
333
+ if set(m["tables"]) != set(TABLES):
334
+ raise ValueError("Unexpected table set")
335
+ paths = set()
336
+ for name, spec in TABLES.items():
337
+ t = m["tables"][name]
338
+ if t["columns"] != spec["columns"] or t["key"] != spec["key"]:
339
+ raise ValueError("Table differs from installed schema")
340
+ for f in t["files"]:
341
+ path = f["path"]
342
+ if not re.fullmatch(r"[a-z_]+/[a-zA-Z0-9_-]+\.parquet", path) or path in paths:
343
+ raise ValueError("Invalid or duplicate data path")
344
+ paths.add(path)
345
+ if f["operation"] not in ("upsert", "delete") or (
346
+ baseline and f["operation"] == "delete"
347
+ ):
348
+ raise ValueError("Invalid table operation")
349
+ for k in ("rows", "bytes"):
350
+ if type(f[k]) is not int or f[k] < 0:
351
+ raise ValueError("Invalid file size/count")
352
+ if not re.fullmatch(r"[a-f0-9]{64}", f["sha256"]):
353
+ raise ValueError("Invalid checksum")
354
+ for key in ("published_at", "input_boundary_at"):
355
+ if datetime.fromisoformat(m[key]).utcoffset() is None:
356
+ raise ValueError("Timestamp requires timezone")
357
+ if not re.fullmatch(r"[a-f0-9]{64}", m["logical_state_sha256"]):
358
+ raise ValueError("Invalid state checksum")
359
+ return m
@@ -0,0 +1 @@
1
+ {"apps_view_columns":{"about_the_game":"VARCHAR","app_type":"VARCHAR","capsule_image":"VARCHAR","capsule_imagev5":"VARCHAR","categories":"JSON","content_descriptors":"JSON","controller_support":"VARCHAR","default_review_series_id":"VARCHAR","detailed_description":"VARCHAR","developers":"VARCHAR[]","extensions":"JSON","first_seen_at":"TIMESTAMPTZ","genres":"JSON","header_image":"VARCHAR","is_free":"BOOLEAN","last_seen_at":"TIMESTAMPTZ","linux_requirements":"JSON","mac_requirements":"JSON","name":"VARCHAR","name_origin":"VARCHAR","pc_requirements":"JSON","platforms":"JSON","positive_percentage":"DOUBLE","price_country":"VARCHAR","price_currency":"VARCHAR","price_discount_percentage":"BIGINT","price_final_minor":"BIGINT","price_initial_minor":"BIGINT","price_observed_at":"TIMESTAMPTZ","publishers":"VARCHAR[]","ratings":"JSON","release_info":"JSON","required_age":"VARCHAR","review_score":"BIGINT","review_score_desc":"VARCHAR","reviews_observed_at":"TIMESTAMPTZ","short_description":"VARCHAR","steam_appid":"BIGINT","steam_url":"VARCHAR","support_info":"JSON","supported_languages":"VARCHAR","tags":"JSON","total_negative":"BIGINT","total_positive":"BIGINT","total_reviews":"BIGINT","website":"VARCHAR"},"canonicalization":"UTF-8 sorted-key compact JSON, UTC six-digit microseconds, table/key ascending; one [table,row] JSON line per row; snapshot_info excluded","protocol_version":1,"query_fields":{"about_the_game":"VARCHAR","acquisition_status":"JSON","app_type":"VARCHAR","capsule_image":"VARCHAR","capsule_imagev5":"VARCHAR","categories":"JSON","content_descriptors":"JSON","controller_support":"VARCHAR","default_review_series_id":"VARCHAR","detailed_description":"VARCHAR","developers":"VARCHAR[]","extensions":"JSON","first_seen_at":"TIMESTAMPTZ","genres":"JSON","header_image":"VARCHAR","is_free":"BOOLEAN","last_seen_at":"TIMESTAMPTZ","linux_requirements":"JSON","mac_requirements":"JSON","name":"VARCHAR","name_origin":"VARCHAR","pc_requirements":"JSON","platforms":"JSON","positive_percentage":"DOUBLE","price_country":"VARCHAR","price_currency":"VARCHAR","price_discount_percentage":"BIGINT","price_final_minor":"BIGINT","price_initial_minor":"BIGINT","price_observed_at":"TIMESTAMPTZ","provenance":"JSON","publishers":"VARCHAR[]","ratings":"JSON","relationships":"JSON","release_info":"JSON","required_age":"VARCHAR","review_score":"BIGINT","review_score_desc":"VARCHAR","reviews_observed_at":"TIMESTAMPTZ","short_description":"VARCHAR","steam_appid":"BIGINT","steam_url":"VARCHAR","support_info":"JSON","supported_languages":"VARCHAR","tags":"JSON","total_negative":"BIGINT","total_positive":"BIGINT","total_reviews":"BIGINT","website":"VARCHAR"},"schema_version":"1.0","snapshot_info_columns":{"app_count":"BIGINT","baseline_version":"VARCHAR","chain_id":"VARCHAR","coverage_json":"JSON","dataset_id":"VARCHAR","dataset_version":"VARCHAR","default_review_series_id":"VARCHAR","feature_support_json":"JSON","freshness_json":"JSON","increment_sequence":"BIGINT","input_boundary_at":"TIMESTAMPTZ","logical_state_sha256":"VARCHAR","metadata_country":"VARCHAR","metadata_language":"VARCHAR","price_country":"VARCHAR","price_language":"VARCHAR","published_at":"TIMESTAMPTZ","schema_version":"VARCHAR","source_release_id":"VARCHAR"},"transport_tables":{"acquisition_status":{"columns":{"context_id":"VARCHAR","context_json":"JSON","data_family":"VARCHAR","last_success_at":"TIMESTAMPTZ","latest_attempt_at":"TIMESTAMPTZ","latest_attempt_status":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","support_status":"VARCHAR"},"key":["steam_appid","source_id","data_family","context_id"]},"app_catalog":{"columns":{"catalog_name":"VARCHAR","first_seen_at":"TIMESTAMPTZ","last_seen_at":"TIMESTAMPTZ","steam_appid":"BIGINT"},"key":["steam_appid"]},"app_categories":{"columns":{"category_id":"VARCHAR","steam_appid":"BIGINT"},"key":["steam_appid","category_id"]},"app_descriptions":{"columns":{"about_the_game":"VARCHAR","detailed_description":"VARCHAR","short_description":"VARCHAR","steam_appid":"BIGINT"},"key":["steam_appid"]},"app_details":{"columns":{"app_type":"VARCHAR","capsule_image":"VARCHAR","capsule_imagev5":"VARCHAR","content_descriptors":"JSON","controller_support":"VARCHAR","extensions":"JSON","header_image":"VARCHAR","is_free":"BOOLEAN","linux_requirements":"JSON","mac_requirements":"JSON","name":"VARCHAR","pc_requirements":"JSON","platforms":"JSON","ratings":"JSON","release_info":"JSON","required_age":"VARCHAR","steam_appid":"BIGINT","support_info":"JSON","supported_languages":"VARCHAR","website":"VARCHAR"},"key":["steam_appid"]},"app_genres":{"columns":{"genre_id":"VARCHAR","steam_appid":"BIGINT"},"key":["steam_appid","genre_id"]},"app_organizations":{"columns":{"identity_quality":"VARCHAR","organization_id":"VARCHAR","original_name":"VARCHAR","role":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT"},"key":["steam_appid","role","organization_id"]},"app_relationships":{"columns":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","relation_type":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","target_appid":"BIGINT"},"key":["steam_appid","relation_type","target_appid"]},"app_search":{"columns":{"developer_keys":"VARCHAR[]","name_key":"VARCHAR","publisher_keys":"VARCHAR[]","steam_appid":"BIGINT"},"key":["steam_appid"]},"app_sets":{"columns":{"categories":"JSON","developers":"VARCHAR[]","genres":"JSON","publishers":"VARCHAR[]","steam_appid":"BIGINT","tags":"JSON"},"key":["steam_appid"]},"app_tags":{"columns":{"source_rank":"BIGINT","source_weight":"DOUBLE","steam_appid":"BIGINT","tag_id":"VARCHAR"},"key":["steam_appid","tag_id"]},"categories":{"columns":{"category_id":"VARCHAR","label":"VARCHAR"},"key":["category_id"]},"field_provenance":{"columns":{"context_id":"VARCHAR","context_json":"JSON","field_name":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","parser_version":"VARCHAR","provenance_id":"VARCHAR","resolution_version":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT","timestamp_quality":"VARCHAR","value_state":"VARCHAR"},"key":["steam_appid","field_name","context_id","provenance_id"]},"genres":{"columns":{"genre_id":"VARCHAR","label":"VARCHAR"},"key":["genre_id"]},"prices":{"columns":{"country":"VARCHAR","currency":"VARCHAR","discount_percentage":"BIGINT","final_minor":"BIGINT","initial_minor":"BIGINT","language":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","source_id":"VARCHAR","steam_appid":"BIGINT"},"key":["steam_appid","country","language","currency"]},"review_series":{"columns":{"definition_json":"JSON","description":"VARCHAR","review_series_id":"VARCHAR"},"key":["review_series_id"]},"review_summaries":{"columns":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","positive_percentage":"DOUBLE","review_score":"BIGINT","review_score_desc":"VARCHAR","review_series_id":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","total_negative":"BIGINT","total_positive":"BIGINT","total_reviews":"BIGINT"},"key":["steam_appid","review_series_id"]},"tags":{"columns":{"label":"VARCHAR","tag_id":"VARCHAR"},"key":["tag_id"]}}}
@@ -0,0 +1 @@
1
+ {"app_count":0,"artifact":{"bytes":0,"data_manifest_sha256":"0000000000000000000000000000000000000000000000000000000000000000","expanded_bytes":0,"sha256":"0000000000000000000000000000000000000000000000000000000000000000","url":"bundle.zip"},"baseline_version":"example-baseline","chain_id":"example-chain","dataset_id":"steam-current","dataset_version":"example-baseline","default_review_series_id":"reviews-example","illustrative_only":true,"increment_sequence":0,"input_boundary_at":"2026-10-21T00:00:00Z","kind":"baseline","logical_state_sha256":"0000000000000000000000000000000000000000000000000000000000000000","minimum_reader_version":"1.0.0.dev1","note":"Shape example; checksums and bundle are placeholders, not a downloadable release.","parent_version":null,"protocol_version":1,"published_at":"2026-10-21T00:00:00Z","schema_version":"1.0","source_release_id":"src_example","tables":{"acquisition_status":{"columns":{"context_id":"VARCHAR","context_json":"JSON","data_family":"VARCHAR","last_success_at":"TIMESTAMPTZ","latest_attempt_at":"TIMESTAMPTZ","latest_attempt_status":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","support_status":"VARCHAR"},"files":[],"key":["steam_appid","source_id","data_family","context_id"],"rows":0},"app_catalog":{"columns":{"catalog_name":"VARCHAR","first_seen_at":"TIMESTAMPTZ","last_seen_at":"TIMESTAMPTZ","steam_appid":"BIGINT"},"files":[],"key":["steam_appid"],"rows":0},"app_categories":{"columns":{"category_id":"VARCHAR","steam_appid":"BIGINT"},"files":[],"key":["steam_appid","category_id"],"rows":0},"app_descriptions":{"columns":{"about_the_game":"VARCHAR","detailed_description":"VARCHAR","short_description":"VARCHAR","steam_appid":"BIGINT"},"files":[],"key":["steam_appid"],"rows":0},"app_details":{"columns":{"app_type":"VARCHAR","capsule_image":"VARCHAR","capsule_imagev5":"VARCHAR","content_descriptors":"JSON","controller_support":"VARCHAR","extensions":"JSON","header_image":"VARCHAR","is_free":"BOOLEAN","linux_requirements":"JSON","mac_requirements":"JSON","name":"VARCHAR","pc_requirements":"JSON","platforms":"JSON","ratings":"JSON","release_info":"JSON","required_age":"VARCHAR","steam_appid":"BIGINT","support_info":"JSON","supported_languages":"VARCHAR","website":"VARCHAR"},"files":[],"key":["steam_appid"],"rows":0},"app_genres":{"columns":{"genre_id":"VARCHAR","steam_appid":"BIGINT"},"files":[],"key":["steam_appid","genre_id"],"rows":0},"app_organizations":{"columns":{"identity_quality":"VARCHAR","organization_id":"VARCHAR","original_name":"VARCHAR","role":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT"},"files":[],"key":["steam_appid","role","organization_id"],"rows":0},"app_relationships":{"columns":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","relation_type":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","target_appid":"BIGINT"},"files":[],"key":["steam_appid","relation_type","target_appid"],"rows":0},"app_search":{"columns":{"developer_keys":"VARCHAR[]","name_key":"VARCHAR","publisher_keys":"VARCHAR[]","steam_appid":"BIGINT"},"files":[],"key":["steam_appid"],"rows":0},"app_sets":{"columns":{"categories":"JSON","developers":"VARCHAR[]","genres":"JSON","publishers":"VARCHAR[]","steam_appid":"BIGINT","tags":"JSON"},"files":[],"key":["steam_appid"],"rows":0},"app_tags":{"columns":{"source_rank":"BIGINT","source_weight":"DOUBLE","steam_appid":"BIGINT","tag_id":"VARCHAR"},"files":[],"key":["steam_appid","tag_id"],"rows":0},"categories":{"columns":{"category_id":"VARCHAR","label":"VARCHAR"},"files":[],"key":["category_id"],"rows":0},"field_provenance":{"columns":{"context_id":"VARCHAR","context_json":"JSON","field_name":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","parser_version":"VARCHAR","provenance_id":"VARCHAR","resolution_version":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT","timestamp_quality":"VARCHAR","value_state":"VARCHAR"},"files":[],"key":["steam_appid","field_name","context_id","provenance_id"],"rows":0},"genres":{"columns":{"genre_id":"VARCHAR","label":"VARCHAR"},"files":[],"key":["genre_id"],"rows":0},"prices":{"columns":{"country":"VARCHAR","currency":"VARCHAR","discount_percentage":"BIGINT","final_minor":"BIGINT","initial_minor":"BIGINT","language":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","source_id":"VARCHAR","steam_appid":"BIGINT"},"files":[],"key":["steam_appid","country","language","currency"],"rows":0},"review_series":{"columns":{"definition_json":"JSON","description":"VARCHAR","review_series_id":"VARCHAR"},"files":[],"key":["review_series_id"],"rows":0},"review_summaries":{"columns":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","positive_percentage":"DOUBLE","review_score":"BIGINT","review_score_desc":"VARCHAR","review_series_id":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","total_negative":"BIGINT","total_positive":"BIGINT","total_reviews":"BIGINT"},"files":[],"key":["steam_appid","review_series_id"],"rows":0},"tags":{"columns":{"label":"VARCHAR","tag_id":"VARCHAR"},"files":[],"key":["tag_id"],"rows":0}}}
@@ -0,0 +1 @@
1
+ {"$schema":"https://json-schema.org/draft/2020-12/schema","description":"Structural schema; validate_manifest additionally enforces cross-field identity, paths, checksums and increment semantics.","properties":{"app_count":{"minimum":0,"type":"integer"},"artifact":{"properties":{"bytes":{"minimum":0,"type":"integer"},"data_manifest_sha256":{"pattern":"^[a-f0-9]{64}$","type":"string"},"expanded_bytes":{"minimum":0,"type":"integer"},"sha256":{"pattern":"^[a-f0-9]{64}$","type":"string"},"url":{"type":"string"}},"required":["url","sha256","bytes","expanded_bytes","data_manifest_sha256"],"type":"object"},"baseline_version":{"minLength":1,"type":"string"},"chain_id":{"minLength":1,"type":"string"},"dataset_id":{"const":"steam-current"},"dataset_version":{"minLength":1,"type":"string"},"default_review_series_id":{"minLength":1,"type":"string"},"increment_sequence":{"minimum":0,"type":"integer"},"input_boundary_at":{"format":"date-time","type":"string"},"kind":{"enum":["baseline","increment"]},"logical_state_sha256":{"pattern":"^[a-f0-9]{64}$","type":"string"},"minimum_reader_version":{"type":"string"},"parent_version":{"type":["string","null"]},"protocol_version":{"const":1},"published_at":{"format":"date-time","type":"string"},"schema_version":{"const":"1.0"},"source_release_id":{"minLength":1,"type":"string"},"tables":{"additionalProperties":false,"properties":{"acquisition_status":{"properties":{"columns":{"const":{"context_id":"VARCHAR","context_json":"JSON","data_family":"VARCHAR","last_success_at":"TIMESTAMPTZ","latest_attempt_at":"TIMESTAMPTZ","latest_attempt_status":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","support_status":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["steam_appid","source_id","data_family","context_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_catalog":{"properties":{"columns":{"const":{"catalog_name":"VARCHAR","first_seen_at":"TIMESTAMPTZ","last_seen_at":"TIMESTAMPTZ","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_categories":{"properties":{"columns":{"const":{"category_id":"VARCHAR","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","category_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_descriptions":{"properties":{"columns":{"const":{"about_the_game":"VARCHAR","detailed_description":"VARCHAR","short_description":"VARCHAR","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_details":{"properties":{"columns":{"const":{"app_type":"VARCHAR","capsule_image":"VARCHAR","capsule_imagev5":"VARCHAR","content_descriptors":"JSON","controller_support":"VARCHAR","extensions":"JSON","header_image":"VARCHAR","is_free":"BOOLEAN","linux_requirements":"JSON","mac_requirements":"JSON","name":"VARCHAR","pc_requirements":"JSON","platforms":"JSON","ratings":"JSON","release_info":"JSON","required_age":"VARCHAR","steam_appid":"BIGINT","support_info":"JSON","supported_languages":"VARCHAR","website":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["steam_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_genres":{"properties":{"columns":{"const":{"genre_id":"VARCHAR","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","genre_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_organizations":{"properties":{"columns":{"const":{"identity_quality":"VARCHAR","organization_id":"VARCHAR","original_name":"VARCHAR","role":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","role","organization_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_relationships":{"properties":{"columns":{"const":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","relation_type":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","target_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","relation_type","target_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_search":{"properties":{"columns":{"const":{"developer_keys":"VARCHAR[]","name_key":"VARCHAR","publisher_keys":"VARCHAR[]","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_sets":{"properties":{"columns":{"const":{"categories":"JSON","developers":"VARCHAR[]","genres":"JSON","publishers":"VARCHAR[]","steam_appid":"BIGINT","tags":"JSON"}},"files":{"type":"array"},"key":{"const":["steam_appid"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"app_tags":{"properties":{"columns":{"const":{"source_rank":"BIGINT","source_weight":"DOUBLE","steam_appid":"BIGINT","tag_id":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["steam_appid","tag_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"categories":{"properties":{"columns":{"const":{"category_id":"VARCHAR","label":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["category_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"field_provenance":{"properties":{"columns":{"const":{"context_id":"VARCHAR","context_json":"JSON","field_name":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","parser_version":"VARCHAR","provenance_id":"VARCHAR","resolution_version":"VARCHAR","source_id":"VARCHAR","source_url":"VARCHAR","steam_appid":"BIGINT","timestamp_quality":"VARCHAR","value_state":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["steam_appid","field_name","context_id","provenance_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"genres":{"properties":{"columns":{"const":{"genre_id":"VARCHAR","label":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["genre_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"prices":{"properties":{"columns":{"const":{"country":"VARCHAR","currency":"VARCHAR","discount_percentage":"BIGINT","final_minor":"BIGINT","initial_minor":"BIGINT","language":"VARCHAR","observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","source_id":"VARCHAR","steam_appid":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","country","language","currency"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"review_series":{"properties":{"columns":{"const":{"definition_json":"JSON","description":"VARCHAR","review_series_id":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["review_series_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"review_summaries":{"properties":{"columns":{"const":{"observation_id":"VARCHAR","observed_at":"TIMESTAMPTZ","positive_percentage":"DOUBLE","review_score":"BIGINT","review_score_desc":"VARCHAR","review_series_id":"VARCHAR","source_id":"VARCHAR","steam_appid":"BIGINT","total_negative":"BIGINT","total_positive":"BIGINT","total_reviews":"BIGINT"}},"files":{"type":"array"},"key":{"const":["steam_appid","review_series_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"},"tags":{"properties":{"columns":{"const":{"label":"VARCHAR","tag_id":"VARCHAR"}},"files":{"type":"array"},"key":{"const":["tag_id"]},"rows":{"minimum":0,"type":"integer"}},"required":["columns","key","rows","files"],"type":"object"}},"required":["app_search","app_catalog","app_details","app_descriptions","app_sets","review_summaries","review_series","prices","app_organizations","app_relationships","field_provenance","acquisition_status","genres","app_genres","categories","app_categories","tags","app_tags"],"type":"object"}},"required":["dataset_id","protocol_version","schema_version","minimum_reader_version","kind","tables","app_count","increment_sequence","logical_state_sha256","parent_version","artifact","dataset_version","chain_id","baseline_version","source_release_id","default_review_series_id","published_at","input_boundary_at"],"title":"Steam current snapshot manifest","type":"object"}