API Контракты (v1)#
Source-of-truth спецификация:
docs/openapi.yaml
Runtime документация API:
/swagger(Swagger UI)/openapi.yaml(OpenAPI YAML)
Базовая дисциплина#
Префикс API:
/api/v1.Имена ресурсов:
kebab-case, множественное число (status-events,device-profiles).Поля JSON:
snake_case.Временные метки:
UTC, форматRFC3339.Контрактные заголовки:
X-Route-PathX-Route-ModuleX-Route-FilterX-Client-VersionX-Client-Build-Time
Канонические маршруты#
GET /api/v1/<resource>/list— выборка с фильтрацией, сортировкой, пагинацией.GET /api/v1/<resource>/scheme— схема/метаданные ресурса для UI.GET /api/v1/<resource>/{id}— получение одной сущности.POST /api/v1/<resource>— создание сущности/команды.PATCH /api/v1/<resource>/{id}— частичное изменение.DELETE /api/v1/<resource>/{id}— архивирование или удаление по политике ресурса.
Параметры list#
limit,offset,sort,order,qДополнительные фильтры по бизнес-атрибутам (
status,source,tenant_id, и т.д.)
Базовый успешный ответ list#
{
"items": [],
"offset": 0,
"limit": 20,
"total": 0,
"has_more": false,
"meta": {
"request_id": "req-20260304-001",
"timestamp": "2026-03-04T17:50:00Z"
}
}
Ответ по одной сущности#
{
"item": {},
"meta": {
"request_id": "req-20260304-002",
"timestamp": "2026-03-04T17:50:03Z"
}
}
Ошибка#
{
"error": {
"code": "validation_error",
"message": "Некорректное значение поля status",
"details": [{ "field": "status", "reason": "unsupported_value" }]
},
"meta": {
"request_id": "req-20260304-003",
"timestamp": "2026-03-04T17:50:05Z"
}
}
Рекомендуемые HTTP-статусы:
200/201/204, 400/401/403/404/409/422, 500.
Контракты текущего этапа#
GET /healthGET /api/v1/modules/listGET /api/v1/modules/schemeGET /api/v1/modules/database/listGET /api/v1/modules/permissions/listPOST /api/v1/modules/permissions/commands/updateGET /api/v1/modules/access-audit/scheme|listGET /api/v1/modules/site-policy/scheme|listPOST /api/v1/modules/site-policy/commands/setPOST /api/v1/modules/commands/installPOST /api/v1/modules/commands/uninstallGET /api/v1/status/listGET /api/v1/status/stream(WebSocket)GET /api/v1/alarms/scheme|listPOST /api/v1/alarms/commands/ackGET /api/v1/tasks/scheme|listPOST /api/v1/tasksGET /api/v1/tasks/{id}POST /api/v1/tasks/commands/transitionGET /api/v1/audit/scheme|listPOST /api/v1/audit/commands/logGET /api/v1/devices/telemetry/scheme|listGET /api/v1/devices/telemetry/kpiGET /api/v1/passkeys/schemeGET /api/v1/passkeys/listPOST /api/v1/passkeys/commands/issuePOST /api/v1/passkeys/commands/revokePOST /api/v1/auth/passkey/commands/startPOST /api/v1/auth/passkey/commands/completeGET /api/v1/auth/passkey/statusGET /api/v1/auth/mePOST /api/v1/auth/commands/logoutGET /api/v1/industry-profiles/scheme|listPOST /api/v1/industry-profiles/commands/importPOST /api/v1/poultry-profiles/commands/import-yamlPOST /api/v1/industry-profiles/commands/exportPOST /api/v1/poultry-profiles/commands/export-yamlPOST /api/v1/industry-profiles/commands/publishPOST /api/v1/poultry-profiles/commands/publishPOST /api/v1/industry-profiles/commands/rollbackPOST /api/v1/poultry-profiles/commands/rollbackGET /api/v1/industry-alarms/scheme|listPOST /api/v1/industry-alarms/commands/publishGET /api/v1/app/contextGET /api/v1/tables/scheme|listPOST /api/v1/tablesGET|PATCH|DELETE /api/v1/tables/{id}GET /api/v1/forms/scheme|listPOST /api/v1/formsGET|PATCH|DELETE /api/v1/forms/{id}GET /api/v1/tenant-master/scheme|listPOST /api/v1/tenant-master/commands/publishGET /api/v1/subscriptions/scheme|listPOST /api/v1/subscriptions/commands/set-statusGET /api/v1/sla-profiles/scheme|listPOST /api/v1/sla-profiles/commands/assignGET /api/v1/version-policies/scheme|listPOST /api/v1/version-policies/commands/setPOST /api/v1/version-policies/commands/checkGET /api/v1/analytics/metrics/scheme|listGET /api/v1/analytics/summaryGET /api/v1/tenant-master-sync/scheme|listPOST /api/v1/tenant-master-sync/commands/runPOST /api/v1/tenant-master-sync/commands/set-modeGET /api/v1/melioration-field/scheme|listGET /api/v1/melioration-alerts/scheme|listGET /api/v1/melioration-irrigation-machine/scheme|listGET /api/v1/melioration-irrigation-drip/scheme|listGET /api/v1/melioration-soil-moisture/scheme|listGET /api/v1/melioration-weather/scheme|listPOST /api/v1/melioration-irrigation-machine/commands/ingestPOST /api/v1/melioration-irrigation-drip/commands/ingestPOST /api/v1/melioration-soil-moisture/commands/ingestPOST /api/v1/melioration-weather/commands/ingestPOST /api/v1/melioration-weather/commands/telemetryGET /api/v1/melioration-control-mode/scheme|listPOST /api/v1/melioration-control-mode/commands/setPOST /api/v1/melioration-control-mode/commands/degradeGET /api/v1/poultry-climate/scheme|listPOST /api/v1/poultry-climate/commands/setpointPOST /api/v1/poultry-climate/commands/ackPOST /api/v1/poultry-climate/commands/telemetryPOST /api/v1/poultry-climate/sensors/commands/ingestGET /api/v1/poultry-flock/scheme|listGET /api/v1/poultry-feedwater/scheme|listPOST /api/v1/poultry-feedwater/commands/ingestGET /api/v1/poultry-production/scheme|listGET /api/v1/poultry-production/kpiGET /api/v1/poultry-alarms/scheme|listPOST /api/v1/poultry-alarms/commands/evaluatePOST /api/v1/poultry-alarms/commands/publishPOST /api/v1/poultry-alarms/commands/ackPOST /api/v1/poultry-alarms/commands/escalateGET /api/v1/swine-climate/scheme|listPOST /api/v1/swine-climate/commands/setpointPOST /api/v1/swine-climate/commands/telemetryPOST /api/v1/swine-climate/sensors/commands/ingestGET /api/v1/swine-feeding/scheme|listPOST /api/v1/swine-feeding/commands/ingestGET /api/v1/swine-water/scheme|listPOST /api/v1/swine-water/commands/ingestGET /api/v1/swine-production/scheme|listGET /api/v1/swine-production/kpiPOST /api/v1/swine-production/commands/ingestGET /api/v1/swine-biosecurity/scheme|listPOST /api/v1/swine-biosecurity/commands/ingestPOST /api/v1/swine-biosecurity/commands/ack
Тело /health:
{ "status": "ok", "layer": "master-cloud" }
Контракт app/context#
Маршрут:
GET /api/v1/app/context
Ключевые правила:
endpoint возвращает bootstrap-контекст runtime (
deployment_mode,industry_code,available_industries,tenant_id,site_id,feature_flags,user);поле
policyявляется source-of-truth для UI/API guard-слоя и содержит:scope_type,role,effective_tenant_id;permissions.uiиpermissions.api(lookupid -> allowed);capabilities(агрегированные флаги операций UI, включаяswitch_industry,sidebar_menu,sidebar_menu_update,module_install,module_permissions,master_*,tenant_*);guards(master_scope,tenant_scope,allow_industry_switch);
feature_flagsиpolicy.capabilitiesприменяются совместно: при запрете capability UI должен блокировать операцию даже при наличии локального fallback по правам.
Контракт CRUD ресурсов (tables/forms)#
Маршруты:
GET /api/v1/tables/schemeGET /api/v1/tables/listPOST /api/v1/tablesGET /api/v1/tables/{id}PATCH /api/v1/tables/{id}DELETE /api/v1/tables/{id}GET /api/v1/forms/schemeGET /api/v1/forms/listPOST /api/v1/formsGET /api/v1/forms/{id}PATCH /api/v1/forms/{id}DELETE /api/v1/forms/{id}
Ключевые правила:
POSTиPATCHпринимают объект в полеitemи возвращают стандартныйitemenvelope;для
listподдерживаютсяlimit,offset,q;при создании
idможет быть сгенерирован автоматически;системные поля
created_at,updated_at,resourceвыставляются runtime;коды ошибок:
validation_error(400),not_found(404),already_exists(409).
Контракт tenant-master exchange#
Маршруты:
GET /api/v1/tenant-master/schemeGET /api/v1/tenant-master/listPOST /api/v1/tenant-master/commands/publish
Ключевые правила:
контур принимает только whitelisted служебные события (
event_type) и статусы (status);обязательные поля publish:
tenant_id,event_type,status;поддерживаются фильтры списка:
tenant_id,event_type,status,limit,offset;события хранят
correlation_idиpayloadдля сквозной трассировки обмена;коды ошибок whitelist:
event_not_whitelisted(409),status_not_whitelisted(409).
Контракт subscriptions + sla-profiles (master)#
Маршруты:
GET /api/v1/subscriptions/schemeGET /api/v1/subscriptions/listPOST /api/v1/subscriptions/commands/set-statusGET /api/v1/sla-profiles/schemeGET /api/v1/sla-profiles/listPOST /api/v1/sla-profiles/commands/assign
Ключевые правила:
контур поддерживает жизненный цикл подписки (
trial|active|paused|canceled);set-statusизменяет состояние подписки и фиксируетupdated_at;sla-profilesсодержит параметры SLA (response_minutes,resolution_minutes,escalation_policy);assignсвязывает подписку с активным SLA-профилем;фильтры списка подписок:
tenant_id,status,sla_profile_id,q,limit,offset.
Контракт version-policies (master)#
Маршруты:
GET /api/v1/version-policies/schemeGET /api/v1/version-policies/listPOST /api/v1/version-policies/commands/setPOST /api/v1/version-policies/commands/check
Ключевые правила:
policy-слой задает ограничения версии модуля (
allowed_major,min_version,max_version,pinned_version);поддерживаются scope:
global,industry,tenant;setсоздает/обновляет policy поid;checkвалидирует версии установленных модулей и возвращает список нарушений (violations).
Контракт central analytics#
Маршруты:
GET /api/v1/analytics/metrics/schemeGET /api/v1/analytics/metrics/listGET /api/v1/analytics/summary
Ключевые правила:
metrics/listпредоставляет агрегированные метрики master-контура поtenant/industry/window;поддерживаются фильтры:
tenant_id,industry_code,metric,window,q,limit,offset;summaryвозвращает укрупненные показатели (tenants_count,industries_count,average_uptime_percent,average_latency_ms,open_alarms_total,open_tasks_total).
Контракт tenant-master-sync#
Маршруты:
GET /api/v1/tenant-master-sync/schemeGET /api/v1/tenant-master-sync/listPOST /api/v1/tenant-master-sync/commands/runPOST /api/v1/tenant-master-sync/commands/set-mode
Ключевые правила:
модуль управляет состоянием синхронизации tenant -> master по каждому
tenant_id;статусы:
live,degraded,stopped;режимы:
auto,manual,paused;runзапускает принудительную синхронизацию tenant и сбрасывает lag/pending;set-modeпереключает рабочий режим синхронизации.
Контракт alarms (tenant/master)#
Маршруты:
GET /api/v1/alarms/schemeGET /api/v1/alarms/listPOST /api/v1/alarms/commands/ack
Ключевые правила:
единый контур тревог для master/tenant с состояниями
open|acknowledged;поддерживаются фильтры списка:
q,severity,state,scope,limit,offset;подтверждение тревоги выполняется через
ackс полямиid,acknowledged_by,comment;ошибка отсутствующей тревоги:
alarm_not_found(404);при деинсталляции модуля возвращается
module_not_installed(404).
Контракт tasks lifecycle#
Маршруты:
GET /api/v1/tasks/schemeGET /api/v1/tasks/listPOST /api/v1/tasksGET /api/v1/tasks/{id}POST /api/v1/tasks/commands/transition
Ключевые правила:
состояния жизненного цикла:
planned,in_progress,blocked,done,canceled;поддерживаются фильтры списка:
q,state,scope,assignee,limit,offset;переходы выполняются через
transitionи валидируются по lifecycle policy;недопустимый переход возвращает
lifecycle_conflict(409);для каждой задачи хранится история переходов (
from_state,to_state,changed_by,changed_at,comment).
Контракт audit trail#
Маршруты:
GET /api/v1/audit/schemeGET /api/v1/audit/listPOST /api/v1/audit/commands/log
Ключевые правила:
auditхранит историю действий и системных операций (actor,action,resource,result);поддерживаются фильтры списка:
q,actor,action,resource,result,limit,offset;запись события выполняется через
logc payloadactor/action/resource/result/correlation_id/details;поддерживаются результаты:
success,denied,error;история хранится в хронологическом порядке (новые записи сверху).
Контракт devices/telemetry#
Маршруты:
GET /api/v1/devices/telemetry/schemeGET /api/v1/devices/telemetry/listGET /api/v1/devices/telemetry/kpi
Ключевые правила:
listвозвращает точки телеметрии устройств с фильтрами;поддерживаются фильтры:
q,device_id,site_id,status,metric,limit,offset;kpiвозвращает агрегаты по устройствам (online/warn/error, total points, average latency);KPI рассчитываются по последнему известному состоянию каждого устройства в текущем фильтре.
Контракт ingest для melioration (MVP)#
POST /api/v1/melioration-irrigation-machine/commands/ingestPOST /api/v1/melioration-irrigation-drip/commands/ingestPOST /api/v1/melioration-soil-moisture/commands/ingestPOST /api/v1/melioration-weather/commands/ingestPOST /api/v1/melioration-weather/commands/telemetry
Ключевые правила:
ingest endpoint-ы принимают
item-данные в request body и возвращают стандартныйitemenvelope;для irrigation событий поддерживаются обе единицы (
mmprimary,m3derived);для
weatherдействует D-008 policy:station primary,service fallbackприtelemetry_healthy=false.weather/telemetryподдерживаетfallback_mode(A|B) и приhealthy=falseавтоматически деградируетcontrol_modeизCв fallback (auto_degraded=true)./api/v1/melioration-alerts/listрассчитываетwater_deficit|overwateringпо связке soil + weather + irrigation.
Контракт poultry-climate (MVP, phase-1)#
Маршруты:
GET /api/v1/poultry-climate/schemeGET /api/v1/poultry-climate/listPOST /api/v1/poultry-climate/commands/setpointPOST /api/v1/poultry-climate/commands/ackPOST /api/v1/poultry-climate/commands/telemetryPOST /api/v1/poultry-climate/sensors/commands/ingest
Ключевые правила:
listвозвращает климат-профили по house/batch/age-phase;поддерживаются фильтры
q,house_id,batch_id,age_phase_id,subtype,state,current_age_days,age_mode,limit,offset;в ответе присутствует модель версий профиля (
version_id,state,change_note,rollback_of).setpointприменяет уставки к выбранному профилю (profile_idили селектор house+batch+age_phase), повышаетversion_idи переводит профиль вdraft;ackподтверждает профиль оператором и переводит его вpublished.setpointвозвращаетadapter_dispatchдля климат-контроллера (adapter_profile_id,controller_id,transport,status).telemetryпринимает измерения адаптера (temp/humidity/co2/nh3/ventilation), сопоставляет с активным профилем и возвращаетstatus+out_of_norm_flags.sensors/ingestпринимает показания датчиков среды (temperature|humidity|pressure|co2|nh3) и нормализует их в общий telemetry-контур climate.при передаче
current_age_daysсписок вычисляет активную age-phase (active_by_age=true), а в режимеage_mode=activeвозвращает только текущий профиль фазы.
Контракт poultry-flock (MVP, phase-1)#
Маршруты:
GET /api/v1/poultry-flock/schemeGET /api/v1/poultry-flock/list
Ключевые правила:
listвозвращает партии выращивания по птичникам;поддерживаются фильтры
q,house_id,batch_id,subtype,status,limit,offset;в ответе присутствуют поля жизненного цикла партии (
start_date,planned_close_date,current_age_days,status).
Контракт poultry-feedwater (MVP, phase-1)#
Маршруты:
GET /api/v1/poultry-feedwater/schemeGET /api/v1/poultry-feedwater/listPOST /api/v1/poultry-feedwater/commands/ingest
Ключевые правила:
listвозвращает объединенный профиль кормления/водопотребления на age phase;поддерживаются фильтры
q,house_id,batch_id,age_phase_id,subtype,status,state,limit,offset;в ответе присутствует модель версий профиля (
version_id,state,change_note,rollback_of) и пороги аномалий расхода воды.ingestпринимает feed/water counters (+ pressure), рассчитывает отклонения и возвращаетstatus=ok|warn|alarmсanomaly_flags.ingestобновляет operational поля профиля (operational_status,last_*,*_deviation_pct,last_counter_at) для runtime-мониторинга.
Контракт poultry-production (MVP, phase-1)#
Маршруты:
GET /api/v1/poultry-production/schemeGET /api/v1/poultry-production/listGET /api/v1/poultry-production/kpi
Ключевые правила:
listвозвращает производственные KPI по house/batch/date;поддерживаются фильтры
q,house_id,batch_id,subtype,metric_date,limit,offset;в ответе доступны эксплуатационные отклонения (
out_of_norm_flags) и KPI для broiler/layer.kpiрассчитывает агрегированные отраслевые показатели по окну (window_days) дляbroiler/layer.
Контракт poultry-alarms (MVP, phase-1)#
Маршруты:
GET /api/v1/poultry-alarms/schemeGET /api/v1/poultry-alarms/listPOST /api/v1/poultry-alarms/commands/evaluatePOST /api/v1/poultry-alarms/commands/publishPOST /api/v1/poultry-alarms/commands/ackPOST /api/v1/poultry-alarms/commands/escalate
Ключевые правила:
listвозвращает отраслевые тревоги poultry с обязательнымcorrelation_id;поддерживаются фильтры
q,house_id,batch_id,severity,priority,status,correlation_id,limit,offset;структура события совпадает с
poultry_alarm_eventи готова к bridge вstatus.publishсоздает событие сstatus=activeи автоматически генерируетcorrelation_id, если не передан;ackподтверждает событие поid, выставляетstatus=acked,acked_at,assignee.для
severity=critical|highpoultry alarm-bus публикует bridge-событие вstatusс тем жеcorrelation_id(bridged_to_status=true).в
status/listbridged-событие хранитcorrelation_idдля сквозной трассировки poultry alarm -> status.evaluateзапускает rule-engine по телеметрии (temp/co2/ventilation/feed-water deviations) и создает события с приоритетами (P1/P2) согласно правилу.для каждого события рассчитывается SLA (
sla_target_sec,sla_deadline_at), аescalateпомечаетsla_breached=trueи повышаетescalation_levelпри нарушении SLA.
Контракт profile-service (D-003)#
Маршруты:
GET /api/v1/industry-profiles/schemeGET /api/v1/industry-profiles/listPOST /api/v1/industry-profiles/commands/importPOST /api/v1/poultry-profiles/commands/import-yamlPOST /api/v1/industry-profiles/commands/exportPOST /api/v1/poultry-profiles/commands/export-yamlPOST /api/v1/industry-profiles/commands/publishPOST /api/v1/poultry-profiles/commands/publishPOST /api/v1/industry-profiles/commands/rollbackPOST /api/v1/poultry-profiles/commands/rollback
Ключевые правила:
перенос нормативов между хозяйствами через YAML (
export/import);версионирование профилей (
draft/published/archived);rollback на выбранную версию с аудитом действий;
совместимость import-профиля проверяется по
industry_codeиequipment_profile.poultry-profiles/import-yamlпринимает только профили сindustry_code=poultry.poultry-profiles/export-yamlэкспортирует толькоindustry_code=poultryи возвращает conflict при попытке экспорта профиля другой отрасли.poultry-profiles/publishпубликует только poultry-профили и выполняет ту же модель версионирования (draft -> published, предыдущая published -> archived).poultry-profiles/rollbackвыполняет откат только для poultry-профилей и публикует указанную версию как активную.
Контракт industry alarm-bus (D-004)#
Маршруты:
GET /api/v1/industry-alarms/schemeGET /api/v1/industry-alarms/listPOST /api/v1/industry-alarms/commands/publish
Ключевые правила:
отраслевые тревоги публикуются в отдельный контур
industry-alarms;изоляционные ключи
tenant_id,industry_code,site_idпередаются в отраслевых событиях и поддерживаются в фильтрах списка;bridge в
statusвыполняется дляseverity=critical|high;mapping в
status:critical|high -> error,medium -> warn,low|info -> ok;для сквозной трассировки в обеих системах передается
correlation_id.
Контракт модульного реестра#
GET /api/v1/modules/list возвращает список модулей с четырьмя контурами:
frontend:block_id,component;backend:routes.database:migrations,tables.permissions:rules(role,resource,actions).отраслевые метаданные:
industry_code,industry_scope,key_entity,provides_enrichment_for.поле
versionдля отраслевых модулей следует политикеMAJOR.MINOR.PATCH; в рамках одной отрасли активная major-линия должна быть единой.
Пример элемента:
{
"id": "status",
"name": "Status Stream",
"description": "Поток статусов оборудования и событий в реальном времени",
"version": "0.1.0",
"core": false,
"installed": true,
"dependencies": [],
"frontend": {
"block_id": "status",
"component": "status-table"
},
"backend": {
"routes": ["/api/v1/status/list", "/api/v1/status/stream"]
},
"database": {
"migrations": ["20260304_20_create_status_events"],
"tables": [
{
"name": "status_events",
"primary_key": "id",
"columns": ["id", "source", "event", "status", "timestamp"]
}
]
},
"permissions": {
"rules": [
{
"role": "operator",
"resource": "status",
"actions": ["read", "stream"]
}
]
}
}
Контракт cross-industry access audit#
Маршруты:
GET /api/v1/modules/access-audit/schemeGET /api/v1/modules/access-audit/list
Ключевые правила:
фиксируются решения отраслевых policy-check при
modules/permissions/commands/updateиmodules/commands/install;событие содержит:
operation,decision(allow|deny),reason,module_id,requested_industry_code,module_industry_code,actor,timestamp;хранение в runtime ограничено последними
200событиями (in-memory, порядокdesc);фильтры списка:
module_id,decision,requested_industry_code,module_industry_code.
Контракт модели БД по модулям#
GET /api/v1/modules/database/list возвращает модель БД модулей.
Параметры:
installed_only(true|false, по умолчаниюtrue) — только установленные модули или полный каталог.industry_code(опционально) — фильтрация permission-модели по отраслевой области доступа.site_id(опционально) — фильтрация permission-модели с учетом site-policy (частичная активация модулей на площадке).industry_code(опционально) — фильтрация permission-модели по отраслевой области доступа.
Элемент списка:
{
"module_id": "tasks",
"module_name": "Tasks",
"installed": true,
"migrations": ["20260305_20_create_tasks_lifecycle"],
"tables": [
{
"name": "tasks",
"primary_key": "id",
"columns": ["id", "title", "priority", "status", "sla_minutes", "created_at"]
}
]
}
Контракт модели прав по модулям#
GET /api/v1/modules/permissions/list возвращает роль-ресурсные правила модулей.
Параметры:
installed_only(true|false, по умолчаниюtrue) — только установленные модули или полный каталог.
Элемент списка:
{
"module_id": "tasks",
"module_name": "Tasks",
"installed": true,
"rules": [
{
"role": "operator",
"resource": "tasks",
"actions": ["read", "create", "transition"]
}
]
}
POST /api/v1/modules/permissions/commands/update обновляет правила конкретного модуля.
Тело запроса:
{
"id": "status",
"industry_code": "melioration",
"rules": [
{ "role": "operator", "resource": "status", "actions": ["read"] },
{ "role": "admin", "resource": "status", "actions": ["read", "stream", "update"] }
]
}
Если industry_code задан, update разрешается только для модулей, доступных в рамках выбранной отрасли; при нарушении возвращается industry_policy_conflict.
Контракт установки/деинсталляции#
Тело запроса:
{ "id": "mqtt" }
Ошибки модульного API:
module_not_foundmodule_already_installedmodule_not_installedmodule_is_coremodule_dependency_missingmodule_has_dependentsindustry_policy_conflict
Контракт site-policy (частичная активация модулей)#
Маршруты:
GET /api/v1/modules/site-policy/schemeGET /api/v1/modules/site-policy/listPOST /api/v1/modules/site-policy/commands/set
Параметры site-policy/list:
site_id(обязательно)limit,offset
Тело site-policy/set:
{
"site_id": "site-a",
"module_id": "melioration-field",
"enabled": false
}
Правило:
modules/list,modules/database/list,modules/permissions/listподдерживают фильтрsite_idи исключают модули, отключенные policy для этой площадки.Source-of-truth для policy хранится в shared SQL persistence, а runtime in-memory map используется только как process cache.
Контракт Passkey (QR/RFID)#
Маршруты:
GET /api/v1/passkeys/schemeGET /api/v1/passkeys/listPOST /api/v1/passkeys/commands/issuePOST /api/v1/passkeys/commands/revoke
Параметры passkeys/list:
limit,offset,sort,order,qtype(qr|rfid)status(active|revoked)
Поддерживаемые поля сортировки:
id,type,holder,scope,status,issued_at,expires_at
Пример элемента passkeys/list:
{
"id": "PK-QR-1001",
"type": "qr",
"holder": "Оператор смены",
"scope": "Gate-A",
"status": "active",
"issued_at": "2026-03-04T14:00:00Z",
"expires_at": "2036-03-05T14:00:00Z",
"last_used_at": "2026-03-04T15:35:00Z"
}
Тело passkeys/commands/issue:
{
"type": "rfid",
"holder": "Test User",
"scope": "Gate-B",
"ttl_minutes": 60
}
Тело passkeys/commands/revoke:
{ "id": "PK-QR-1001" }
Если модуль passkey деинсталлирован, API возвращает 404 module_not_installed.
Контракт аутентификации Passkey#
Маршруты:
POST /api/v1/auth/passkey/commands/startPOST /api/v1/auth/passkey/commands/completeGET /api/v1/auth/passkey/statusGET /api/v1/auth/mePOST /api/v1/auth/commands/logoutGET /api/v1/auth/permissions/schemeGET /api/v1/auth/permissions/listGET /api/v1/auth/ui-access/listPOST /api/v1/auth/ui-access/commands/updateGET /api/v1/auth/ui-preferences/listPOST /api/v1/auth/ui-preferences/commands/updateGET /api/v1/auth/shell-profile/listPOST /api/v1/auth/shell-profile/commands/exportPOST /api/v1/auth/shell-profile/commands/importPOST /api/v1/auth/shell-profile/commands/rollbackGET /api/v1/auth/security-log/scheme
Практический канон для iP-1510:
локальный
L1path:RFID -> local auth bridge -> local sessionphone-assisted path:
QR challenge/responseBLEне считается обязательным transport contract и допустим только как ускорительдля
iPhone/Safariобязателен fallbackQR -> 4-digit codebackend обязан фильтровать module projection по grants до рендера UI, а не только скрывать элементы на frontend
GET /api/v1/auth/security-log/list
Тело auth/passkey/start:
{ "method": "qr" }
Ответ:
challenge_id,method,status,expires_atдля
method=qrдополнительноqr_payload
Тело auth/passkey/complete:
{
"challenge_id": "CH-...",
"credential": "PK-QR-1001"
}
credential может быть как id ключа (PK-*), так и внутренним credential (QR-*/RF-*).
POST /api/v1/auth/passkey/commands/complete:
по успешному завершению выставляет HttpOnly cookie
ioot_sessionс JWT (HMAC-SHA256).JWT также может передаваться через
Authorization: Bearer <token>.
GET /api/v1/auth/me:
возвращает
authenticated=trueиuserпри валидном JWT;возвращает
authenticated=false, если токен отсутствует/невалиден.userвключает:role,scope,scope_type,tenant_id(для tenant-scope).
GET /api/v1/auth/permissions/list:
возвращает объединенную матрицу
api+uiопераций с расчетным флагомallowed;поддерживает фильтры:
layer=api|ui;allowed=true|false.
GET /api/v1/auth/ui-access/list:
возвращает role/action правила для UI-shell ресурса;
текущий runtime-ресурс:
ui.sidebar.menu;idможно передать query-параметром, по умолчанию используетсяui.sidebar.menu.backend source-of-truth хранится в shared SQL persistence.
POST /api/v1/auth/ui-access/commands/update:
обновляет правила UI-access для shell-ресурса;
используется для доступа к burger-меню и прав на его редактирование;
допустимые
actionsтекущего runtime:read,update.
GET /api/v1/auth/ui-preferences/list:
возвращает пользовательские shell-настройки для текущего контекста
tenant/site/industry;читает
theme,dashboard_layout,quick_module_idsс флагами наличияhas_*;при отсутствии сохраненных значений frontend использует локальный fallback.
backend source-of-truth хранится в shared SQL persistence.
POST /api/v1/auth/ui-preferences/commands/update:
сохраняет пользовательские shell-настройки для текущего контекста;
доступен всем аутентифицированным ролям как self-service ресурс;
текущий payload включает
theme,dashboard_layout,quick_module_ids,industry_code,site_id;при каждом обновлении пишет versioned snapshot в
shell-profileдля текущегоtenant/site/industry.
GET /api/v1/auth/shell-profile/list:
возвращает историю versioned shell-profile для текущего
tenantс optional фильтрамиsite_id,industry_code;запись включает
current_version,versions[],audit[],updated_at.backend source-of-truth хранится в shared SQL persistence; legacy JSON sidecars допустимы только как bootstrap import path.
POST /api/v1/auth/shell-profile/commands/export:
экспортирует текущий shell-profile snapshot в JSON payload со
schema_version=v1;поддерживает выбор конкретной
version; если история еще не создана, экспортирует live-снимок изui-preferences+ui-access.
POST /api/v1/auth/shell-profile/commands/import:
импортирует shell-profile snapshot в выбранный
site_id/industry_code;payload включает
theme,dashboard_layout,quick_module_ids,ui_access;применяет snapshot к
ui-preferencesиui-access, затем создает новую версию с audit entry.
POST /api/v1/auth/shell-profile/commands/rollback:
откатывает shell-profile к выбранной
to_version;повторно применяет сохраненный snapshot и пишет новую версию с
rollback_of=<to_version>;доступен только
admin, так как изменяет общие UI access rules.
GET /api/v1/auth/security-log/list:
возвращает security-журнал по событиям
auth/action(allow|deny) с route-контекстом;поддерживает фильтры
category,result,event,method,path,tenant_id;доступен только ролям
admin|security(иначе403 rbac_forbidden).
Защита API#
Все маршруты
/api/*защищены middleware, кроме публичных auth-маршрутов:POST /api/v1/auth/passkey/commands/startPOST /api/v1/auth/passkey/commands/completeGET /api/v1/auth/passkey/statusGET /api/v1/auth/mePOST /api/v1/auth/commands/logout
При отсутствии валидного JWT возвращается:
{
"error": {
"code": "auth_required",
"message": "Требуется вход в приложение"
}
}
RBAC и scope-гварды применяются на уровне middleware:
masterendpoint-группы (tenant-master*,subscriptions/sla,version-policies,analytics) требуютscope_type=master;tenantendpoint-группы (industry-*,melioration-*,poultry-*,swine-*) требуютscope_type=tenant;для tenant scope включена boundary-проверка
tenant_id/target_tenant_idв query и JSON body;при нарушении границ возвращаются
403с кодамиscope_boundary_denied/tenant_boundary_denied/rbac_forbidden.
Pilot process composition (runtime facts)#
Существующие API-контракты используются process-утилитами reference runtime без введения новых endpoint-ов:
scripts/pilot-bootstrap.pyиспользуетGET /api/v1/app/context,GET /api/v1/modules/list,GET /api/v1/modules/site-policy/list,POST /api/v1/auth/shell-profile/commands/export,POST /api/v1/auth/shell-profile/commands/import,POST /api/v1/modules/commands/install,POST /api/v1/modules/commands/uninstall,POST /api/v1/modules/site-policy/commands/set;scripts/pilot-evidence-bundle.pyиспользуетGET /api/v1/app/context,GET /ready,GET /api/v1/modules/list,GET /api/v1/modules/site-policy/list,POST /api/v1/auth/shell-profile/commands/export,GET /api/v1/auth/security-log/list;scripts/pilot-rollback-drill.pyоркестрирует baseline export/apply/evidence/restore поверх двух контуров выше.
Синхронизация с ../green-robot#
При дальнейшем развитии:
modules/schemeдолжен возвращатьdisplay_module,show_filters,module_view,catalog_enrichment(sidebar_fields,infobar_fields).Shell должен поддерживать отдельный UI-access ресурс
ui.sidebar.menuдля role-gated burger-меню и конфигурации быстрых fullscreen-кнопок.Shell persistence должен поддерживать backend-хранение
theme,dashboard_layout,quick_module_idsс изоляцией поtenant/site/industryи локальным fallback.Shell должен поддерживать versioned export/import/rollback profile для
theme,dashboard_layout,quick_module_ids,ui-access, а также pilot preset-артефактыcloud-multiиedge-single.Ввести единый envelope ответа со
metaдля всех новых list/get endpointов.Применять
kebab-caseимена ресурсов и idempotency для критичных POST-операций.