48 lines
3.0 KiB
Markdown
48 lines
3.0 KiB
Markdown
# Schemas
|
|
|
|
JSON Schemas (draft 2020-12) for every file and record the formats define.
|
|
Each schema's `$id` is `https://scient.ing/ns/schemas/<file>`, and schemas refer to each other by those names, so a validator that loads the whole folder resolves every reference.
|
|
|
|
## Which schema for which file
|
|
|
|
| Topic | Schemas |
|
|
| --- | --- |
|
|
| Shared definitions | `common.schema.json`: hashes, IDs, keys, addresses, times, decimals, boxes, licenses, signatures, evidence, quotes. |
|
|
| A package | `manifest.schema.json`, `document.schema.json`, `node.schema.json`, `runs.schema.json`, `witnesses.schema.json`, `provenance.schema.json`, `page.schema.json`, `location.schema.json`, `reference.schema.json`, `id-entry.schema.json`, `correction.schema.json`, `receipt.schema.json`, `revocation.schema.json`, `roster.schema.json`, `suspect.schema.json`, `mathml.schema.json` |
|
|
| Pointing into documents | `anchor.schema.json` |
|
|
| Rights | `rights.schema.json`, `policy.schema.json`, `stages.schema.json`, `backend.schema.json`, `profile.schema.json`, `stamps.schema.json` |
|
|
| Review | `qa-report.schema.json` |
|
|
| Annotation and teaching | `layer.schema.json`, `annotation.schema.json`, `exercise.schema.json`, `submission.schema.json`, `grade.schema.json` |
|
|
| Data | `dataset.schema.json`, `value-anchor.schema.json`, `digitization.schema.json`, `view.schema.json` |
|
|
| Teams and drafts | `project.schema.json`, `snapshot.schema.json`, `draft-ids.schema.json` |
|
|
|
|
A record that travels on its own carries a `format` such as `scienting-anchor/1`; [registry/formats.json](../registry/formats.json) maps each format to its schema.
|
|
|
|
## Validating
|
|
|
|
With the `jsonschema` package (4.18 or later):
|
|
|
|
```python
|
|
import json, pathlib
|
|
from jsonschema import Draft202012Validator
|
|
from referencing import Registry, Resource
|
|
|
|
schemas = {p.name: json.loads(p.read_text()) for p in pathlib.Path("schemas").glob("*.json")}
|
|
registry = Registry().with_resources((s["$id"], Resource.from_contents(s)) for s in schemas.values())
|
|
validator = Draft202012Validator(schemas["anchor.schema.json"], registry=registry)
|
|
validator.validate(json.load(open("fixtures/records/anchor-span.json")))
|
|
```
|
|
|
|
Any draft 2020-12 validator works the same way; `python3 tools/check.py` validates every fixture with the repository's own validator and, when installed, with `jsonschema` too.
|
|
|
|
## What a schema does not check
|
|
|
|
A schema checks shape: required properties, types, patterns, enumerations.
|
|
It cannot check that a hash recomputes, that a node's children are allowed, that a correction's ID derives from its content, or that a receipt's signature verifies.
|
|
Those are the rules of [spec/22-conformance.md](../spec/22-conformance.md), each with an ID in [registry/rules.json](../registry/rules.json).
|
|
|
|
## Writing schemas
|
|
|
|
The schemas use only the keywords listed in [spec/22-conformance.md](../spec/22-conformance.md#223-schemas), and their patterns avoid `\d`, `\w`, `\s`, `\b` and lookbehind, so that validators in every language read them alike.
|
|
Optional properties are omitted rather than set to null, except where a schema says a property is nullable.
|