Skip to content

Карта API Arkvory ​

Управление установленным кодом: GET/HEAD /api/v1/system/updates и POST /api/v1/system/updates/requests. Surface administration, глобальный administrator, команды check/configure/apply с revision и UUID. SDK: client.updates. Контракт, права и восстановление.

Резервные копии экземпляра (B2, ADR 0056): /api/v1/backup/*, surface administration, системные права backup.read/backup.manage (администратор учётных записей или файловый ключ владельца/bootstrap; ключи репозиториев — 403). Подробности — раздел 1a. Схема БД введена в 26; актуальная — 34 (SCHEMA_VERSION).

Области ответственности, уровни видимости, каталог операций текущего credential и SDK для удалённых клиентов реализованы: API_SURFACES. GET/HEAD /api/v1/operations — authenticated, контекст repository необязателен, pagination до 100, advisory conditions. GET/HEAD /api/v1/openapi.json?surface=… — документационное представление. Актуальная схема БД — 32.

Дата сверки: 2026-10-05, runtime со схемой 32. Это точка входа для интеграторов: реализованные маршруты ниже отделены от проектируемых расширений. Детальные JSON-схемы текущего сервера: GET /api/v1/openapi.json с действующим Bearer. OpenAPI сейчас 3.0.3; новую модель доступа описывает API_ACCESS, порядок внедрения — API_EVOLUTION.

Физическая очистка: GET/HEAD R/storage/cleanup (storage.read), PUT того же пути и POST R/storage/cleanup/run (storage.manage). Настройки с CAS, динамическая пауза, ограниченный проход и результат последнего выполнения: ONLINE_CLEANUP. Выполняется в фоне без остановки HTTP; 200 при запросе прохода не означает завершение удаления.

Обозначения и общие правила ​

R = /api/v1/repositories/{repository}. read, write, administrator — реальные сегодняшние проверки; own означает того же principal, не просто любой ключ с write. Пользовательская сессия также допустима. Администратор не обходит read/write. В таблице «целевое право» permissions репозиторных операций разделов 2–3 уже действуют для managed keys; глобальные identity/policy permissions пока проектные. Service administration выполняется file bootstrap либо делегатом с отдельными действиями на точные аккаунты, см. текущий контракт ключей. Несколько прав через + обязательны одновременно.

У reader доступны только GET/HEAD, кроме инфраструктурного CORS preflight; изменяющие методы получают 405 даже при наличии права. /console/ размещается только на writer. Автоматические HEAD у Fastify GET могут присутствовать; ниже перечислены контрактные методы, для bytes HEAD указан явно.

Сейчас размеры JSON — десятичные строки, revision — ограниченное целое; timestamps UTC. JSON body по умолчанию до 64 KiB (больше — 413), upload content передаётся отдельным бинарным stream. Ошибка native: {code,message,requestId} и необязательные reason, details, retryAfterSeconds (ошибки). Неизвестный путь — 404 до аутентификации, иной метод известного пути — 405 с Allow, неподдерживаемый тип тела — 415. Нет/неверный/истёкший credential — 401 с причиной; недостаточно права — 403; чужой upload/job скрывается 404; конфликт — 409; hash mismatch — 422; исчерпанная ёмкость и ENOSPC/EDQUOT — 507; busy/unavailable, включая потерю соединения с PostgreSQL и drain при остановке, — 503 с Retry-After; непредвиденная ошибка сервера — 500 internal без Retry-After, её нельзя повторять автоматически. Не считать любой POST безопасным для автоматического retry.

1. Система и identity — реализовано ​

Метод и путьТекущий доступРезультат / важное условиеЦелевое право
GET /health/liveБез ключа200, минимальная livenessПубличный минимум
GET /health/statusБез ключа200 ready / 503 unavailable, draining; без подробностей, вне бюджета запросовПубличный минимум для балансировщика
GET /health/readyЛюбой действующий ключ/сессия200/503, writable, role, агрегаты admission/bandwidth; вне бюджета запросовСовместимый прежний доступ; подробная диагностика отдельно system.observe
GET /health/metricsЛюбой действующий ключ/сессия200 Prometheus text 0.0.4; шаблон маршрута, метод, класс; вне бюджетаКак readiness; подробная диагностика отдельно system.observe
GET /api/v1/openapi.jsonЛюбой действующий ключ/сессияРабочая спецификацияАутентифицированный доступ
POST /api/v1/auth/loginБез предварительного ключа200, token/expiresAt/account; password gateУчётные данные пользователя
GET /api/v1/auth/meЛюбой действующий ключ/сессияID, administrator, точные repository grantsСвоя identity
POST /api/v1/auth/logoutДействующая авторизация204; отзыв текущей пользовательской сессии. Не отзывает file-based service keyСвоя сессия
POST /api/v1/auth/passwordПользовательская сессия204; currentPassword + newPassword, отзывает все сессии и PATСвоя учётная запись
POST /api/v1/auth/registerБез предварительного ключа201, сессия; при выключенной selfRegistration — 403, лимит по адресуПубличный минимум при включённой регистрации
POST /api/v1/feedbackЛюбой действующий ключ/сессия202, обращение авторам продукта; с serverLog — только администратор (ADR 0060)Свои учётные данные
GET /api/v1/feedback/attachmentsadministrator, не managed keyСерверный журнал и сводка установки, которые можно приложить к обращениюАдминистратор
GET /api/v1/auth/optionsБез ключа200, selfRegistrationПубличный минимум
GET / POST / DELETE /api/v1/auth/tokens[/{id}]Только сессия, не PATPAT: срок ≤ 365 дней, scope read/read-write, без administratorСвои учётные данные
GET / DELETE /api/v1/users/{id}/tokens[/{tokenId}]administrator, не PATСписок и отзыв PAT учётной записиidentity.manage
GET /api/v1/security/auditadministrator, не PATAppend-only журнал identity, курсор after, limit ≤ 100identity.read
GET /api/v1/usersadministratoritems, текущий предел 1000 пользователейidentity.read
POST /api/v1/usersadministrator201; name/password/administratoridentity.manage, с ограничением назначения полномочий
PATCH /api/v1/users/{id}administrator200; enabled и/или password; не изменение administratoridentity.manage
GET /api/v1/access-groupsadministratorГруппы с members/grants; до 100 группidentity.read
POST /api/v1/access-groupsadministrator201; nameidentity.manage
PUT / DELETE /api/v1/access-groups/{id}/members/{userId}administrator204; добавить/убрать membershipidentity.manage, membership не обходит delegation ceiling
PUT / DELETE /api/v1/access-groups/{id}/grants/{repository}administrator204; access read/write либо снять grantpolicy.manage + разрешение делегировать конкретные actions/resources

CORS: OPTIONS для /api/v1/* и /health/ready проверяет origin/method/headers без Bearer. Это не разрешение на саму операцию; см. EXTERNAL_UI. /console/ — статический клиент, не API управления.

1a. Резервные копии — реализовано ​

Команды выполняет агент arkvory-backup agent; API ставит задания в очередь и читает состояние из БД, не принимает и не возвращает путей. Права проверяются до разбора входа. Байты — десятичные строки, время — ISO UTC. SDK: client.backup; CLI: arkvoryctl backup.

Метод и путьПравоРезультат / условие
GET /api/v1/backup/statusbackup.readvault {configured,id,available,encrypted,freeBytes,totalBytes} (encrypted — boolean или null: неизвестно, агент старой версии или нет vault.json; ADR 0070), agent {online,lastSeenAt,version}, plan, lastCompleted, nextRunAt, running, warnings
GET /api/v1/backup/planbackup.read{enabled,hour,minute,timezone,retention{daily,weekly,monthly},revision}
PUT /api/v1/backup/planbackup.manageТело плана + expectedRevision; 200 план, 409 revision_mismatch, 400 validation с details (JSON Pointer)
POST /api/v1/backup/runsbackup.manageIdempotency-Key обязателен; 202 {id,kind:'capture',state}; повтор ключа — то же задание; 507 queue_full при 100 открытых
POST /api/v1/backup/points/{id}/verifybackup.manageIdempotency-Key; 202 {id,kind:'verify',state}, глубокая проверка; 404 для неизвестной точки; 409 idempotency_mismatch для ключа другой точки
POST /api/v1/backup/retention/applybackup.manageIdempotency-Key; 202 {id,kind:'retention',state}
GET /api/v1/backup/jobs?after&limitbackup.read{items: Job[], next}, новые первыми, limit 1–100 (50); Job {id,kind,state,phase,startedAt,finishedAt,errorCode,pointId,progress}
GET /api/v1/backup/points?after&limitbackup.read{items: Point[], next}, новейший T первым; Point {id,snapshotAt,completedAt,blobs,contentBytes,newBytes,tables,rows,pinned,verifiedAt,verifyDepth,…}
PUT /api/v1/backup/points/{id}/pinbackup.manage{pinned: boolean} → Point; 404 для неизвестной или забытой точки
GET /api/v1/backup/retention/previewbackup.read{keep: {id,reasons}[], delete: {id}[]}; reasons daily/weekly/monthly/pinned/newest; рекомендательный, apply решает заново по vault

state задания: queued|running|committing|completed|failed|interrupted; kind: capture|verify|retention. progress {bytesCopied,bytesTotal,blobsCopied,blobsTotal}: для копии — обработанные (скопированные или уже имевшиеся в vault) байты и объекты, для проверки — проверенные, для retention — удалённые blob и освобождённые байты. Коды предупреждений и уровни — CORE_RUNBOOK. GET также доступны как HEAD.

2. Загрузки, задания и байты — реализовано ​

Метод и путьТекущий доступКонтракт / повторЦелевое право
POST R/uploadswrite201, descriptor; Idempotency-Key обязателен, конфликт другого descriptorupload.create
GET R/uploads/{id}write + ownСостояние собственной сессииupload.read + own
DELETE R/uploads/{id}write + own200, отменяет pending; опубликованный объект не удаляетupload.cancel + own
PUT R/uploads/{id}/contentwrite + own200, целый octet-stream с проверкой размера/SHA и публикацией. После потери ответа сначала statusupload.write + upload.complete + own
GET R/uploads/{id}/partswrite + ownpartBytes и принятые parts; часть от 8 MiB, до 1 GiB при >10 000 частейupload.read + own
PUT R/uploads/{id}/parts/{index}write + own204; X-Content-SHA256, повтор той же части безопасен; другой hash — 409upload.write + own
POST R/uploads/{id}/completewrite + own200; повтор завершённой сессии возвращает опубликованный результатupload.complete + own
POST R/uploads/{id}/complete-asyncwrite + own202, durable job; публикация подтверждается отдельноupload.complete + own
GET /api/v1/jobs/{id}write в repo задания + ownqueued/running/completed/failed, attempts и errorCodejob.read + own
GET R/artifactsreaditems/next; limit 1–100, по умолчанию 50, afterartifact.list
GET R/artifacts/{id}readТолько available; descriptor, не bytesartifact.read
GET / HEAD R/artifacts/{id}/contentreadGET: 200/206/304/416, ETag, Range/If-Range. HEAD не передаёт body и игнорирует Rangecontent.read
GET / HEAD R/packages/content?group=…&name=…&version=…readТочная версия UPack; пустой group — корневая группа. Ответ как у artifacts/{id}/contentcontent.read
GET / HEAD R/packages/content?name=…&range=…&stage=…readВерсия по SemVer-диапазону и стадии, без них — старшая стабильная; правилаcontent.read
GET / HEAD R/asset/content?path=…readТекущая ревизия файла по пути, исходные bytes; ответ как у artifacts/{id}/contentcontent.read

packages/content (downloadPackageContent) и asset/content (downloadAssetContent) разрешают один неизменяемый артефакт на момент запроса и дальше используют тот же путь выдачи, что artifacts/{id}/content: ACL content.read без права перечислять пакеты/assets, admission, bandwidth, Range/ETag/If-Range. ETag относится к выбранному содержимому, поэтому If-Range после смены текущей ревизии или старшей версии не склеивает разные объекты. Аутентификация, как и у остальных операций, — Authorization: Bearer.

Upload owner привязан к principal. Долговечность сейчас — local filesystem + PostgreSQL; наличие маршрута resume не означает сохранность после потери диска/узла. Вся схема восстановления: TRANSFER_RECOVERY.

3. Каталог, metadata и ссылки — реализовано ​

Метод и путьТекущий доступКонтракт / границаЦелевое право
GET R/artifacts/{id}/annotationsreadrevision, labels, metadata, collectionsannotation.read
PUT R/artifacts/{id}/annotationsread + writeexpectedRevision + value; CAS, 409 при конфликтеannotation.write + artifact.read
POST R/artifacts/{id}/packageread + writeЧитает и валидирует исходный UPack; регистрирует неизменяемую идентичностьpackage.publish + artifact.read
GET R/packagesreadgroup/name, sort/direction/groupBy, after/limit; items/groups/nextpackage.read
GET R/assetsreadprefix; items, текущий предел 1000, полноценного cursor нетasset.read
GET / HEAD R/assets/pagereadprefix/after/limit; items/next, до 100; literal prefix и UTF-8 порядок, контрактasset.read
GET R/asset?path=…readТекущий path/revision/artifactIdasset.read
PUT R/assetread + writepath/artifactId/expectedRevision; 0 для создания, CASasset.write + artifact.read исходника
GET R/asset/history?path=…&before=…readДо 50 ревизий и nextasset.read
GET R/asset/revision?path=…&revision=…readТочная ревизия и artifactIdasset.read
POST R/asset/restoreread + writepath/sourceRevision/expectedRevision; создаёт новую revision, не меняет старый blobasset.restore + asset.read + artifact.read
GET R/searchreadq/label/collection/metadata*/after; до 100 items (size, даты, labels, stages) и nextartifact.list; metadata и collections не возвращаются — нужен annotation.read
GET R/audit?after=…writeДо 100 событий каталога; after — sequence, не аудит всех auth/download событийaudit.read
GET R/changes?after=…&limit=…readЛента изменений репозитория для зеркал: публикация, удаление, аннотации, пакеты, пути (detail — путь), стадии (detail — стадия); порядок commit, без авторов; items/head/next, до 100 (ADR 0058)artifact.list
GET R/mirrorreadСостояние зеркального репозитория этой установки: фаза, caughtUp, ошибка, объём; 404 для обычного (ADR 0058)repository.read
POST / DELETE R/artifacts/{id}/referencesread + write, reference owner204; JSON body key, ссылка принадлежит principalreference.write + artifact.read
GET R/artifacts/{id}/stagesreadТекущие стадии продвижения, до 16artifact.read
PUT / DELETE R/artifacts/{id}/stages/{s}read + writeИдемпотентно добавляет/снимает стадию с журналом; body {comment}artifact.promote + artifact.read
POST R/artifacts/{id}/promoteread (источник), write (цель){target, mode: copy|move, stages, comment}; 201 копия, 200 существующая; контрактисточник artifact.read + content.read, цель artifact.promote
GET R/artifacts/{id}/promotions, R/promotionsreadЖурнал стадий и переносов по sequence, after/limit до 100artifact.read / artifact.list
GET R/stages?stage=…&ids=…readАртефакты со стадией, cursor artifactId/stage; ids — до 100 artifact ID через запятуюartifact.list
GET R/packages/resolvereadname/group + version|range, stage, prerelease, order; версия, artifactId, SHA-256, стадииpackage.read
DELETE R/artifacts/{id}Только managed keyЛогическое удаление; body {expectedAnnotationRevision} обязателен, зависимости и CAS проверяются всегда; 200 не означает, что файл удалён физически (ARTIFACT_RETENTION)artifact.delete
GET R/artifacts/{id}/deletionТолько managed keyИнспекция опубликованного артефакта: блокирующие зависимости; без bytesartifact.delete
POST R/retention/previewТолько managed keyСтраница кандидатов по criteria/limit/after, без изменений; на reader 405artifact.delete
POST R/retention/applyТолько managed keyПовторно проверяет и обрабатывает только перечисленные IDs; результат по каждому объектуartifact.delete
GET / PUT R/storage/policyТолько managed keyКвоты и автоочистка; PUT с expectedRevision, CAS (STORAGE_POLICIES)storage.read / storage.manage
GET R/storage/usageТолько managed keyОпубликованные, незавершённые и ожидающие GC байтыstorage.read
GET R/storage/previewТолько managed keyДо 100 кандидатов сохранённой политики, hasMoreartifact.delete
POST R/storage/runТолько managed keyОдна порция включённой политики, body {expectedRevision}; на reader 405storage.manage + artifact.delete
GET R/storage/eventsТолько managed keyСобытия по возрастающему sequence, after, level, до 100diagnostics.read
POST R/artifacts/{id}/linksread (как content.read)201 {token, url, expiresAt}; body {} или {ttlSeconds} (60–86400, по умолчанию 3600); токен dtl_… только в этом ответе; ссылка не выдаёт ссылок (ADR 0062)content.read
PUT R/raw/{assetPath}read + writeНовая ревизия пути одним запросом (X-Checksum-Sha256, If-None-Match: *); 201 новая, 200 те же байты; 409 revision_mismatch; на reader 405 (ADR 0064)upload.*, asset.read + asset.write, artifact.read
GET / HEAD R/raw/{assetPath}readТекущая ревизия пути, Range, ETag, X-Arkvory-Artifact-Idcontent.read

Пустой group= выбирает корневую группу; отсутствие group — все группы. Cursor пакетов связан с параметрами запроса, страницы не образуют snapshot. SDK допускает package page и own permissions до 8 MiB; остальные JSON-ответы до 2 MiB. Эти различия сохраняются до отдельного совместимого изменения.

Отдельного CRUD для schemas, labels и collections пока нет: labels/collections — ограниченные поля annotations. Нет REST-управления репозиториями. Native удаление опубликованного содержимого есть, но только логическое и только для управляемого ключа с artifact.delete: DELETE R/artifacts/{id}, deletion и retention/* ниже; физическое освобождение места — storage/* (ARTIFACT_RETENTION, ONLINE_CLEANUP).

4. Сервисные API и дальнейшие расширения ​

Маршруты A/B ниже реализованы с уточнениями: создание аккаунтов и назначение делегирования требуют локального serviceAdministrator; управление существующими целями допускает отдельные admin actions в пределах ceiling. PATCH меняет только enabled; effective permissions не возвращает policy revision. GET /api/v1/service-accounts/{id}/audit требует bootstrap либо service-audit.read. Текущие контракты: ключи, делегирование и карта admin actions. В этапе C уже работают assets/page и список/карточки логических репозиториев; остальные строки C–E остаются проектом и не входят в рабочую OpenAPI.

ЭтапМетод / областьНазначение и право
AGET /api/v1/capabilitiesРазвёрнутые функции, gateway role, лимиты протокола; любой действующий credential. Не список чужих ресурсов.
AGET /api/v1/auth/permissionsСобственные effective bindings, profile, credentialId и serviceAdministration; клиентский UX, не замена серверному authorize.
BGET / POST /api/v1/service-accountsCursor-list: bootstrap или фильтр service-account.read; создание: только bootstrap.
BGET / PATCH /api/v1/service-accounts/{id}Карточка / enabled с expectedRevision: bootstrap либо service-account.read/manage. Policy меняется отдельным CAS-контрактом.
BGET / PUT /api/v1/service-accounts/{id}/policyBootstrap либо policy.read/manage; expectedRevision, точные bindings, ceiling для изменения.
BGET / POST /api/v1/service-accounts/{id}/keysMetadata list / выдача pending key: bootstrap либо credential.read/manage. Secret только в первом ответе POST.
BGET /api/v1/api-keys/{id}Метаданные без hash/secret: bootstrap либо credential.read.
BPOST /api/v1/api-keys/{id}/rotateНовый pending key, Idempotency-Key, прежние ограничения или сужение: bootstrap либо credential.manage + ceiling.
BPOST /api/v1/api-keys/{id}/revokeНеобратимый отзыв: bootstrap либо credential.manage + ceiling; повтор — 204.
BPOST /api/v1/auth/activate-keyДоказательство владения pending credential; 204, без выдачи дополнительных прав.
BGET /api/v1/api-keys/{id}/delegationsBootstrap либо владелец самого key; до 64 записей, включая tombstones.
BPUT / DELETE /api/v1/api-keys/{id}/delegations/{accountId}Только bootstrap, CAS expectedRevision; 200 grant/tombstone. PUT создания требует revision 0. Контракт.
CGET /api/v1/repositories и /{repository}Реализовано: собственные логические scopes, after/limit, карточка id/formats/permissions; managed repository.read, legacy собственные непустые grants. Настройки/создание не включены.
CПагинация каталогов (assets/page и accounts/keys уже работают)Bounded pages, согласованный cursor, фильтрация ACL до LIMIT; старый ответ assets не менять молча.
CPOST /api/v1/transfer-ticketsУзкий краткоживущий допуск к одному immutable объекту; право выдачи отдельно от content access. Контракт после проверки gateway audience/revoke.
DGET R/changes (реализовано, ADR 0058); webhooks (реализовано файлом оператора, ADR 0069); GET / POST R/webhooks — не реализованоCursor replay по ленте изменений; доставка webhook с подписью, повтором и защитой от SSRF. API подписок и event.read / webhook.manage остаются планом.
DКаталог schemas и типизированных metadataВерсионированные схемы, ограниченная сложность; собственная policy, без исполнения пользовательского кода.
EУправление retention / операции удаленияРеализованы explicit permission, preview, fixed-selection apply и защита ссылок/истории; scheduler и отдельный online GC реализованы: ONLINE_CLEANUP. Контракт.
EСтатус replicas / gateways / очередейsystem.observe; управление квотами — отдельный операторский контракт, не параметр произвольного клиента.

Реализованы raw-файлы по пути в /api/v1 (ADR 0064) и протоколы рядом с ним: реестр образов OCI (ADR 0063), Git LFS с блокировками (ADR 0065) и npm-реестр для Unity Package Manager (ADR 0066). OAuth/OIDC federation, S3/NuGet adapters — потенциальные отдельные интеграции, не обещание совместимости. Они добавляются только при конкретном сценарии и используют те же authorizer/storage use cases.

5. Рецепты для клиентов ​

КлиентРабочий маршрут сегодняЦелевая минимизация
CI/CDcreate upload → parts → complete или async job → register package / set assetPublisher в одном repo, короткий срок ключа, отдельные identities dev/prod
Агент развёртыванияpackages/content или asset/content (либо resolve → artifact content) + Range/ETagDownloader либо только content по закреплённому объекту; approved/channel policy отдельно
Индексатор / каталогpackages/search/annotationsCatalogReader без content.read
Редактор metadataannotations GET/PUT с expectedRevisionMetadataEditor без публикации и удаления
Внешняя браузерная консольlogin/me + native SDK, CORS exact originПользовательские сессии; machine secret не встроен в frontend
Мониторингauthenticated health/readyObserver, минимум информации для health, подробности отдельно
Интеграция по событиямЛента изменений GET R/changes (polling) и подписанный webhook из файла оператораAPI управления подписками; события identity отдельно

6. Как поддерживать карту ​

При добавлении операции обновлять use case, runtime-схему, OpenAPI, SDK, право/ресурс в карте, негативные ACL-тесты и описание retry. HTTP method не определяет permission: GET jobs сегодня требует write, PUT annotations — read+write. Нельзя заменить эти проверки одним middleware «GET = read».

Экспортируемая OpenAPI описывает все операции, включая HEAD, liveness и сам endpoint спецификации. Все имеют operationId, описание авторизации, retry и роли шлюза. Сервер при onReady и CI сверяют фактические маршруты со схемой; исключения ограничены точными static GET/HEAD. При сборке создаётся packages/contracts/dist/openapi.json. Правила и границы проверок: API_CONTRACT_GUARD, ADR 0018.

Discovery: GET/HEAD /api/v1/repositories возвращает items/next (до 100), GET/HEAD /api/v1/repositories/{repository} — собственную карточку или 404. Это projection прав, не глобальный реестр storage и не право читать bytes. Точные правила и SDK.

Ревизионные вложения сборки: GET/HEAD/PUT /api/v1/repositories/{repository}/artifacts/{id}/attachments и GET/HEAD /attachments/history. Метаданные и произвольные метки используют существующий annotations API. Права, SDK и сценарии.

Логическое удаление и retention preview/apply реализованы в ARTIFACT_RETENTION: managed-only artifact.delete, CAS аннотаций, пины истории и receipts. Миграции 13/14. Реестр/настройки/квоты репозиториев, SDK distribution, identity delegation/SSO и глобальное управление очередями остаются отдельными этапами.

Настройки хранения: GET/PUT repositories/{repository}/storage/policy, GET storage/usage, GET storage/preview, POST storage/run, GET storage/events. Surface catalog, права storage.read/manage, artifact.delete и diagnostics.read по операции. Контракт.

Поиск GET search: q — literal substring имени или значения актуальной metadata без учёта регистра; metadataKey + metadataValue — точная пара с учётом регистра, задаются вместе. Значение может быть пустой строкой. Фильтры объединяются через AND, доступ и cursor/100 сохраняются. SQL параметризован; regex/wildcards не поддерживаются. См. CLI. Элемент результата: id, name, size (десятичная строка), createdAt, publishedAt (null, если время публикации не записано), labels (текущие: из annotation, иначе из descriptor загрузки) и stages (текущие стадии продвижения в байтовом порядке, до 16). Страница и стадии читаются одним ограниченным запросом без N+1. Metadata и collections в ответ не входят: для них нужен annotation.read.

Arkvory · ProAnimaStudio