diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e189f..2d62a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,55 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the specification adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.0] - 2026-07-21 + +### Added + +- The registered `deposit` extension: write access through deposit sessions + against storage objects — an RO-Crate plus all the files it references, + deposited and stored as a unit, from which the implementation materialises + catalog entities by its own rules. The storage object is the sole write + pathway; entities remain read-only projections. +- Deposit session endpoints: `POST /deposits` creates a deposit for a new + storage object (client-proposed or server-minted ID per the `idMinting` + capability) and `POST /storage-object/{id}/deposits` opens an update + deposit; staging via `PUT /deposit/{id}/crate` (full replace) and + `PUT /deposit/{id}/file/{fileId}` (inline bytes or presigned upload, + discriminated by Content-Type), in any order; `POST /deposit/{id}/finalise` + validates and publishes atomically, synchronously (200) or asynchronously + (202 with polling via `GET /deposit/{id}`); `DELETE /deposit/{id}` aborts. + A failed finalise returns the deposit to `open` with the violations + recorded — staged content is never lost to a metadata typo. +- Update deposits use crate-as-manifest carry-forward: stage a new crate plus + only the changed files; unchanged files carry forward from the baseline by + `@id`, and files absent from the new crate drop out. The baseline is pinned + at deposit creation and each finalise replaces the storage object + wholesale, so the last finalise wins as a unit. +- The storage-object read surface: `GET /storage-objects` (minimal list), + `GET /storage-object/{id}` (lean body — `id`, `entityIds`, timestamps, + `access`) and `GET /storage-object/{id}/crate` (the deposited crate, + verbatim, with a HEAD twin). Bidirectional linkage between the catalog and + storage objects: a plural `storageObjectIds` on entities, a singular + `storageObjectId` on files, and `entityIds` on the storage object. +- Deletion: `DELETE /storage-object/{id}` with no spec-mandated + preconditions (implementations MAY refuse with a 409 and a reason), and a + constrained `DELETE /entity/{id}` valid only for entities no storage + object contributes to. Deleted URIs follow a single per-implementation + tombstone policy — `410` with a new `Tombstone` schema, or plain `404` — + declared in `/capabilities` and covering entities alike. +- A `DepositCapability` block in `/capabilities` declaring `idMinting`, + `fileUpload` and `tombstonePolicy` (required), plus optional + `depositTtlSeconds` and `maxFileSizeBytes`. Write operations require the + new coarse OAuth2 `write` scope. + +### Changed + +- `GET /entity/{id}/rocrate` is now specified as implementation-defined in + provenance: the document may be stored or derived from the entity's + contributing storage objects, but must always be a valid RO-Crate whose + root data entity describes the entity. An original deposited crate is + retrieved verbatim from `GET /storage-object/{id}/crate`. + ## [0.2.0] - 2026-07-20 ### Added diff --git a/blog/2026-07-21-deposit-extension.md b/blog/2026-07-21-deposit-extension.md new file mode 100644 index 0000000..bf19fb2 --- /dev/null +++ b/blog/2026-07-21-deposit-extension.md @@ -0,0 +1,104 @@ +--- +slug: deposit-extension +title: "The deposit extension: write access via storage objects" +authors: [johnf] +tags: [paradisec, ldaca] +--- + +Version 0.3.0 of the RO-Crate API specification registers the `deposit` +extension — the first write pathway in an otherwise read-only API. Writes flow +through deposit sessions against storage objects: an RO-Crate plus all the +files it references, deposited and stored as a unit, from which the +implementation materialises catalog entities by its own rules. + +{/* truncate */} + +## Why storage objects, not entity writes + +A single RO-Crate routinely describes many catalog entities — a collection, +its items, every file they contain, and the people and organisations +connected to them; the entity model is extensible, so the list doesn't end +there. Entity-granular +write endpoints would force depositors to decompose a crate they already hold +into a sequence of per-entity calls, and force the API to referee partial +failures across that sequence. + +The unit a depositor actually holds is the crate plus its files, so that is +the unit of deposit. Depositors send storage objects; the implementation +materialises entities from them, and entities remain read-only projections. +How materialisation works is implementation-defined — PARADISEC turns one +item crate into an item entity plus a file entity per media file, while LDaCA +may explode a whole corpus crate into collection, item, file, person, and +organisation entities from a single deposit. + +## The deposit session + +A deposit is a staging area with an atomic publish at the end: + +1. **Create** — `POST /deposits` opens a deposit for a new storage object + (client-proposed or server-minted ID, per the declared `idMinting` mode); + `POST /storage-object/{id}/deposits` opens an update deposit against an + existing one. +2. **Stage** — `PUT /deposit/{id}/crate` stages the RO-Crate (full replace) + and `PUT /deposit/{id}/file/{fileId}` stages files, either inline or via a + presigned upload target, in any order. +3. **Finalise** — `POST /deposit/{id}/finalise` validates and publishes + atomically, synchronously (200) or asynchronously (202 with polling via + `GET /deposit/{id}`). A failed finalise returns the deposit to `open` with + the violations recorded — staged content is never lost to a metadata typo. + +`DELETE /deposit/{id}` aborts an open deposit. + +Updates use crate-as-manifest carry-forward: stage a new crate plus only the +changed files. Unchanged files carry forward from the pinned baseline by +`@id`, files absent from the new crate drop out, and each finalise replaces +the storage object wholesale — the last finalise wins as a unit. + +## The read surface and linkage + +Deposited storage objects are readable: `GET /storage-objects` lists them, +`GET /storage-object/{id}` returns a lean body, and +`GET /storage-object/{id}/crate` returns the deposited crate verbatim. The +two surfaces are bidirectionally linked — `entityIds` on the storage object +answers "what did my deposit create", while `storageObjectIds` on entities +and `storageObjectId` on files point back at the source of truth. + +Deletion is `DELETE /storage-object/{id}`, plus a narrow +`DELETE /entity/{id}` valid only for entities no storage object contributes +to. Deleted URIs follow a single per-implementation tombstone policy — +`410` with a `Tombstone` body, or plain `404`. + +## Discovering write support + +Presence of the `deposit` key in `/capabilities` is how clients discover +write support — there is no separate write flag: + +```json +{ + "apiVersion": "0.3.0", + "extensions": { + "deposit": { + "idMinting": "both", + "fileUpload": ["inline", "presigned"], + "tombstonePolicy": "410", + "depositTtlSeconds": 604800, + "maxFileSizeBytes": 5368709120 + } + } +} +``` + +Clients read the declared modes rather than probing, and write operations +require the new coarse OAuth2 `write` scope; finer-grained authorisation is +implementation-defined. + +## Where to go next + +- The [deposit extension guide](/docs/extensions/deposit) covers the model in + depth, with walkthroughs of [depositing](/docs/extensions/deposit/depositing), + [updating](/docs/extensions/deposit/updating), and + [deletion & lifecycle](/docs/extensions/deposit/lifecycle). +- The [API reference](/docs/api) documents the deposit and storage-object + endpoints and schemas. +- The [changelog](https://github.com/Language-Research-Technology/ro-crate-api/blob/main/CHANGELOG.md) + records the full 0.3.0 change set. diff --git a/docs/extensions/deposit/depositing.md b/docs/extensions/deposit/depositing.md new file mode 100644 index 0000000..2c1c9b3 --- /dev/null +++ b/docs/extensions/deposit/depositing.md @@ -0,0 +1,239 @@ +--- +title: Depositing +mdx.format: md +--- + +# Depositing + +A deposit is a session: open it, stage an RO-Crate and files, finalise. The +storage object comes into existence only at the first successful finalise — +until then nothing is readable and no entities exist. This page walks the +whole flow for a new storage object; [updating an existing +one](./updating) uses the same staging surface with a different entry point. + +The deposit's lifecycle: + +```mermaid +stateDiagram-v2 + direction LR + [*] --> open + open --> finalising: finalise + finalising --> open: validation fails + finalising --> complete: success + open --> aborted: abort / expiry + complete --> [*] + aborted --> [*] +``` + +Deposits are single-use: once `complete`, further changes open a new deposit. + +## 1. Check the Capability + +Read [`/capabilities`](/docs/getting-started/capabilities) and confirm +`"deposit" in capabilities.extensions`. Note the declared `idMinting` mode +and `fileUpload` modes — they decide the shape of the calls below. All +deposit calls require the `write` scope. + +## 2. Create the Deposit + +```http +POST /deposits +Content-Type: application/json + +{ "storageObjectId": "https://catalog.paradisec.org.au/repository/NT1/001" } +``` + +The `storageObjectId` in the body is a proposal, allowed when `idMinting` is +`client` or `both`. Omit the body (or the field) and the server mints an ID +(`server` or `both`). Proposing an ID the declared mode does not support is +rejected with `422`; proposing one that already exists is rejected with +`409` — which also catches the typo'd-ID footgun of aiming a fresh deposit +at an ID you meant to [update](./updating). + +```json +{ + "depositId": "dep_8f14e45f", + "storageObjectId": "https://catalog.paradisec.org.au/repository/NT1/001", + "state": "open" +} +``` + +The response (`201`, with a `Location` header for the deposit) returns the +storage-object ID immediately, so you can reference it from the crate you are +about to stage. Whether the crate MUST reference it is implementation-defined +and enforced at finalise. + +## 3. Stage the Crate + +```http +PUT /deposit/dep_8f14e45f/crate +Content-Type: application/ld+json + +{ "@context": "https://w3id.org/ro/crate/1.2/context", "@graph": [ ... ] } +``` + +Staging the crate is a **full replace** — staging again discards the earlier +crate; there is no crate PATCH and no crate DELETE. Crate and files may be +staged in **any order**; the crate–file association is only checked at +finalise. + +At finalise the staged crate becomes the storage object's authoritative file +manifest: every file the new version holds is a file entity in this crate. + +## 4. Stage the Files + +Files are staged at `PUT /deposit/{id}/file/{fileId}`, where `{fileId}` is +the file entity's `@id` in the crate, percent-encoded — for attached files, +its crate-relative path. Two modes share the endpoint, discriminated by the +request `Content-Type`; use the ones the implementation declares in +`fileUpload`. Only transport metadata travels here — descriptive metadata +about the file lives in the crate. + +### Inline mode + +The request body is the file's bytes, sent with the file's own media type: + +```http +PUT /deposit/dep_8f14e45f/file/NT1-001-001A.wav +Content-Type: audio/x-wav + + +``` + +Responds `204`. Suited to modest files and simple clients. + +### Presigned mode + +The request body is JSON transport metadata, and the response is an upload +target the client sends the bytes to directly — typically a presigned +object-store URL: + +```http +PUT /deposit/dep_8f14e45f/file/NT1-001-001A.wav +Content-Type: application/json + +{ + "size": 2048576, + "checksum": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", + "mediaType": "audio/x-wav" +} +``` + +Responds `200` with the upload target: + +```json +{ + "uploadUrl": "https://uploads.example.org/deposit/dep_8f14e45f/NT1-001-001A.wav?signature=...", + "method": "PUT", + "headers": { "Content-Type": "audio/x-wav" }, + "expiresAt": "2026-07-22T10:00:00Z" +} +``` + +Upload the bytes to `uploadUrl` with the given method and headers before +`expiresAt` (re-stage the file to obtain a fresh target). There is **no +per-file completion call**: finalise verifies that the bytes landed and +match the declared size and checksum. A missing or mismatched upload is a +validation violation at finalise — re-upload just that file and finalise +again. + +### Housekeeping + +- Staging the same `{fileId}` again replaces the earlier staging, in either + mode. +- `DELETE /deposit/{id}/file/{fileId}` removes a staged file while the + deposit is `open`. +- `GET /deposit/{id}` lists the staged files with per-file status — + `pending` (presigned, bytes not yet observed) or `received`. Status MAY be + updated eagerly or lazily; finalise remains the authoritative + verification point. +- Files exceeding a declared `maxFileSizeBytes` are rejected with `413`. + +## 5. Finalise + +```http +POST /deposit/dep_8f14e45f/finalise +``` + +Finalise validates the staged content, publishes it as the storage object's +new current version, and materialises catalog entities from it. Validation +depth and materialisation rules are implementation-defined. + +The server MAY complete synchronously or asynchronously, **at its own +discretion per request** — there is no capability flag, and one client code +path handles both: + +- **`200`**: the deposit is returned in state `complete`. Done. +- **`202`**: the deposit is returned in state `finalising`. Poll + `GET /deposit/{id}` until the state leaves `finalising`. + +``` +finalise → state? + complete → done + finalising → poll GET /deposit/{id} until the state changes + open → a failure was recorded in `errors`; fix and retry +``` + +The finalise response is always the thin deposit representation. On +`complete` it carries the `storageObjectId`; the materialised-entity list +lives on the storage object itself, because later deposits can change it. + +### When finalise fails + +**Failure atomicity is guaranteed**: a finalise that does not reach +`complete` leaves no observable change — the storage object stays at its +prior version (or, for a create deposit, does not come into existence) and +no entities are touched. Retry is always safe. + +- **Validation failure** returns the deposit to `open` with the violations + recorded — as a `422` body on the synchronous path, and in the deposit's + `errors` field (readable via `GET /deposit/{id}`) on the asynchronous + path. Same violations shape either way. Staged content is intact: a + metadata typo never forces re-uploading media — fix the crate, re-stage + it, finalise again. `errors` is cleared when the next finalise is + accepted. +- **Non-validation failure** (materialisation crash, backend outage, or the + target storage object having been [deleted + mid-deposit](./lifecycle#open-deposits-when-the-object-is-deleted)) also + returns the deposit to `open` with the failure recorded; the synchronous + path gets a `5xx`. There is no terminal `failed` state — retry, or abort + to walk away. + +Once `complete`, the new crate and all materialised entities are readable. +Readers are not guaranteed to observe the transition as a single atomic +flip; implementations should minimise the window (for example by flipping +the crate pointer last). + +## 6. See What Was Materialised + +```http +GET /storage-object/https%3A%2F%2Fcatalog.paradisec.org.au%2Frepository%2FNT1%2F001 +``` + +```json +{ + "id": "https://catalog.paradisec.org.au/repository/NT1/001", + "entityIds": [ + "https://catalog.paradisec.org.au/repository/NT1/001", + "https://catalog.paradisec.org.au/repository/NT1/001/NT1-001-001A.wav" + ], + "createdAt": "2026-07-21T04:12:00Z", + "lastDepositedAt": "2026-07-21T04:12:00Z", + "access": { "metadata": true, "content": true } +} +``` + +`entityIds` is the authoritative "what did my deposit create". The deposited +crate — [`GET /storage-object/{id}/crate`](/docs/api/get-storage-object-crate) — +is the single source of truth for the object's content inventory; the +storage object carries no file list of its own. + +## Abort and Expiry + +`DELETE /deposit/{id}` aborts an `open` deposit, discarding its staged crate +and files. Aborting is terminal; the storage object is left at its prior +version, or never comes into existence for a create deposit. + +Abandoned deposits are subject to implementation-defined expiry — an expired +deposit behaves as aborted, and subsequent access MAY return `404`. Where +the implementation declares `depositTtlSeconds`, that is the expiry horizon. diff --git a/docs/extensions/deposit/index.md b/docs/extensions/deposit/index.md new file mode 100644 index 0000000..cea07c4 --- /dev/null +++ b/docs/extensions/deposit/index.md @@ -0,0 +1,210 @@ +--- +title: "Extension: deposit" +mdx.format: md +--- + +# The `deposit` Extension + +The core specification is read-only: entities, crates, files, and search. The +`deposit` extension adds the write pathway. It is deliberately not +entity-level CRUD — all writes flow through **deposit sessions** against +**storage objects**, and catalog entities remain read-only projections that +the implementation derives from what was deposited. + +The extension covers three things as one unit: + +- the **deposit session** endpoints — open a deposit, stage an RO-Crate and + files, finalise +- the **storage-object read surface** — list, retrieve, and delete storage + objects, and fetch a deposited crate verbatim +- the **linkage fields** added to core schemas (`storageObjectIds` on + [Entity](/docs/api/schemas/entity), `storageObjectId` on + [File](/docs/api/schemas/file)) + +The read surface is not separable from the write pathway: readable storage +objects without a deposit pathway is not a state this specification supports. + +## Why Storage Objects, Not Entity Writes + +A single RO-Crate routinely describes many catalog entities — a collection, +its items, every file they contain, and the people and organisations +connected to them; the entity model is extensible, so the list doesn't end +there. Entity-granular +write endpoints would force depositors to decompose a crate they already have +into a sequence of per-entity calls, and force the API to referee partial +failures across that sequence. + +The unit a depositor actually holds is the crate plus its files. The +extension makes that the unit of deposit: + +> A **storage object** is the real thing on disk — an RO-Crate plus all the +> files it references, deposited and stored as a unit. + +Depositors send storage objects; the implementation **materialises** catalog +entities from them by its own rules. There are no entity write endpoints +(with one narrow exception for +[orphaned entities](./lifecycle#deleting-a-contributor-less-entity)). + +## Materialisation + +How a storage object becomes catalog entities is **implementation-defined**. +The contract is only that once a deposit reports `complete`, the entities +materialised from it are readable, and the linkage fields below let clients +traverse between the two surfaces. Two real archives illustrate how much the +rules can differ: + +- **PARADISEC**: a storage object is one item's crate and its media files. + Materialisation yields the item entity plus one file entity per media + file — a small, fixed shape. +- **LDaCA**: a storage object may be a whole corpus crate. Materialisation + explodes it into collection, item, file, person, and organisation + entities — one deposit, many entities. + +Materialisation can also be **many-to-one**: several storage objects may +contribute to a single merged entity. If two deposited crates both describe +the same speaker (same `@id`), an implementation may materialise one Person +entity carrying both storage objects in its `storageObjectIds`. This merge +machinery is also what makes +[curation storage objects](./lifecycle#enriching-entities-curation-storage-objects) +work. + +Because entities are projections, re-materialisation can change them. A later +deposit — of the same storage object or a different one — may add, alter, or +remove entities. Whether entities that lose their last contributor are pruned +or retained is likewise implementation-defined (see +[Deletion & Lifecycle](./lifecycle)). + +## The Linkage Fields + +The two surfaces — deposited storage objects and materialised entities — are +bidirectionally linked: + +- **`entityIds`** on a [storage object](/docs/api/schemas/storageobject): the + entities materialised from its current version. This is the authoritative + answer to "what did my deposit create", and it can change as later deposits + alter the materialisation. +- **`storageObjectIds`** on an [Entity](/docs/api/schemas/entity): the + storage objects whose current versions contribute to the entity. Usually + one; more when materialisation merges contributions. +- **`storageObjectId`** on a [File](/docs/api/schemas/file): the storage + object whose deposit supplied the file's bytes. Singular, because bytes + arrive in exactly one deposit. Optional, to accommodate files predating any + storage object. + +With the extension present, `GET /entity/{id}/rocrate` is specified as +implementation-defined in provenance: the document may be a stored crate or a +view derived from the crate(s) of the entity's contributing storage objects, +but it MUST always be a valid RO-Crate whose root data entity describes the +entity. To retrieve an original deposited crate verbatim, use +[`GET /storage-object/{id}/crate`](/docs/api/get-storage-object-crate). + +## Declaring the Capability + +An implementation that provides deposit declares the extension in +[`/capabilities`](/docs/getting-started/capabilities). Presence of the +`deposit` key is how clients discover write support — there is no separate +write flag: + +```json +{ + "apiVersion": "0.3.0", + "extensions": { + "deposit": { + "idMinting": "both", + "fileUpload": ["inline", "presigned"], + "tombstonePolicy": "410", + "depositTtlSeconds": 604800, + "maxFileSizeBytes": 5368709120 + } + } +} +``` + +- **`idMinting`** (required): who mints storage-object IDs — `client` + (depositor proposes), `server` (implementation mints), or `both` (client + may propose, server fills gaps). +- **`fileUpload`** (required): the staging modes supported, a set drawn from + `inline` (bytes in the staging request) and `presigned` (metadata in the + staging request, bytes uploaded directly to a returned target). Future + modes may be added; clients ignore values they do not recognise. +- **`tombstonePolicy`** (required): `"410"` or `"404"` — what deleted + resource URIs return. One policy covers storage objects and the entity + knock-on alike; see [Deletion & Lifecycle](./lifecycle#tombstones). +- **`depositTtlSeconds`** (optional): the expiry horizon for abandoned + deposits. Absent means expiry is implementation-defined — don't rely on a + particular window. +- **`maxFileSizeBytes`** (optional): the largest file a deposit may stage. + Absent means no declared limit. + +Deliberately *not* declared: whether finalise runs synchronously or +asynchronously (server's discretion per request — one client code path +handles both), and the storage-object visibility pattern (observable through +behaviour; clients don't branch on it before acting). + +### Authentication + +Deposit and storage-object write operations require the coarse OAuth2 +`write` scope (see [Authentication](/docs/getting-started/authentication)). +Finer-grained authorisation — who may deposit what — is +implementation-defined and expressed through ordinary `403` responses. + +## Storage-Object Visibility + +Whether storage objects are readable beyond their depositor is +**implementation-defined**. Implementations should choose one of two named +patterns and apply it consistently: + +- **Public surface**: storage objects are listable and retrievable by + anyone; each carries an entity-style `access` object saying whether the + caller may fetch the crate. Recommended derivation: grant crate access + only if the caller has metadata access to *every* entity materialised from + the object, since the deposited crate is the union of their metadata. + *Pros*: provenance is publicly traversable (any reader can follow + `storageObjectIds` to the source of truth); citations to deposited crates + resolve for everyone. *Cons*: access derivation must be computed and kept + consistent with entity-level access; the surface must be hardened like any + public catalog surface. +- **Depositor-only surface**: storage-object reads require the `write` + scope — a management surface for depositors and curators, not a catalog + surface. *Pros*: simple to reason about; no access derivation. *Cons*: + provenance links are dead ends for ordinary readers; the deposited crate + is not citable as a public artefact. + +Either way the storage-object resource carries the `access` object, so +client code is identical under both patterns. + +## The Endpoints + +| Operation | Purpose | +| --- | --- | +| [`POST /deposits`](/docs/api/create-deposit) | Open a deposit for a new storage object | +| [`POST /storage-object/{id}/deposits`](/docs/api/create-update-deposit) | Open an update deposit for an existing storage object | +| [`GET /deposit/{id}`](/docs/api/get-deposit) | Deposit state, staged files, recorded errors; the polling resource | +| [`PUT /deposit/{id}/crate`](/docs/api/stage-deposit-crate) | Stage the RO-Crate (full replace) | +| [`PUT /deposit/{id}/file/{fileId}`](/docs/api/stage-deposit-file) | Stage a file (inline or presigned) | +| [`DELETE /deposit/{id}/file/{fileId}`](/docs/api/unstage-deposit-file) | Remove a staged file | +| [`POST /deposit/{id}/finalise`](/docs/api/finalise-deposit) | Validate, publish, materialise | +| [`DELETE /deposit/{id}`](/docs/api/abort-deposit) | Abort an open deposit | +| [`GET /storage-objects`](/docs/api/list-storage-objects) | List storage objects | +| [`GET /storage-object/{id}`](/docs/api/get-storage-object) | Retrieve a storage object | +| [`GET /storage-object/{id}/crate`](/docs/api/get-storage-object-crate) | The deposited crate, verbatim | +| [`DELETE /storage-object/{id}`](/docs/api/delete-storage-object) | Delete a storage object | +| [`DELETE /entity/{id}`](/docs/api/delete-entity) | Delete a contributor-less entity | + +The guides walk through the flows: + +- [Depositing](./depositing) — create → stage → finalise, both upload modes +- [Updating a Storage Object](./updating) — the carry-forward delta model +- [Deletion & Lifecycle](./lifecycle) — deleting, tombstones, enrichment + +## Client Rules + +- **Feature-detect before use**: check `"deposit" in + capabilities.extensions` and read the declared modes rather than probing. +- **One code path for finalise**: branch on the deposit's returned `state`, + not on an expectation of sync or async behaviour. +- **Treat `entityIds` as live**: the materialised-entity list reflects the + *current* materialisation and can change as other deposits land. +- **Degrade gracefully**: the linkage fields are extension properties; + absent means the implementation (or that resource) doesn't carry them, + not that the resource is invalid. diff --git a/docs/extensions/deposit/lifecycle.md b/docs/extensions/deposit/lifecycle.md new file mode 100644 index 0000000..c055307 --- /dev/null +++ b/docs/extensions/deposit/lifecycle.md @@ -0,0 +1,139 @@ +--- +title: Deletion & Lifecycle +mdx.format: md +--- + +# Deletion & Lifecycle + +Storage objects are deleted directly; what happens to the entities +materialised from them is the implementation's call. This page covers the +delete operation, tombstones, the entity knock-on, and the two patterns that +replace entity-level writes: curation storage objects for enrichment, and +the one constrained entity delete. + +## Deleting a Storage Object + +```http +DELETE /storage-object/https%3A%2F%2Fcatalog.paradisec.org.au%2Frepository%2FNT1%2F001 +``` + +Deletion is not a deposit session — there is nothing to stage and the +operation is already atomic. It removes the storage object's crate and +files. Implementations needing slow teardown MAY return `202 Accepted`. + +The specification mandates **no preconditions**. An implementation MAY +refuse a delete with `409` and a reason body per its own policy — curatorial +holds, cross-references, retention rules — but none is required. + +## The Entity Knock-On + +What deletion does to the entities materialised from the object is +**implementation-defined**, with the same latitude as re-deposit pruning: + +- An entity whose `storageObjectIds` still lists another contributor + survives — deleting one contributor just removes it from the list. The + merged-entity case needs no special protection; it is the same machinery + as any re-materialisation. +- An entity left with no contributors MAY be pruned — or deliberately + retained. Retention is legitimate: an archive may keep an Organisation + entity alive after its last contributing storage object is deleted. + +Entity URIs have no independent deletion semantics: entities disappear (or +not) per the implementation's lifecycle rules, and when they do, their URIs +adopt the same tombstone policy as everything else. + +### Previewing a Delete + +There is no dry-run endpoint in this revision (a delete-preview is a named +future extension). Clients can approximate one: + +1. `GET /storage-object/{id}` and read `entityIds`. +2. For each listed entity, `GET /entity/{id}` and inspect + `storageObjectIds`. +3. Any entity whose `storageObjectIds` contains only this storage object is + a pruning candidate. + +Treat the result as an **indication, not a promise** — the entity lifecycle +is implementation-defined, so a candidate may still be retained. + +## Tombstones + +Each implementation adopts **one** tombstone policy, declared as +`tombstonePolicy` in its [deposit capability](./#declaring-the-capability), +covering deleted storage-object URIs (including `/crate`) and the entity +knock-on alike — no mixing: + +- **`"410"`**: deleted URIs return `410 Gone` with a + [Tombstone](/docs/api/schemas/tombstone) body: + + ```json + { + "id": "https://catalog.paradisec.org.au/repository/NT1/001", + "resourceType": "storage-object", + "deletedAt": "2026-07-21T04:12:00Z", + "reason": "Withdrawn at the depositor's request" + } + ``` + + An entity or file tombstone MAY carry a `storageObjectId` naming the + storage object whose deletion orphaned it. + +- **`"404"`**: hard delete — deleted URIs are indistinguishable from URIs + that never existed. + +### ID Reuse + +A deleted storage-object ID MAY be recreated (`POST /deposits` with the +previously used ID); implementations MAY refuse with `409`. Recreation is a +**new object, not a continuation** — no version lineage and no relationship +to the deleted object's entities is implied. + +The policies pair naturally, though neither pairing is mandated: `410` +tombstones suit archives that reserve IDs forever (trustworthy citations); +`404` hard-delete suits clean reuse, including the delete-and-recreate flow +for changing an object's ID. + +## Open Deposits When the Object Is Deleted + +**Delete wins.** An open deposit targeting a deleted storage object can no +longer finalise: the finalise fails, the failure is recorded in the +deposit's `errors`, and the deposit returns to `open` — the same shape as a +validation failure. The client's move is to abort. Implementations MAY +auto-abort such deposits; cautious archives can instead refuse the delete +via the implementation-defined `409` above. + +## Enriching Entities: Curation Storage Objects + +There is no entity UPDATE. To enrich an entity beyond what its original +deposit said — without touching that deposit — deposit a small **curation +storage object** whose crate mentions the entity's `@id` and carries the +extra metadata. The ordinary +[many-to-one merge](./#materialisation) combines the contributions. + +For example, to flesh out an Organisation entity that a collection deposit +mentioned only by name, deposit a one-entity crate: + +```json +{ + "@id": "https://ror.org/03zparb35", + "@type": "Organization", + "name": "Australian National University", + "url": "https://www.anu.edu.au/" +} +``` + +The merged entity now lists both storage objects in `storageObjectIds` — +the enrichment survives re-deposit of the original object, carries its own +provenance, and flows through the normal session pathway with nothing new +to learn. + +## Deleting a Contributor-less Entity + +The one entity-level write: +[`DELETE /entity/{id}`](/docs/api/delete-entity) is valid **only** when the +entity's `storageObjectIds` is empty, and returns `409` otherwise. It +exists because no session-based operation can reach an entity that no +storage object contributes to — such as a retained Organisation whose last +contributor was deleted. Crate-backed data can never be touched this way: +while any storage object contributes, the delete is refused and changes go +through [deposit sessions](./updating) instead. diff --git a/docs/extensions/deposit/updating.md b/docs/extensions/deposit/updating.md new file mode 100644 index 0000000..48b3be1 --- /dev/null +++ b/docs/extensions/deposit/updating.md @@ -0,0 +1,78 @@ +--- +title: Updating a Storage Object +mdx.format: md +--- + +# Updating a Storage Object + +An update is a new deposit against an existing storage object: + +```http +POST /storage-object/https%3A%2F%2Fcatalog.paradisec.org.au%2Frepository%2FNT1%2F001/deposits +``` + +(`404` if the object doesn't exist.) From here the session is [the same as a +create deposit](./depositing) — same staging endpoints, same finalise, same +state machine. What differs is how the staged content resolves against the +version being replaced. + +## Crate-as-Manifest Carry-Forward + +An update deposit starts logically empty. You stage a **new crate** plus +**only the files that changed**. At finalise, the new crate is the +authoritative file manifest, and each file entity in it resolves in order: + +1. **Staged in this deposit** — the new bytes win. +2. **Carried forward from the baseline by `@id`** — the existing bytes are + kept, without re-upload. +3. **Unresolved** — the reference stays dangling (see below). + +Files present in the baseline version but **absent from the new crate drop +out** of the new version. There is no explicit file-delete call against a +storage object — the crate says what the new version holds. + +The common cases all fall out of this one rule: + +- **Fix a metadata typo**: stage the corrected crate, finalise. No files + staged; everything carries forward. (There is no separate + replace-crate-only fast path — this *is* it.) +- **Replace one recording**: stage the corrected crate (if the metadata + changed) or none at all, stage the new bytes at the file's `@id`, + finalise. Every other file carries forward. +- **Remove a file**: stage a crate that no longer references it, finalise. +- **Add a file**: stage a crate that references it, stage its bytes, + finalise. + +## Unresolved References + +An unresolved reference is **not a protocol error** — the file simply +`404`s when followed. This is the same non-policing integrity stance as the +rest of the specification: a crate may legitimately reference material the +archive does not hold. Strict archives MAY reject unresolved references at +finalise via implementation-defined validation (the uniform `422` +violations shape). + +The same resolution rule applies to create deposits — there is no baseline, +so every file entity without staged bytes is simply unresolved. + +## Concurrency + +- **The baseline is pinned when the deposit is opened.** Carry-forward + resolves against the version that was current at `POST + /storage-object/{id}/deposits` time, recorded as the deposit's + `createdAt`. +- **Finalise replaces the storage object wholesale.** The last finalise + wins *as a unit*: a published version is always exactly what one + depositor described — never a mix of two sessions. +- Concurrent open deposits against one storage object are allowed. + Implementations MAY reject a finalise whose baseline has been superseded + with `409`; clients should be prepared to re-open a deposit against the + new current version. + +## No Version History + +The API surface is current-version-only. The pinned baseline is internal +deposit state, not an exposed history surface: each successful finalise +produces a new current version, and prior versions are not addressable. +Implementations are free to keep full histories internally (for example in +OCFL); exposing them through the API would be a future extension. diff --git a/docs/extensions/index.md b/docs/extensions/index.md index 4502ab3..ca8f8ab 100644 --- a/docs/extensions/index.md +++ b/docs/extensions/index.md @@ -50,6 +50,7 @@ consumers a single authoritative definition. | Identifier | Adds | Capability details | | --- | --- | --- | | [`segments`](./segments) | `searchExtra.segments` — structured drill-down locations (PDF pages, time-aligned annotations) for full-text search matches inside files | none | +| [`deposit`](./deposit/) | Write access through deposit sessions against storage objects — the deposit and storage-object endpoints, plus `storageObjectIds` on Entity and `storageObjectId` on File | `idMinting`, `fileUpload`, `tombstonePolicy`, optional `depositTtlSeconds` and `maxFileSizeBytes` | ### Legacy Extensions diff --git a/docs/extensions/segments.md b/docs/extensions/segments.md index 73f44e5..cb85367 100644 --- a/docs/extensions/segments.md +++ b/docs/extensions/segments.md @@ -25,7 +25,7 @@ An implementation that provides segments declares the extension in ```json { - "apiVersion": "0.2.0", + "apiVersion": "0.3.0", "extensions": { "segments": {} } diff --git a/docs/getting-started/capabilities.md b/docs/getting-started/capabilities.md index 344c52c..324c16e 100644 --- a/docs/getting-started/capabilities.md +++ b/docs/getting-started/capabilities.md @@ -14,8 +14,15 @@ it instead of relying on per-archive configuration or probing responses. ```json { - "apiVersion": "0.2.0", - "extensions": { "segments": {} }, + "apiVersion": "0.3.0", + "extensions": { + "segments": {}, + "deposit": { + "idMinting": "both", + "fileUpload": ["inline", "presigned"], + "tombstonePolicy": "410" + } + }, "search": { "filters": { "inLanguage": { "type": "string", "label": "Language" }, diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 4192fb2..8eae218 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -190,7 +190,11 @@ const config: Config = { }, ], ], - themes: ['docusaurus-theme-openapi-docs'], + markdown: { + mermaid: true, + }, + + themes: ['docusaurus-theme-openapi-docs', '@docusaurus/theme-mermaid'], }; export default config; diff --git a/openapi.yaml b/openapi.yaml index abfb196..86b746c 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -16,6 +16,8 @@ info: When authentication is required, an API implementation MUST implement OAuth2 and it is recommended that OpenID is also added for simpler configuration and discoverability. + Write operations — the deposit and storage-object endpoints of the `deposit` extension — require the coarse OAuth2 `write` scope. Finer-grained authorisation policy (who may deposit what) is implementation-defined. + ## Rate Limiting API implementations MAY implement rate limiting to ensure fair usage and system stability. When rate limiting is active, responses will include rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`) and will return a 429 status code when limits are exceeded. @@ -24,6 +26,10 @@ info: The core specification can be extended through a curated registry of extensions defined in this document. Every extension has a stable identifier, a schema, and semantics. Implementations choose which extensions to implement and declare them through the `GET /capabilities` endpoint. Extension properties appear in core schemas as optional fields tagged with an `x-extension` annotation. See the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions) for the full extension model. + ## Deposits and storage objects + + Implementations may support write access through the registered `deposit` extension. All writes flow through deposit sessions against **storage objects** — an RO-Crate plus all the files it references, deposited and stored as a unit. The implementation materialises catalog entities from storage objects by its own rules; entities are read-only projections and have no write endpoints of their own. Write support is discovered by the presence of the `deposit` key in `capabilities.extensions`. + contact: name: Issues url: https://github.com/Language-Research-Technology/ro-crate-api/issues @@ -33,7 +39,7 @@ info: license: name: MIT identifier: MIT - version: 0.2.0 + version: 0.3.0 servers: - url: https://data.ldaca.edu.au/api description: LDaCA @@ -55,6 +61,12 @@ tags: - name: search description: Endpoints to perform searches on archived media and metadata. x-displayName: Search + - name: deposits + description: Endpoints for depositing content — open a deposit session against a storage object, stage an RO-Crate and files, and finalise. Part of the `deposit` extension. + x-displayName: Deposits + - name: storage_objects + description: Endpoints for reading and deleting storage objects — the deposited RO-Crates and files from which catalog entities are materialised. Part of the `deposit` extension. + x-displayName: Storage Objects - name: entity_model x-displayName: The Entity Model description: | @@ -67,6 +79,8 @@ x-tagGroups: - entities - files - search + - deposits + - storage_objects - name: Models tags: - entity_model @@ -222,6 +236,76 @@ paths: examples: default: $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + delete: + tags: + - entities + summary: Delete a contributor-less entity + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Delete an entity that no storage object contributes to — its `storageObjectIds` is empty. Such entities (for example an Organisation whose last contributing storage object was deleted but which the implementation chose to retain) cannot be reached by any deposit-session operation, so this is the one entity-level write. + + An entity with contributing storage objects cannot be deleted directly — its lifecycle is governed by its storage objects — and the request is rejected with `409 Conflict`. + + After deletion the entity's URI follows the implementation's declared `tombstonePolicy`. + operationId: deleteEntity + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - name: id + in: path + required: true + description: The unique RO-Crate ID representing a specific entity in the repository. + example: https://catalog.paradisec.org.au/repository/NT1/001 + schema: + $ref: "#/components/schemas/Id" + responses: + "204": + description: Entity deleted + "400": + description: Bad Request - Invalid ID format + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Entity not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the entity has contributing storage objects and must be managed through them + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" "429": $ref: "#/components/responses/RateLimitResponse" "500": @@ -236,6 +320,8 @@ paths: Retrieve the complete RO-Crate JSON-LD metadata for an entity. This returns the raw RO-Crate representation, which includes all metadata conforming to the RO-Crate specification. This endpoint works for any entity type (Collection, Object, or MediaObject) and returns the associated ro-crate-metadata.json content. + + The returned document's provenance is implementation-defined: it may be a stored crate, or a view derived from the crate(s) of the entity's contributing storage objects. Either way it MUST be a valid RO-Crate whose root data entity describes this entity. To retrieve an original deposited crate verbatim, use `GET /storage-object/{id}/crate` (part of the `deposit` extension). operationId: getEntityCrate parameters: - name: id @@ -298,6 +384,8 @@ paths: examples: default: $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" "429": $ref: "#/components/responses/RateLimitResponse" "500": @@ -353,6 +441,8 @@ paths: examples: default: $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" "429": $ref: "#/components/responses/RateLimitResponse" "500": @@ -772,6 +862,8 @@ paths: examples: default: $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" "416": description: Range Not Satisfiable - the requested range is invalid content: @@ -851,17 +943,773 @@ paths: required: true schema: type: integer - description: The size of the file content in bytes + description: The size of the file content in bytes + Content-Type: + required: true + schema: + type: string + description: The MIME type of the file + Last-Modified: + schema: + type: string + format: date-time + description: The date and time the file was last modified + ETag: + schema: + type: string + description: Entity tag for cache validation + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Entity not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /deposits: + post: + tags: + - deposits + summary: Create a deposit for a new storage object + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Open a deposit session that will create a new storage object. The storage object comes into existence only at the deposit's first successful finalise — until then nothing is readable and no entities exist. + + The request body MAY propose a `storageObjectId` where the implementation's `idMinting` capability is `client` or `both`; when the body or the field is absent the server mints one (`server` or `both`). Proposing an ID that is not supported by the declared `idMinting` mode is rejected with `422`; proposing an ID that already exists is rejected with `409`. The storage-object ID is returned immediately so the client can reference it from the deposited crate; whether the crate MUST reference it is implementation-defined and enforced at finalise. + + A previously deleted storage-object ID MAY be reused; implementations MAY refuse with `409`. Recreation is a new storage object, not a continuation — no relationship to the deleted object's history or entities is implied. + + To update an existing storage object, use `POST /storage-object/{id}/deposits` instead. + operationId: createDeposit + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + requestBody: + required: false + content: + application/json: + schema: + type: object + properties: + storageObjectId: + description: A client-proposed ID for the new storage object. Only valid when the implementation's `idMinting` capability is `client` or `both`. + $ref: "#/components/schemas/Id" + responses: + "201": + description: Deposit created + headers: + Location: + schema: + type: string + format: uri + description: The URL of the created deposit + content: + application/json: + schema: + $ref: "#/components/schemas/Deposit" + examples: + DepositResponse: + $ref: "#/components/examples/DepositResponse" + "400": + description: Bad Request - Invalid request body + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "409": + description: Conflict - a storage object with the proposed ID already exists, or the implementation refuses to reuse a deleted ID + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "422": + description: Unprocessable Entity - the request does not match the implementation's declared `idMinting` mode (an ID was proposed but not accepted, or omitted where the client must propose one) + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /deposit/{id}: + get: + tags: + - deposits + summary: Get a deposit + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Retrieve the deposit, including its lifecycle state, the files staged so far with per-file upload status, and the violations recorded by the most recent failed finalise. This is the polling resource for asynchronous finalisation: after a `202` from finalise, poll here until the state leaves `finalising`. + operationId: getDeposit + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Deposit" + examples: + DepositResponse: + $ref: "#/components/examples/DepositResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit not found - unknown, or expired and cleaned up + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + delete: + tags: + - deposits + summary: Abort a deposit + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Abort an `open` deposit, discarding its staged crate and files. Aborting is terminal; the storage object is left at its prior version (or never comes into existence for a create deposit). + + Deposits are also subject to implementation-defined expiry — an expired deposit behaves as aborted, and subsequent access MAY return `404`. Where the implementation declares `depositTtlSeconds` in `/capabilities`, that is the expiry horizon. + operationId: abortDeposit + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + responses: + "204": + description: Deposit aborted + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit not found - unknown, or expired and cleaned up + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the deposit is not in the `open` state + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /deposit/{id}/crate: + put: + tags: + - deposits + summary: Stage the RO-Crate metadata + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Stage the RO-Crate metadata document for this deposit. This is a full replace — staging a new crate discards the previously staged one; there is no crate PATCH and no crate DELETE. The crate and files may be staged in any order; crate–file association is checked at finalise. + + At finalise the staged crate becomes the storage object's authoritative file manifest: each file entity in the crate resolves to bytes staged in this deposit, else (for update deposits) to the file carried forward by `@id` from the baseline version, else remains an unresolved reference. Unresolved references are not protocol errors — they simply `404` when followed — but implementations MAY reject them at finalise via validation. Files present in the baseline but absent from the new crate drop out of the new version. + operationId: stageDepositCrate + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + requestBody: + required: true + content: + application/ld+json: + schema: + type: object + description: RO-Crate metadata conforming to the RO-Crate specification + responses: + "204": + description: Crate staged + "400": + description: Bad Request - the body is not a JSON-LD document + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit not found - unknown, or expired and cleaned up + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the deposit is not in the `open` state + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /deposit/{id}/file/{fileId}: + put: + tags: + - deposits + summary: Stage a file + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Stage a file in this deposit. `{fileId}` is the file entity's `@id` in the deposited crate, percent-encoded — for attached files, its crate-relative path. The crate and files may be staged in any order. + + Two upload modes share this endpoint, discriminated by the request `Content-Type`; the implementation declares which it supports in the `fileUpload` capability: + + - **Inline** (`fileUpload` contains `inline`): the request body is the file's bytes, sent with the file's own media type. Responds `204`. + - **Presigned** (`fileUpload` contains `presigned`): the request body is `application/json` transport metadata (size, checksum, media type) and the response is `200` with an upload target the client sends the bytes to directly. There is no per-file completion call — finalise verifies that the bytes landed and match the declared size and checksum. + + Only transport metadata is carried here; descriptive metadata about the file lives in the crate. Staging the same `{fileId}` again replaces the earlier staging. Using a mode the implementation does not declare is rejected with `400`. + operationId: stageDepositFile + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + - name: fileId + in: path + required: true + description: The file entity's `@id` in the deposited crate, percent-encoded. For attached files this is the crate-relative path. + example: NT1-001-001A.mp3 + schema: + type: string + format: uri-reference + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/FileStagingMetadata" + "*/*": + schema: + type: string + format: binary + description: The file's bytes, sent with the file's own media type (inline mode). + responses: + "200": + description: Transport metadata staged (presigned mode) - upload the bytes to the returned target + content: + application/json: + schema: + $ref: "#/components/schemas/FileUploadTarget" + examples: + FileUploadTargetResponse: + $ref: "#/components/examples/FileUploadTargetResponse" + "204": + description: File staged (inline mode) + "400": + description: Bad Request - invalid transport metadata, or an upload mode the implementation does not declare + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit not found - unknown, or expired and cleaned up + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the deposit is not in the `open` state + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "413": + description: Content Too Large - the file exceeds the implementation's declared `maxFileSizeBytes` + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + delete: + tags: + - deposits + summary: Remove a staged file + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Remove a file staged in this deposit. Valid while the deposit is `open`. This only affects the deposit's staging area — to drop a file from an existing storage object, stage a crate that no longer references it. + operationId: unstageDepositFile + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + - name: fileId + in: path + required: true + description: The file entity's `@id` in the deposited crate, percent-encoded. For attached files this is the crate-relative path. + example: NT1-001-001A.mp3 + schema: + type: string + format: uri-reference + responses: + "204": + description: Staged file removed + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit or staged file not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the deposit is not in the `open` state + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /deposit/{id}/finalise: + post: + tags: + - deposits + summary: Finalise a deposit + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Finalise the deposit: validate the staged content, publish it as the storage object's new current version (replacing the prior version wholesale), and materialise catalog entities from it. Validation depth and materialisation rules are implementation-defined. + + Finalisation MAY complete synchronously or asynchronously, at the server's discretion per request — there is no capability flag. A `200` returns the deposit in state `complete`; a `202` returns it in state `finalising`, and the client polls `GET /deposit/{id}` until the state leaves `finalising`. One client code path handles both. + + For every file staged in presigned mode, finalise verifies the bytes landed and match the declared size and checksum; missing or mismatched files are validation violations. + + **Failure atomicity is guaranteed**: a finalise that does not reach `complete` leaves no observable change. On validation failure the deposit returns to `open` with the violations recorded — as a `422` on the synchronous path, and in the deposit's `errors` field on the asynchronous path. Non-validation failures (including the target storage object having been deleted mid-deposit) also return the deposit to `open` with the failure recorded; retry is safe, and abort covers walking away. Once `complete`, the new crate and all materialised entities are readable; readers are not guaranteed to observe the transition as a single atomic flip. + + For update deposits, carry-forward resolves against the baseline version pinned when the deposit was opened; the last finalise wins as a unit. Implementations MAY reject a finalise whose baseline has been superseded with `409`. + operationId: finaliseDeposit + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/DepositIdParameter" + responses: + "200": + description: Finalised synchronously - the deposit is `complete` and the storage object's new version is published + content: + application/json: + schema: + $ref: "#/components/schemas/Deposit" + examples: + DepositCompleteResponse: + $ref: "#/components/examples/DepositCompleteResponse" + "202": + description: Accepted - finalisation is proceeding asynchronously; poll `GET /deposit/{id}` until the state leaves `finalising` + content: + application/json: + schema: + $ref: "#/components/schemas/Deposit" + examples: + DepositFinalisingResponse: + $ref: "#/components/examples/DepositFinalisingResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Deposit not found - unknown, or expired and cleaned up + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the deposit is not in the `open` state, or the implementation rejects a finalise whose baseline has been superseded + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "422": + description: Unprocessable Entity - validation failed; the deposit has returned to `open` with the violations recorded, staged content intact + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/FinaliseValidationErrorResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /storage-objects: + get: + tags: + - storage_objects + summary: List storage objects + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + List storage objects, paginated and sorted. The response contains whatever the caller is allowed to see under the implementation's visibility model: implementations choose whether storage objects are a public surface (listable by anyone, with per-object `access` governing crate retrieval) or a depositor-only management surface (requiring the `write` scope). + + There are no content filters — catalog-side questions belong to `/entities` and `/search`. + operationId: listStorageObjects + x-extension: deposit + parameters: + - $ref: "#/components/parameters/LimitParameter" + - $ref: "#/components/parameters/OffsetParameter" + - $ref: "#/components/parameters/StorageObjectSortParameter" + - $ref: "#/components/parameters/OrderParameter" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + description: A list of storage objects visible to the caller. + required: + - total + - storageObjects + properties: + total: + description: Total number of storage objects (before pagination) visible to the caller. + type: integer + example: 42 + storageObjects: + type: array + items: + $ref: "#/components/schemas/StorageObject" + examples: + StorageObjectsListResponse: + $ref: "#/components/examples/StorageObjectsListResponse" + "400": + description: Bad Request - Invalid parameters + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + examples: + default: + $ref: "#/components/examples/ValidationErrorResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /storage-object/{id}: + get: + tags: + - storage_objects + summary: Get a storage object + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Retrieve a storage object. The body is deliberately lean: identity, the entities materialised from the current version, timestamps, and access. The deposited crate — `GET /storage-object/{id}/crate` — is the single source of truth for the object's content inventory; the storage object carries no file list of its own. + + `entityIds` is the authoritative answer to "what did my deposit create". It is the inverse of the entity's `storageObjectIds` and can change when later deposits (of this or other storage objects) alter the materialisation. + operationId: getStorageObject + x-extension: deposit + parameters: + - $ref: "#/components/parameters/StorageObjectIdParameter" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/StorageObject" + examples: + StorageObjectResponse: + $ref: "#/components/examples/StorageObjectResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Storage object not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + delete: + tags: + - storage_objects + summary: Delete a storage object + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Delete a storage object — its crate and files. Deletion is not a deposit session; it is already atomic. Implementations needing slow teardown MAY return `202 Accepted`. + + The spec mandates no preconditions; implementations MAY refuse per their own policy (curatorial holds, cross-references) with `409` and a reason. The effect on materialised entities is implementation-defined, mirroring re-deposit pruning: an entity no other storage object contributes to MAY be removed, and deliberate retention is legitimate. An entity with other contributors survives — the deleted object simply drops out of its `storageObjectIds`. + + Open deposits do not block deletion: delete wins, and a subsequent finalise of such a deposit fails back to `open` with the failure recorded. Implementations MAY auto-abort open deposits against the deleted object. + + After deletion, the storage object's URIs (including `/crate`) follow the implementation's declared `tombstonePolicy`. + operationId: deleteStorageObject + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/StorageObjectIdParameter" + responses: + "204": + description: Storage object deleted + "202": + description: Accepted - deletion is proceeding asynchronously + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Storage object not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "409": + description: Conflict - the implementation refuses the deletion per its own policy; the body carries the reason + content: + application/json: + schema: + $ref: "#/components/schemas/ConflictError" + examples: + default: + $ref: "#/components/examples/ConflictErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /storage-object/{id}/crate: + get: + tags: + - storage_objects + summary: Get the deposited RO-Crate + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Retrieve the storage object's current RO-Crate metadata document, verbatim as deposited. Unlike `GET /entity/{id}/rocrate`, which may return a derived view, this endpoint always returns an original deposited crate. + operationId: getStorageObjectCrate + x-extension: deposit + parameters: + - $ref: "#/components/parameters/StorageObjectIdParameter" + responses: + "200": + description: Returns the deposited RO-Crate JSON-LD metadata + headers: + Content-Length: + required: true + schema: + type: integer + description: The size of the returned content in bytes + Content-Type: + required: true + schema: + type: string + description: The MIME type of the returned content + Last-Modified: + schema: + type: string + format: date-time + description: The date and time the crate was last modified + ETag: + schema: + type: string + description: Entity tag for cache validation + content: + application/ld+json: + schema: + type: object + description: RO-Crate metadata conforming to the RO-Crate specification + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Storage object not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + head: + tags: + - storage_objects + summary: Get deposited RO-Crate headers + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Retrieve the deposited crate's headers without downloading the content. Returns the same headers as GET but with no response body, useful for checking availability and caching information. + operationId: headStorageObjectCrate + x-extension: deposit + parameters: + - $ref: "#/components/parameters/StorageObjectIdParameter" + responses: + "200": + description: Deposited RO-Crate headers + headers: + Content-Length: + required: true + schema: + type: integer + description: The size of the crate content in bytes Content-Type: required: true schema: type: string - description: The MIME type of the file + description: The MIME type of the crate content Last-Modified: schema: type: string format: date-time - description: The date and time the file was last modified + description: The date and time the crate was last modified ETag: schema: type: string @@ -871,7 +1719,64 @@ paths: "403": $ref: "#/components/responses/ForbiddenResponse" "404": - description: Entity not found + description: Storage object not found + content: + application/json: + schema: + $ref: "#/components/schemas/NotFoundError" + examples: + default: + $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" + "429": + $ref: "#/components/responses/RateLimitResponse" + "500": + $ref: "#/components/responses/InternalServerErrorResponse" + + /storage-object/{id}/deposits: + post: + tags: + - deposits + summary: Create a deposit to update a storage object + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only available when the implementation declares the `deposit` extension in `/capabilities`. + + Open a deposit session against an existing storage object. The deposit starts logically empty; the client stages a new crate plus only the files that changed. At finalise the new crate is the authoritative file manifest — unchanged files are carried forward from the baseline by `@id`, and files absent from the new crate drop out. A metadata-only fix is therefore just `PUT /deposit/{id}/crate` followed by finalise. + + The baseline for carry-forward is the storage object's current version at the moment this deposit is created. Concurrent open deposits against one storage object are allowed; each finalise replaces the storage object wholesale, so the last finalise wins as a unit. + operationId: createUpdateDeposit + x-extension: deposit + security: + - ApiKey: [] + - OAuth2: + - write + - OpenID: + - write + parameters: + - $ref: "#/components/parameters/StorageObjectIdParameter" + responses: + "201": + description: Deposit created + headers: + Location: + schema: + type: string + format: uri + description: The URL of the created deposit + content: + application/json: + schema: + $ref: "#/components/schemas/Deposit" + examples: + DepositResponse: + $ref: "#/components/examples/DepositResponse" + "401": + $ref: "#/components/responses/UnauthorizedResponse" + "403": + $ref: "#/components/responses/ForbiddenResponse" + "404": + description: Storage object not found content: application/json: schema: @@ -879,6 +1784,8 @@ paths: examples: default: $ref: "#/components/examples/NotFoundErrorResponse" + "410": + $ref: "#/components/responses/GoneResponse" "429": $ref: "#/components/responses/RateLimitResponse" "500": @@ -944,6 +1851,33 @@ components: schema: $ref: "#/components/schemas/Order" default: "asc" + DepositIdParameter: + name: id + in: path + required: true + description: The deposit ID, as returned when the deposit was created. + example: dep_8f14e45f + schema: + type: string + StorageObjectIdParameter: + name: id + in: path + required: true + description: The storage object ID. + example: https://catalog.paradisec.org.au/repository/NT1/001 + schema: + $ref: "#/components/schemas/Id" + StorageObjectSortParameter: + name: sort + in: query + description: Field to sort by. + example: id + schema: + type: string + enum: + - id + - lastDepositedAt + default: id responses: RateLimitResponse: @@ -996,6 +1930,15 @@ components: examples: default: $ref: "#/components/examples/InternalServerErrorResponse" + GoneResponse: + description: Gone - the resource has been deleted. Returned in place of 404 when the implementation declares the `deposit` extension with a `tombstonePolicy` of `"410"`; the body is a tombstone describing the deletion. Under a `tombstonePolicy` of `"404"`, deleted resources return 404 instead. + content: + application/json: + schema: + $ref: "#/components/schemas/Tombstone" + examples: + default: + $ref: "#/components/examples/TombstoneResponse" securitySchemes: ApiKey: @@ -1018,6 +1961,7 @@ components: tokenUrl: /oauth/token scopes: read: Grants read access + write: Grants write access through deposit sessions (the `deposit` extension). Finer-grained authorisation policy is implementation-defined. schemas: Id: @@ -1068,7 +2012,7 @@ components: apiVersion: type: string description: The version of this specification that the implementation targets. - example: "0.2.0" + example: "0.3.0" extensions: type: object description: | @@ -1079,10 +2023,17 @@ components: segments: $ref: "#/components/schemas/SegmentsCapability" x-extension: segments + deposit: + $ref: "#/components/schemas/DepositCapability" + x-extension: deposit additionalProperties: type: object example: segments: {} + deposit: + idMinting: both + fileUpload: [inline, presigned] + tombstonePolicy: "410" search: $ref: "#/components/schemas/SearchCapability" SearchCapability: @@ -1122,6 +2073,52 @@ components: type: object description: Details the implementation communicates about its `segments` support. The extension currently has no extra details to communicate; the value is an empty object. x-extension: segments + DepositCapability: + type: object + description: | + Details the implementation communicates about its `deposit` support. Presence of the `deposit` key in `capabilities.extensions` is how clients discover write support; there is no separate write flag. + x-extension: deposit + required: + - idMinting + - fileUpload + - tombstonePolicy + properties: + idMinting: + type: string + enum: + - client + - server + - both + description: How storage-object IDs are minted at deposit creation. `client` - the client MUST propose an ID; `server` - the server always mints one; `both` - the client MAY propose an ID and the server mints one when absent. + example: both + fileUpload: + type: array + minItems: 1 + items: + type: string + enum: + - inline + - presigned + description: The file staging modes the implementation supports on `PUT /deposit/{id}/file/{fileId}`. `inline` - the file's bytes in the request body; `presigned` - transport metadata in the request, bytes uploaded directly to a returned target. New modes may be added by revision of this specification; clients MUST ignore values they do not recognise. + example: [inline, presigned] + tombstonePolicy: + type: string + enum: + - "410" + - "404" + description: What deleted resource URIs return. `"410"` - deleted URIs respond 410 Gone with a `Tombstone` body; `"404"` - deleted resources are indistinguishable from those that never existed. One policy covers storage-object URIs (including `/crate`) and materialised entities alike. + example: "410" + depositTtlSeconds: + type: integer + minimum: 1 + description: How long an open deposit lives before expiring. When absent, expiry is implementation-defined and clients should not rely on any particular TTL. + example: 604800 + maxFileSizeBytes: + type: integer + format: int64 + minimum: 1 + description: The largest file the implementation accepts in a deposit. When absent, no limit is declared. + example: 5368709120 FacetCapability: type: object description: Describes a search facet field the implementation supports. @@ -1320,6 +2317,17 @@ components: metadata: true content: false contentAuthorizationUrl: "https://test.cadre.example.com/catalogue/application?id=https%3A%2F%2Fhttps%3A%2F%2Fcatalog.paradisec.org.au%2Flicenses%2Ftest" + storageObjectIds: + type: array + items: + $ref: "#/components/schemas/Id" + x-extension: deposit + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only present when the implementation declares the `deposit` extension in `/capabilities`. + + The storage objects whose current versions contribute to this entity. Usually one; more when the implementation's materialisation merges contributions from several storage objects into a single entity. An entity MAY be removed once no storage object contributes to it. + example: + - https://catalog.paradisec.org.au/repository/NT1/001 File: type: object description: | @@ -1368,6 +2376,13 @@ components: description: URL for enrolment or authorisation process if content access is restricted. example: content: true + storageObjectId: + x-extension: deposit + description: | + Part of the `deposit` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only present when the implementation declares the `deposit` extension in `/capabilities`. + + The storage object whose deposit supplied this file's bytes. Singular, because a file's bytes arrive in exactly one deposit. May be absent for files predating any storage object, or where the implementation withholds it. + $ref: "#/components/schemas/Id" SearchEntity: description: Contains additional information returned in search contexts. properties: @@ -1394,6 +2409,230 @@ components: Part of the `segments` extension — see the [Extensions guide](https://language-research-technology.github.io/ro-crate-api/docs/extensions). Only present when the implementation declares the `segments` extension in `/capabilities`. Locations inside the file where the full-text match occurred, allowing clients to deep-link the user to the match (e.g. a PDF page or an ELAN annotation's time range). Segments are optional — absent or empty for hits without structured content. They are ranked by relevance and capped at an implementation-defined limit. + Deposit: + type: object + x-extension: deposit + description: | + A deposit session against a storage object. Part of the `deposit` extension. + + A deposit is opened against a new storage object (`POST /deposits`) or an existing one (`POST /storage-object/{id}/deposits`), staged with an RO-Crate and files, then finalised. Deposits are single-use: once `complete` they are finished, and further changes open a new deposit. + required: + - depositId + - storageObjectId + - state + properties: + depositId: + type: string + description: Server-minted opaque identifier for this deposit. + example: dep_8f14e45f + storageObjectId: + description: The storage object this deposit targets. Once the deposit is `complete`, retrieve it via `GET /storage-object/{id}` — its `entityIds` list is the authoritative answer to what the deposit materialised. + $ref: "#/components/schemas/Id" + state: + type: string + enum: + - open + - finalising + - complete + - aborted + description: | + The deposit's lifecycle state. `open` - accepting staging calls; `finalising` - a finalise is in progress and staging calls are rejected with 409; `complete` - the storage object's new version is published (terminal); `aborted` - explicitly aborted or expired, staged content discarded (terminal). A failed finalise returns the deposit to `open` with the failure recorded in `errors`. + example: open + createdAt: + type: string + format: date-time + description: When the deposit was created. This is also the moment the carry-forward baseline is pinned for update deposits. + files: + type: array + description: The files staged in this deposit, with per-file upload status. Status MAY be updated eagerly or lazily; finalise is the authoritative verification point. + items: + $ref: "#/components/schemas/StagedFile" + errors: + type: array + description: The violations recorded when the most recent finalise failed and the deposit returned to `open`. Cleared when the next finalise is accepted; absent when there has been no failure. + items: + type: object + properties: + field: + type: string + description: The field or file the violation concerns + message: + type: string + description: Validation error message + value: + description: The invalid value + example: + - field: NT1-001-001A.wav + message: staged file bytes not received + StagedFile: + type: object + x-extension: deposit + description: A file staged in a deposit, with its upload status. Part of the `deposit` extension. + required: + - fileId + - status + properties: + fileId: + type: string + format: uri-reference + description: The file entity's `@id` in the deposited crate. For attached files this is the crate-relative path. + example: NT1-001-001A.mp3 + status: + type: string + enum: + - pending + - received + description: "`pending` - staged in presigned mode and the bytes have not (yet) been observed; `received` - the bytes are held. Finalise remains the authoritative verification point." + example: received + size: + type: integer + format: int64 + minimum: 0 + description: The file's size in bytes, where declared or known. + example: 2048576 + StorageObject: + type: object + x-extension: deposit + description: | + A storage object is the unit of deposit: an RO-Crate plus all the files it references, stored as deposited. Part of the `deposit` extension. + + Catalog entities are materialised from storage objects by implementation-specific rules — one storage object may yield one entity or many, and several storage objects may contribute to a single merged entity. The deposited crate (`GET /storage-object/{id}/crate`) is the single source of truth for the object's content inventory; the storage object carries no file list of its own. + required: + - id + - entityIds + - createdAt + - lastDepositedAt + - access + properties: + id: + description: The storage object's ID. + example: https://catalog.paradisec.org.au/repository/NT1/001 + $ref: "#/components/schemas/Id" + entityIds: + type: array + items: + $ref: "#/components/schemas/Id" + description: The entities materialised from this storage object's current version — the inverse of the entity's `storageObjectIds`. Can change when later deposits (of this or other storage objects) alter the materialisation. + example: + - https://catalog.paradisec.org.au/repository/NT1/001 + - https://catalog.paradisec.org.au/repository/NT1/001/NT1-001-001A.mp3 + createdAt: + type: string + format: date-time + description: When the storage object was first created (its first successful finalise). + lastDepositedAt: + type: string + format: date-time + description: When the storage object's current version was published (its most recent successful finalise). + access: + type: object + description: Access information for this storage object. `metadata` governs this resource; `content` governs the deposited crate and file retrieval. + required: + - metadata + - content + properties: + metadata: + type: boolean + description: Whether this storage-object resource is accessible to the current user. + content: + type: boolean + description: Whether the deposited crate is accessible to the current user. + metadataAuthorizationUrl: + type: string + format: uri + description: URL for enrolment or authorisation process if metadata access is restricted. + contentAuthorizationUrl: + type: string + format: uri + description: URL for enrolment or authorisation process if content access is restricted. + example: + metadata: true + content: true + Tombstone: + type: object + x-extension: deposit + description: | + A record of a deletion, returned with `410 Gone` when the implementation's `tombstonePolicy` is `"410"`. Part of the `deposit` extension. One policy covers storage-object URIs (including `/crate`) and materialised entities alike. + required: + - id + - resourceType + - deletedAt + properties: + id: + description: The ID of the deleted resource. + example: https://catalog.paradisec.org.au/repository/NT1/001 + $ref: "#/components/schemas/Id" + resourceType: + type: string + enum: + - storage-object + - entity + - file + description: The kind of resource that was deleted. + example: storage-object + deletedAt: + type: string + format: date-time + description: When the resource was deleted. + reason: + type: string + description: An optional human-readable reason for the deletion. + example: Withdrawn at the depositor's request + storageObjectId: + description: For entity and file tombstones, the storage object whose deletion led to this resource's removal, where known. + $ref: "#/components/schemas/Id" + FileStagingMetadata: + type: object + x-extension: deposit + description: | + Transport metadata staged for a file in presigned mode. Part of the `deposit` extension. Carries only what is needed to move and verify the bytes — descriptive metadata about the file lives in the deposited crate. + required: + - size + properties: + size: + type: integer + format: int64 + minimum: 0 + description: The file's size in bytes. Verified at finalise. + example: 2048576 + checksum: + type: string + description: The file's checksum, prefixed with the algorithm (e.g. `sha256:`). Verified at finalise when supplied. + example: "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" + mediaType: + type: string + maxLength: 127 + pattern: '^[a-z]+/[a-z0-9\-\+\.]+$' + description: The MIME type of the file. + example: audio/x-wav + FileUploadTarget: + type: object + x-extension: deposit + description: Where to send a file's bytes after staging it in presigned mode. Part of the `deposit` extension. There is no per-file completion call — finalise verifies the upload. + required: + - uploadUrl + properties: + uploadUrl: + type: string + format: uri + description: The URL to upload the file's bytes to, typically a presigned object-store URL. + example: "https://uploads.example.org/deposit/dep_8f14e45f/NT1-001-001A.wav?signature=..." + method: + type: string + default: PUT + description: The HTTP method to use for the upload. + example: PUT + headers: + type: object + additionalProperties: + type: string + description: Headers the client MUST include in the upload request. + example: + Content-Type: audio/x-wav + expiresAt: + type: string + format: date-time + description: When the upload target stops accepting bytes. Re-stage the file to obtain a fresh target. ValidationError: type: object required: @@ -1466,6 +2705,34 @@ components: description: Unique identifier for this request, useful for debugging example: 550e8400-e29b-41d4-a716-446655440000 + ConflictError: + type: object + required: + - error + properties: + error: + type: object + required: + - code + - message + properties: + code: + type: string + enum: [CONFLICT] + message: + type: string + description: Human-readable error message + example: A storage object with this ID already exists + details: + type: object + description: Additional error details specific to the error type + additionalProperties: true + requestId: + type: string + format: uuid + description: Unique identifier for this request, useful for debugging + example: 550e8400-e29b-41d4-a716-446655440000 + InvalidEntityTypeError: description: >- Returned when an operation requires a specific entity type but the @@ -1638,9 +2905,14 @@ components: CapabilitiesResponse: summary: Example capabilities response value: - apiVersion: "0.2.0" + apiVersion: "0.3.0" extensions: segments: {} + deposit: + idMinting: "both" + fileUpload: ["inline", "presigned"] + tombstonePolicy: "410" + depositTtlSeconds: 604800 search: filters: inLanguage: @@ -1902,3 +3174,124 @@ components: code: "INTERNAL_ERROR" message: "An unexpected error occurred" requestId: "550e8400-e29b-41d4-a716-446655440000" + + DepositResponse: + summary: Example deposit in the open state + value: + depositId: "dep_8f14e45f" + storageObjectId: "https://catalog.paradisec.org.au/repository/NT1/001" + state: "open" + createdAt: "2026-07-21T03:24:00Z" + files: + - fileId: "NT1-001-001A.mp3" + status: "received" + size: 2048576 + - fileId: "NT1-001-001A.wav" + status: "pending" + size: 52428800 + + DepositFinalisingResponse: + summary: Example deposit finalising asynchronously + value: + depositId: "dep_8f14e45f" + storageObjectId: "https://catalog.paradisec.org.au/repository/NT1/001" + state: "finalising" + createdAt: "2026-07-21T03:24:00Z" + files: + - fileId: "NT1-001-001A.mp3" + status: "received" + size: 2048576 + - fileId: "NT1-001-001A.wav" + status: "received" + size: 52428800 + + DepositCompleteResponse: + summary: Example completed deposit + value: + depositId: "dep_8f14e45f" + storageObjectId: "https://catalog.paradisec.org.au/repository/NT1/001" + state: "complete" + createdAt: "2026-07-21T03:24:00Z" + files: + - fileId: "NT1-001-001A.mp3" + status: "received" + size: 2048576 + - fileId: "NT1-001-001A.wav" + status: "received" + size: 52428800 + + StorageObjectResponse: + summary: Example storage object response + value: + id: "https://catalog.paradisec.org.au/repository/NT1/001" + entityIds: + - "https://catalog.paradisec.org.au/repository/NT1/001" + - "https://catalog.paradisec.org.au/repository/NT1/001/NT1-001-001A.mp3" + - "https://catalog.paradisec.org.au/repository/NT1/001/NT1-001-001A.wav" + createdAt: "2024-03-02T09:10:00Z" + lastDepositedAt: "2026-07-21T03:30:00Z" + access: + metadata: true + content: true + + StorageObjectsListResponse: + summary: Example storage objects list response + value: + total: 2 + storageObjects: + - id: "https://catalog.paradisec.org.au/repository/NT1/001" + entityIds: + - "https://catalog.paradisec.org.au/repository/NT1/001" + - "https://catalog.paradisec.org.au/repository/NT1/001/NT1-001-001A.mp3" + createdAt: "2024-03-02T09:10:00Z" + lastDepositedAt: "2026-07-21T03:30:00Z" + access: + metadata: true + content: true + - id: "https://catalog.paradisec.org.au/repository/NT1/002" + entityIds: + - "https://catalog.paradisec.org.au/repository/NT1/002" + createdAt: "2024-05-14T22:41:00Z" + lastDepositedAt: "2024-05-14T22:41:00Z" + access: + metadata: true + content: false + + TombstoneResponse: + summary: Example tombstone response + value: + id: "https://catalog.paradisec.org.au/repository/NT1/001" + resourceType: "storage-object" + deletedAt: "2026-07-01T00:00:00Z" + reason: "Withdrawn at the depositor's request" + + ConflictErrorResponse: + summary: Example conflict error response + value: + error: + code: "CONFLICT" + message: "A storage object with this ID already exists" + requestId: "550e8400-e29b-41d4-a716-446655440000" + + FileUploadTargetResponse: + summary: Example file upload target response + value: + uploadUrl: "https://uploads.example.org/deposit/dep_8f14e45f/NT1-001-001A.wav?signature=c2ln" + method: "PUT" + headers: + Content-Type: "audio/x-wav" + expiresAt: "2026-07-22T03:24:00Z" + + FinaliseValidationErrorResponse: + summary: Example finalise validation error response + value: + error: + code: "VALIDATION_ERROR" + message: "Deposit validation failed; the deposit has returned to the open state" + details: + violations: + - field: "NT1-001-001A.wav" + message: "staged file bytes not received" + - field: "./" + message: "root dataset does not reference the storage object ID" + requestId: "550e8400-e29b-41d4-a716-446655440000" diff --git a/package.json b/package.json index aa594a3..908580a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@docusaurus/core": "^3.10.2", "@docusaurus/faster": "^3.10.2", "@docusaurus/preset-classic": "^3.10.2", + "@docusaurus/theme-mermaid": "^3.10.2", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "docusaurus-plugin-openapi-docs": "^5.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 980e203..a547279 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@docusaurus/preset-classic': specifier: ^3.10.2 version: 3.10.2(@algolia/client-search@5.55.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.16))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.12)(@swc/core@1.15.43)(@swc/html@1.15.43)(@types/react@19.2.17)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(supports-color@8.1.1)(typescript@5.9.3) + '@docusaurus/theme-mermaid': + specifier: ^3.10.2 + version: 3.10.2(85eac7e6f4c099abe4e6a78ba3064efd) '@mdx-js/react': specifier: ^3.1.1 version: 3.1.1(@types/react@19.2.17)(react@19.2.7) @@ -154,6 +157,9 @@ packages: resolution: {integrity: sha512-lCwXyijwPm3vbYHpBXPRomMcD6mgiptmps27gnMCf4HK+u/AOeFPBnIFh4V3l4A5SnP9VRiKBZqwGBpUH0vaTg==} engines: {node: '>= 14.0.0'} + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + '@apidevtools/json-schema-ref-parser@15.4.0': resolution: {integrity: sha512-QbMJJlMZd27fZmi7Q+twCqwABlfaO4Qdc1YvbbwkqN2lILfELnfWfw9xFFl6CeF5jAeGQpokUVhvCkhz+rvEGg==} engines: {node: '>=20'} @@ -789,6 +795,12 @@ packages: cpu: [x64] os: [win32] + '@braintree/sanitize-url@7.1.2': + resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} + + '@chevrotain/types@11.1.2': + resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==} + '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -1279,6 +1291,17 @@ packages: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 + '@docusaurus/theme-mermaid@3.10.2': + resolution: {integrity: sha512-Stssh5MYQJ+EdYugUXf+ZcpeJFQPKXf0KCd/SWp10o3CmXNaOoh5IEgVjVqY1e1XhQf3on4+Y4BnrMiD95E2SQ==} + engines: {node: '>=20.0'} + peerDependencies: + '@mermaid-js/layout-elk': ^0.1.9 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@mermaid-js/layout-elk': + optional: true + '@docusaurus/theme-search-algolia@3.10.2': resolution: {integrity: sha512-1msxllyhi/5m77JukXtp5UFnUAriwZIC1oJ7MTnpQpCwLTbclJi5BK5n28CTZuSXpQN2ewbbnqRgAhMM6c6ihg==} engines: {node: '>=20.0'} @@ -1340,6 +1363,12 @@ packages: react-dom: '>=16.8.0' react-hook-form: ^7.0.0 + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@3.1.4': + resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==} + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1499,6 +1528,9 @@ packages: '@types/react': '>=16' react: '>=16' + '@mermaid-js/parser@1.2.0': + resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==} + '@module-federation/error-codes@0.22.0': resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} @@ -2080,6 +2112,99 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.4': + resolution: {integrity: sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -2095,6 +2220,9 @@ packages: '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -2185,6 +2313,9 @@ packages: '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2206,6 +2337,9 @@ packages: '@ungap/structured-clone@1.3.2': resolution: {integrity: sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==} + '@upsetjs/venn.js@2.0.0': + resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==} + '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -2764,6 +2898,12 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -2902,6 +3042,165 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.34.0: + resolution: {integrity: sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.14: + resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -2965,6 +3264,9 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + delaunator@5.1.0: + resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} + depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} @@ -3053,6 +3355,9 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dompurify@3.4.12: + resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==} + domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} @@ -3135,6 +3440,9 @@ packages: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} + es-toolkit@1.49.0: + resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} @@ -3443,6 +3751,9 @@ packages: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} @@ -3631,6 +3942,9 @@ packages: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -3660,6 +3974,13 @@ packages: inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + interpret@1.4.0: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} @@ -3886,9 +4207,16 @@ packages: jsonfile@6.2.1: resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + katex@0.16.47: + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + hasBin: true + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -3904,6 +4232,12 @@ packages: launch-editor@2.14.1: resolution: {integrity: sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==} + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -4005,6 +4339,9 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -4047,6 +4384,11 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + marked@16.4.2: + resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} + engines: {node: '>= 20'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -4130,6 +4472,9 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + mermaid@11.16.0: + resolution: {integrity: sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==} + methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -4577,6 +4922,9 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + package-manager-detector@1.7.0: + resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==} + pako@2.2.0: resolution: {integrity: sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==} @@ -4613,6 +4961,9 @@ packages: path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + path-exists@5.0.0: resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4671,6 +5022,12 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + postcss-attribute-case-insensitive@7.0.1: resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==} engines: {node: '>=18'} @@ -5408,6 +5765,12 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + robust-predicates@3.0.3: + resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} + + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + rtlcss@4.3.0: resolution: {integrity: sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==} engines: {node: '>=12.0.0'} @@ -5420,6 +5783,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -5726,6 +6092,9 @@ packages: peerDependencies: postcss: ^8.4.31 + stylis@4.4.0: + resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==} + sucrase@3.35.1: resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} @@ -5835,6 +6204,10 @@ packages: tiny-warning@1.0.3: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -5873,6 +6246,10 @@ packages: ts-algebra@1.2.2: resolution: {integrity: sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==} + ts-dedent@2.3.0: + resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==} + engines: {node: '>=6.10'} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -6013,6 +6390,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@14.0.1: + resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). @@ -6379,6 +6760,11 @@ snapshots: dependencies: '@algolia/client-common': 5.55.1 + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.7.0 + tinyexec: 1.2.4 + '@apidevtools/json-schema-ref-parser@15.4.0(@types/json-schema@7.0.15)': dependencies: '@types/json-schema': 7.0.15 @@ -7177,6 +7563,10 @@ snapshots: '@biomejs/cli-win32-x64@2.5.4': optional: true + '@braintree/sanitize-url@7.1.2': {} + + '@chevrotain/types@11.1.2': {} + '@colors/colors@1.5.0': optional: true @@ -8274,6 +8664,42 @@ snapshots: - uglify-js - webpack-cli + '@docusaurus/theme-mermaid@3.10.2(85eac7e6f4c099abe4e6a78ba3064efd)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.16))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.12)(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1)(typescript@5.9.3) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1) + '@docusaurus/theme-common': 3.10.2(93f20ff30a889a2d48291595daa93d2b) + '@docusaurus/types': 3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1) + mermaid: 11.16.0 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + tslib: 2.8.1 + transitivePeerDependencies: + - '@docusaurus/faster' + - '@docusaurus/plugin-content-docs' + - '@mdx-js/react' + - '@minify-html/node' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - bufferutil + - clean-css + - cssnano + - csso + - debug + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - supports-color + - typescript + - uglify-js + - utf-8-validate + - webpack-cli + '@docusaurus/theme-search-algolia@3.10.2(@algolia/client-search@5.55.1)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.15.43)(@swc/html@1.15.43)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@8.1.1))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.16))(@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7))(@rspack/core@1.7.12)(@swc/core@1.15.43)(@swc/html@1.15.43)(@types/react@19.2.17)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.16))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.32.0)(postcss@8.5.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(search-insights@2.17.3)(supports-color@8.1.1)(typescript@5.9.3)': dependencies: '@algolia/autocomplete-core': 1.19.9(@algolia/client-search@5.55.1)(algoliasearch@5.55.1)(search-insights@2.17.3) @@ -8482,6 +8908,14 @@ snapshots: react-dom: 19.2.7(react@19.2.7) react-hook-form: 7.81.0(react@19.2.7) + '@iconify/types@2.0.0': {} + + '@iconify/utils@3.1.4': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@iconify/types': 2.0.0 + import-meta-resolve: 4.2.0 + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.10 @@ -8684,6 +9118,10 @@ snapshots: '@types/react': 19.2.17 react: 19.2.7 + '@mermaid-js/parser@1.2.0': + dependencies: + '@chevrotain/types': 11.1.2 + '@module-federation/error-codes@0.22.0': {} '@module-federation/runtime-core@0.22.0': @@ -9265,6 +9703,123 @@ snapshots: dependencies: '@types/node': 26.1.0 + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.4': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -9289,6 +9844,8 @@ snapshots: '@types/qs': 6.15.1 '@types/serve-static': 1.15.10 + '@types/geojson@7946.0.16': {} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -9389,6 +9946,9 @@ snapshots: dependencies: '@types/node': 26.1.0 + '@types/trusted-types@2.0.7': + optional: true + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -9407,6 +9967,11 @@ snapshots: '@ungap/structured-clone@1.3.2': {} + '@upsetjs/venn.js@2.0.0': + optionalDependencies: + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + '@webassemblyjs/ast@1.14.1': dependencies: '@webassemblyjs/helper-numbers': 1.13.2 @@ -10016,6 +10581,14 @@ snapshots: core-util-is@1.0.3: {} + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 @@ -10178,6 +10751,192 @@ snapshots: csstype@3.2.3: {} + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.0): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.34.0 + + cytoscape-fcose@2.2.0(cytoscape@3.34.0): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.34.0 + + cytoscape@3.34.0: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.1.0 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.14: + dependencies: + d3: 7.9.0 + lodash-es: 4.18.1 + + dayjs@1.11.21: {} + debounce@1.2.1: {} debug@2.6.9(supports-color@8.1.1): @@ -10229,6 +10988,10 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + delaunator@5.1.0: + dependencies: + robust-predicates: 3.0.3 + depd@1.1.2: {} depd@2.0.0: {} @@ -10367,6 +11130,10 @@ snapshots: dependencies: domelementtype: 2.3.0 + dompurify@3.4.12: + optionalDependencies: + '@types/trusted-types': 2.0.7 + domutils@2.8.0: dependencies: dom-serializer: 1.4.1 @@ -10439,6 +11206,8 @@ snapshots: dependencies: es-errors: 1.3.0 + es-toolkit@1.49.0: {} + es6-promise@3.3.1: {} esast-util-from-estree@2.0.0: @@ -10789,6 +11558,8 @@ snapshots: dependencies: duplexer: 0.1.2 + hachure-fill@0.5.2: {} + handle-thing@2.0.1: {} has-flag@4.0.0: {} @@ -11058,6 +11829,8 @@ snapshots: import-lazy@4.0.0: {} + import-meta-resolve@4.2.0: {} + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -11077,6 +11850,10 @@ snapshots: inline-style-parser@0.2.7: {} + internmap@1.0.1: {} + + internmap@2.0.3: {} + interpret@1.4.0: {} invariant@2.2.4: @@ -11263,10 +12040,16 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + katex@0.16.47: + dependencies: + commander: 8.3.0 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + khroma@2.1.0: {} + kind-of@6.0.3: {} kleur@3.0.3: {} @@ -11280,6 +12063,10 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.9.0 + layout-base@1.0.2: {} + + layout-base@2.0.1: {} + leven@3.1.0: {} lightningcss-android-arm64@1.32.0: @@ -11349,6 +12136,8 @@ snapshots: dependencies: p-locate: 6.0.0 + lodash-es@4.18.1: {} + lodash.debounce@4.0.8: {} lodash.memoize@4.1.2: {} @@ -11381,6 +12170,8 @@ snapshots: markdown-table@3.0.4: {} + marked@16.4.2: {} + math-intrinsics@1.1.0: {} mdast-util-directive@3.1.0(supports-color@8.1.1): @@ -11600,6 +12391,30 @@ snapshots: merge2@1.4.1: {} + mermaid@11.16.0: + dependencies: + '@braintree/sanitize-url': 7.1.2 + '@iconify/utils': 3.1.4 + '@mermaid-js/parser': 1.2.0 + '@types/d3': 7.4.3 + '@upsetjs/venn.js': 2.0.0 + cytoscape: 3.34.0 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.0) + cytoscape-fcose: 2.2.0(cytoscape@3.34.0) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.14 + dayjs: 1.11.21 + dompurify: 3.4.12 + es-toolkit: 1.49.0 + katex: 0.16.47 + khroma: 2.1.0 + marked: 16.4.2 + roughjs: 4.6.6 + stylis: 4.4.0 + ts-dedent: 2.3.0 + uuid: 14.0.1 + methods@1.1.2: {} micromark-core-commonmark@2.0.3: @@ -12194,6 +13009,8 @@ snapshots: registry-url: 6.0.1 semver: 7.8.5 + package-manager-detector@1.7.0: {} + pako@2.2.0: {} param-case@3.0.4: @@ -12242,6 +13059,8 @@ snapshots: path-browserify@1.0.1: {} + path-data-parser@0.1.0: {} + path-exists@5.0.0: {} path-is-absolute@1.0.1: {} @@ -12285,6 +13104,13 @@ snapshots: pluralize@8.0.0: {} + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + postcss-attribute-case-insensitive@7.0.1(postcss@8.5.16): dependencies: postcss: 8.5.16 @@ -13157,6 +13983,15 @@ snapshots: reusify@1.1.0: {} + robust-predicates@3.0.3: {} + + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + rtlcss@4.3.0: dependencies: escalade: 3.2.0 @@ -13170,6 +14005,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rw@1.3.3: {} + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -13516,6 +14353,8 @@ snapshots: postcss: 8.5.16 postcss-selector-parser: 6.1.4 + stylis@4.4.0: {} + sucrase@3.35.1: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -13614,6 +14453,8 @@ snapshots: tiny-warning@1.0.3: {} + tinyexec@1.2.4: {} + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) @@ -13641,6 +14482,8 @@ snapshots: ts-algebra@1.2.2: {} + ts-dedent@2.3.0: {} + ts-interface-checker@0.1.13: {} tslib@1.14.1: {} @@ -13783,6 +14626,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@14.0.1: {} + uuid@8.3.2: {} validate.io-array@1.0.6: {} diff --git a/sidebars.ts b/sidebars.ts index 1e93955..7771c91 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -38,7 +38,19 @@ const sidebars: SidebarsConfig = { type: 'doc', id: 'extensions/index', }, - items: ['extensions/segments', 'extensions/legacy'], + items: [ + 'extensions/segments', + { + type: 'category', + label: 'Extension: deposit', + link: { + type: 'doc', + id: 'extensions/deposit/index', + }, + items: ['extensions/deposit/depositing', 'extensions/deposit/updating', 'extensions/deposit/lifecycle'], + }, + 'extensions/legacy', + ], }, { type: 'category',