diff --git a/openapi.json b/openapi.json index 3e9b59b3..89904bca 100644 --- a/openapi.json +++ b/openapi.json @@ -3590,6 +3590,70 @@ ], "description": "An error response." }, + "TitledItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The item's ID." + }, + "type": { + "type": "string", + "description": "The item's type." + }, + "title": { + "type": "string", + "description": "The item's title as it is stored, which the caller can compare itself." + }, + "has_blob": { + "type": "boolean", + "description": "`true` if the item's `blob_ref` property holds a blob digest." + } + }, + "required": [ + "id", + "type", + "title", + "has_blob" + ], + "description": "An item whose title matches a name." + }, + "MissingRequiredFieldOrValidationErrorRefusal": { + "type": "object", + "properties": { + "error": { + "type": "object", + "properties": { + "code": { + "type": "string", + "enum": [ + "missing_required_field", + "validation_error" + ], + "description": "A machine-readable code for the error. Use it in your logic." + }, + "message": { + "type": "string", + "description": "A description of the error for a person to read. It can change, so don't match on it." + }, + "details": { + "type": "object", + "additionalProperties": {}, + "description": "More about the error, such as the field it concerns. Each code defines its own details." + } + }, + "required": [ + "code", + "message" + ], + "description": "What went wrong." + } + }, + "required": [ + "error" + ], + "description": "An error response." + }, "ExtensionsResponse": { "type": "object", "properties": { @@ -6856,42 +6920,6 @@ ], "description": "A run a connector reported, with its outcome and times." }, - "MissingRequiredFieldOrValidationErrorRefusal": { - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "code": { - "type": "string", - "enum": [ - "missing_required_field", - "validation_error" - ], - "description": "A machine-readable code for the error. Use it in your logic." - }, - "message": { - "type": "string", - "description": "A description of the error for a person to read. It can change, so don't match on it." - }, - "details": { - "type": "object", - "additionalProperties": {}, - "description": "More about the error, such as the field it concerns. Each code defines its own details." - } - }, - "required": [ - "code", - "message" - ], - "description": "What went wrong." - } - }, - "required": [ - "error" - ], - "description": "An error response." - }, "ConnectorPage": { "type": "object", "properties": { @@ -16118,6 +16146,385 @@ ] } }, + "/items/titles": { + "post": { + "operationId": "findItemsByTitle", + "tags": [ + "Items" + ], + "summary": "Find items by title", + "description": "Finds the active and archived items titled by each of up to 200 names, matched without regard to case, Unicode form or the white space around a name. `system.*` items and items you can't read are left out.", + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "maxLength": 1000 + }, + "maxItems": 200, + "description": "The titles to look for, at most 200, each at most 1000 UTF-16 code units. Case, Unicode form and surrounding white space do not matter." + } + }, + "required": [ + "names" + ], + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Returns one result for each name. A name matching nothing, or empty after trimming, has no items.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name, as the request sent it." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TitledItem" + }, + "description": "The active and archived items you can read whose title matches the name, by ID, at most 20." + }, + "more": { + "type": "boolean", + "description": "`true` if more than 20 items match and `items` holds the first 20." + } + }, + "required": [ + "name", + "items", + "more" + ] + }, + "description": "One result for each name, in the order the request named them." + } + }, + "required": [ + "results" + ] + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + } + }, + "400": { + "description": "- `missing_required_field`: `names` is missing.\n- `validation_error`: `names` is not a list of strings, has more than 200 names, has a name longer than 1,000 UTF-16 code units, or the body has a field this endpoint doesn't take.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MissingRequiredFieldOrValidationErrorRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "401": { + "description": "`unauthorized`: the request has no credential, or its credential is not valid.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "403": { + "description": "- `type_not_permitted`: your credential reaches no type. If it reaches some types, items of the others are left out instead.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TypeNotPermittedRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "409": { + "description": "`instance_changed`: `X-Marfa-Instance-Id` names another instance. Nothing is written. Rebuild the working copy from the instance at this address.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstanceChangedRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "413": { + "description": "`request_too_large`: the request body is larger than this instance accepts.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestTooLargeRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "429": { + "description": "`rate_limited`: you sent too many requests. Wait for the number of seconds in `Retry-After`, then try again.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitedRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + }, + "Retry-After": { + "$ref": "#/components/headers/Retry-After" + } + } + }, + "500": { + "description": "`internal_error`: Marfa failed in a way it didn't expect, and the request may not have completed. Read what you changed before you repeat a write.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InternalErrorRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "503": { + "description": "`write_contention`: the database was busy, and Marfa couldn't complete the request in time. Nothing changed. Try the request again.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WriteContentionRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + }, + "507": { + "description": "`insufficient_storage`: the disk that holds the instance's data has no room for the request, or the request would leave less free than the instance keeps in reserve. Nothing changed, unless `details.write_outcome` is `unknown`, which means the write may have landed: read what you changed before you repeat it. Free space on the disk, then try the request again.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsufficientStorageRefusal" + } + } + }, + "headers": { + "X-Marfa-Contract": { + "$ref": "#/components/headers/X-Marfa-Contract" + }, + "X-Request-ID": { + "$ref": "#/components/headers/X-Request-ID" + }, + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + }, + "X-Error-Code": { + "$ref": "#/components/headers/X-Error-Code" + } + } + } + }, + "parameters": [ + { + "name": "X-Marfa-Instance-Id", + "in": "header", + "required": false, + "schema": { + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + }, + "description": "The ID of the instance you expect, as `GET /` returns it. If another instance answers at this address, Marfa returns `409 instance_changed` and doesn't write. Leave it out to send the request to whichever instance answers." + } + ] + } + }, "/items/bulk-get": { "post": { "operationId": "bulkGetItems", @@ -62762,6 +63169,7 @@ "transitionItem", "listItemVersions", "lookupItems", + "findItemsByTitle", "bulkGetItems", "bulkUpsertItems", "getItemStats", diff --git a/src/generated/cli-commands.json b/src/generated/cli-commands.json index cdb9b73b..e372ed31 100644 --- a/src/generated/cli-commands.json +++ b/src/generated/cli-commands.json @@ -60,6 +60,7 @@ "items occurrences": {"options": [{"flag": "--from", "value": true}, {"flag": "--to", "value": true}, {"flag": "--type", "value": true}], "positional": true}, "items bulk": {"options": [{"flag": "--file", "value": true}, {"flag": "--mode", "value": true}, {"flag": "--atomic"}, {"flag": "--no-fanout"}, {"flag": "--retype"}], "positional": true}, "items bulk-get": {"options": [{"flag": "--include", "value": true}], "positional": true}, + "items titles": {"options": [], "positional": true}, "items lookup": {"options": [{"flag": "--type", "value": true}, {"flag": "--link", "value": true}, {"flag": "--source", "value": true}, {"flag": "--source-id", "value": true}, {"flag": "--id", "value": true}, {"flag": "--include", "value": true}], "positional": true}, "items tombstones": {"options": [{"flag": "--type", "value": true}, {"flag": "--link", "value": true}, {"flag": "--source", "value": true}, {"flag": "--source-id", "value": true}, {"flag": "--settled-at", "value": true}], "positional": true}, "items bulk-action": {"options": [], "subcommands": true}, diff --git a/src/generated/cli-download.md b/src/generated/cli-download.md index 9e4b3982..66863d4b 100644 --- a/src/generated/cli-download.md +++ b/src/generated/cli-download.md @@ -1,5 +1,5 @@ ```bash -curl -fsSL https://github.com/withmarfa/marfa/releases/download/v0.0.58/marfa-0.0.58-darwin-arm64.tar.gz | tar -xz +curl -fsSL https://github.com/withmarfa/marfa/releases/download/v0.0.59/marfa-0.0.59-darwin-arm64.tar.gz | tar -xz sudo mkdir -p /usr/local/bin sudo mv marfa /usr/local/bin/ marfa --version diff --git a/src/generated/contract-index.json b/src/generated/contract-index.json index f7e8614d..991a0431 100644 --- a/src/generated/contract-index.json +++ b/src/generated/contract-index.json @@ -2243,7 +2243,7 @@ "folders/same-name-scan-choice-other-paths-held": "1aec2c876514fd86", "folders/same-name-beside": "90f7ceccf939f5c3", "folders/case-rename-unsent": "fd42b7b53f11d981", - "folders/lookup-both-normalizations": "34316bce7aa17614", + "folders/lookup-any-normalization": "0914d2402bdd7691", "folders/state-not-admitted": "ddf02a5d0495d85e", "folders/watched-settings": "cad83752915116c1", "folders/binary-outside-search": "140ef8de25d23408", @@ -2390,14 +2390,19 @@ "folders/edge-new-namesake": "1fc829120595c80b", "folders/edge-lookup-waits": "935ce4cf00442a8e", "folders/edge-lookup-retries": "3258f336a40759ef", - "folders/edge-lookup-refused": "157f5b5cf3ec50ee", - "folders/edge-lookup-no-repeat": "3f3d43ae753797cb", + "folders/edge-lookup-refused": "010d491f0fd7d991", + "folders/edge-lookup-no-repeat": "61496bbc982f074f", + "folders/edge-lookup-call-refused": "8bc242215babe323", + "folders/edge-lookup-call-retried": "b6e9c385c95d6f3a", + "folders/edge-lookup-call-told": "f57ba0cfa8423430", "folders/create-before-links": "5f370a7297d1030e", "folders/edge-held-retried": "ed61780c666446ea", "folders/edge-held-quiet": "dbae757611e01639", "folders/edge-held-cleared": "5db9e3f4fb91d7cf", "folders/edge-held-never-guessed": "3d0ac849cf737986", - "folders/edge-lookup-page-limit": "2c0edc188e476605", + "folders/edge-lookup-list-limit": "78a426c68b280ab6", + "folders/lookup-batched": "e67e4e7b2e35fff3", + "folders/lookup-held-ambiguous": "4709ac946972ae2c", "folders/edge-lookup-states": "acb0f66c646dffb3", "folders/edge-lookup-title-field": "afe7334e4ade59aa", "folders/edge-line-removal": "1b8f8a8f8ec26542", @@ -3014,6 +3019,7 @@ "folders/push-placement-retry": "eac4b4a8407d3aae", "folders/push-placement-verdict": "12977dc546ec8e87", "folders/push-placement-withheld": "698b42a16663352a", + "folders/clears-recorded-answers": "b015cec0dceda860", "folders/conflict-file-report": "1bd00bedbe63f96e", "folders/conflict-copy-file": "64aae1ea027ce8c3", "folders/conflict-copy-pending": "a8cfb0a36bac0a61", @@ -3831,6 +3837,15 @@ "items/bulk-get-undeclared-key": "3d597d0ab55be58e", "items/bulk-get-metadata": "851660ba5a2a4f06", "items/bulk-get-system": "4359fc6be0d13b2e", + "items/titles": "a5efd3b963bc10e6", + "items/titles-fold": "61321ddba94be76d", + "items/titles-blank": "d54665443c0d8a20", + "items/titles-title": "ed49881c13031b38", + "items/titles-scope": "7faa124083284c6a", + "items/titles-no-type": "64dd9193ad75e64a", + "items/titles-limits": "d044daad1fbf7675", + "items/titles-long-title": "f1a1bfa9ee53d877", + "items/titles-list": "42679e7692fcc8ac", "items/update-merge": "8a1edc09e430b5f7", "items/update-replace": "1def2b6778ea3fbb", "items/update-replace-required": "209fb44525df3bf8", diff --git a/src/generated/marfa-release.json b/src/generated/marfa-release.json index b4c38acd..3bb6ed68 100644 --- a/src/generated/marfa-release.json +++ b/src/generated/marfa-release.json @@ -1 +1 @@ -{"version":"v0.0.58"} +{"version":"v0.0.59"} diff --git a/src/generated/server-image.md b/src/generated/server-image.md index d56db2e8..74d1080a 100644 --- a/src/generated/server-image.md +++ b/src/generated/server-image.md @@ -1,5 +1,5 @@ ```bash -docker pull ghcr.io/withmarfa/marfa-server:0.0.58 +docker pull ghcr.io/withmarfa/marfa-server:0.0.59 docker run --name marfa -d --restart unless-stopped -p 127.0.0.1:8600:8600 \ - -v marfa-data:/data --env-file marfa.env ghcr.io/withmarfa/marfa-server:0.0.58 + -v marfa-data:/data --env-file marfa.env ghcr.io/withmarfa/marfa-server:0.0.59 ```