- session: set_tenant use bound param (SQL injection fix)
- health: text('SELECT 1'), REDIS_URL from config
- deps: re-export get_db from session, use settings.ENABLE_DEV_AUTH (default False)
- routes: all get_db from app.api.deps; conftest overrides deps.get_db
- main: register exception handlers from app.api.exceptions
- next.config: enable ESLint and TypeScript checks
- .eslintrc: drop @typescript-eslint/recommended; fix no-console (logger, ws-client, regulations)
- backend/.env.example added
- frontend: export apiFetch; dashboard, profile, settings, risks use api-client
- docs/ANALYSIS_AND_RECOMMENDATIONS.md
Co-authored-by: Cursor <cursoragent@cursor.com>
549 lines
24 KiB
Python
549 lines
24 KiB
Python
"""
|
||
API маршруты для системы юридических документов:
|
||
- юрисдикции, документы, перекрёстные ссылки, правовые комментарии, судебная практика
|
||
- запуск мультиагентного ИИ-анализа и подготовки документов по нормам
|
||
"""
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||
from app.api.helpers import audit, paginate_query
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.api.deps import get_current_user, require_roles
|
||
from app.api.deps import get_db
|
||
from app.models import Jurisdiction, LegalDocument, CrossReference, LegalComment, JudicialPractice
|
||
from app.schemas.legal import (
|
||
JurisdictionCreate,
|
||
JurisdictionUpdate,
|
||
JurisdictionOut,
|
||
LegalDocumentCreate,
|
||
LegalDocumentUpdate,
|
||
LegalDocumentOut,
|
||
CrossReferenceCreate,
|
||
CrossReferenceOut,
|
||
LegalCommentCreate,
|
||
LegalCommentUpdate,
|
||
LegalCommentOut,
|
||
JudicialPracticeCreate,
|
||
JudicialPracticeUpdate,
|
||
JudicialPracticeOut,
|
||
AnalysisRequest,
|
||
AnalysisResponse,
|
||
)
|
||
from app.services.legal_agents import LegalAnalysisOrchestrator
|
||
|
||
router = APIRouter(prefix="/legal", tags=["legal"])
|
||
|
||
|
||
# --- Jurisdictions ---
|
||
|
||
@router.get("/jurisdictions", response_model=list[JurisdictionOut])
|
||
def list_jurisdictions(
|
||
active_only: bool = Query(True),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(get_current_user),
|
||
):
|
||
q = db.query(Jurisdiction)
|
||
if active_only:
|
||
q = q.filter(Jurisdiction.is_active.is_(True))
|
||
return q.order_by(Jurisdiction.code).all()
|
||
|
||
|
||
@router.post("/jurisdictions", response_model=JurisdictionOut, status_code=status.HTTP_201_CREATED)
|
||
def create_jurisdiction(
|
||
payload: JurisdictionCreate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin")),
|
||
):
|
||
j = Jurisdiction(**payload.model_dump())
|
||
db.add(j)
|
||
db.commit()
|
||
db.refresh(j)
|
||
return j
|
||
|
||
|
||
@router.get("/jurisdictions/{jid}", response_model=JurisdictionOut)
|
||
def get_jurisdiction(jid: str, db: Session = Depends(get_db), user=Depends(get_current_user)):
|
||
j = db.get(Jurisdiction, jid)
|
||
if not j:
|
||
raise HTTPException(status_code=404, detail="Jurisdiction not found")
|
||
return j
|
||
|
||
|
||
@router.patch("/jurisdictions/{jid}", response_model=JurisdictionOut)
|
||
def update_jurisdiction(
|
||
jid: str,
|
||
payload: JurisdictionUpdate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin")),
|
||
):
|
||
j = db.get(Jurisdiction, jid)
|
||
if not j:
|
||
raise HTTPException(status_code=404, detail="Jurisdiction not found")
|
||
for k, v in payload.model_dump(exclude_unset=True).items():
|
||
setattr(j, k, v)
|
||
db.commit()
|
||
db.refresh(j)
|
||
return j
|
||
|
||
|
||
# --- Legal Documents ---
|
||
|
||
@router.get("/documents", response_model=list[LegalDocumentOut])
|
||
def list_legal_documents(
|
||
page: int = Query(1, ge=1), per_page: int = Query(25, ge=1, le=100),
|
||
jurisdiction_id: str | None = Query(None),
|
||
document_type: str | None = Query(None),
|
||
limit: int = Query(100, le=500),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(get_current_user),
|
||
):
|
||
q = db.query(LegalDocument)
|
||
if jurisdiction_id:
|
||
q = q.filter(LegalDocument.jurisdiction_id == jurisdiction_id)
|
||
if document_type:
|
||
q = q.filter(LegalDocument.document_type == document_type)
|
||
q = q.order_by(LegalDocument.created_at.desc())
|
||
return paginate_query(q, page, per_page)
|
||
|
||
|
||
@router.post("/documents", response_model=LegalDocumentOut, status_code=status.HTTP_201_CREATED)
|
||
def create_legal_document(
|
||
payload: LegalDocumentCreate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
d = LegalDocument(**payload.model_dump())
|
||
db.add(d)
|
||
db.commit()
|
||
db.refresh(d)
|
||
return d
|
||
|
||
|
||
@router.get("/documents/{doc_id}", response_model=LegalDocumentOut)
|
||
def get_legal_document(doc_id: str, db: Session = Depends(get_db), user=Depends(get_current_user)):
|
||
d = db.get(LegalDocument, doc_id)
|
||
if not d:
|
||
raise HTTPException(status_code=404, detail="Document not found")
|
||
return d
|
||
|
||
|
||
@router.patch("/documents/{doc_id}", response_model=LegalDocumentOut)
|
||
def update_legal_document(
|
||
doc_id: str,
|
||
payload: LegalDocumentUpdate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
d = db.get(LegalDocument, doc_id)
|
||
if not d:
|
||
raise HTTPException(status_code=404, detail="Document not found")
|
||
for k, v in payload.model_dump(exclude_unset=True).items():
|
||
setattr(d, k, v)
|
||
db.commit()
|
||
db.refresh(d)
|
||
return d
|
||
|
||
|
||
@router.get("/documents/{doc_id}/cross-references", response_model=list[CrossReferenceOut])
|
||
def list_document_cross_references(
|
||
doc_id: str,
|
||
direction: str = Query("outgoing", description="outgoing|incoming"),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(get_current_user),
|
||
):
|
||
q = db.query(CrossReference)
|
||
if direction == "incoming":
|
||
q = q.filter(CrossReference.target_document_id == doc_id)
|
||
else:
|
||
q = q.filter(CrossReference.source_document_id == doc_id)
|
||
return q.limit(100).all()
|
||
|
||
|
||
# --- Cross References (ручное добавление) ---
|
||
|
||
@router.post("/cross-references", response_model=CrossReferenceOut, status_code=status.HTTP_201_CREATED)
|
||
def create_cross_reference(
|
||
payload: CrossReferenceCreate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
ref = CrossReference(**payload.model_dump())
|
||
db.add(ref)
|
||
db.commit()
|
||
db.refresh(ref)
|
||
return ref
|
||
|
||
|
||
# --- Legal Comments ---
|
||
|
||
@router.get("/comments", response_model=list[LegalCommentOut])
|
||
def list_legal_comments(
|
||
jurisdiction_id: str | None = Query(None),
|
||
document_id: str | None = Query(None),
|
||
limit: int = Query(100, le=500),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(get_current_user),
|
||
):
|
||
q = db.query(LegalComment)
|
||
if jurisdiction_id:
|
||
q = q.filter(LegalComment.jurisdiction_id == jurisdiction_id)
|
||
if document_id:
|
||
q = q.filter(LegalComment.document_id == document_id)
|
||
from fastapi import Query as FQuery
|
||
return paginate_query(q.order_by(LegalComment.created_at.desc()), 1, limit)
|
||
|
||
|
||
@router.post("/comments", response_model=LegalCommentOut, status_code=status.HTTP_201_CREATED)
|
||
def create_legal_comment(
|
||
payload: LegalCommentCreate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
c = LegalComment(**payload.model_dump())
|
||
db.add(c)
|
||
db.commit()
|
||
db.refresh(c)
|
||
return c
|
||
|
||
|
||
@router.patch("/comments/{cid}", response_model=LegalCommentOut)
|
||
def update_legal_comment(
|
||
cid: str,
|
||
payload: LegalCommentUpdate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
c = db.get(LegalComment, cid)
|
||
if not c:
|
||
raise HTTPException(status_code=404, detail="Comment not found")
|
||
for k, v in payload.model_dump(exclude_unset=True).items():
|
||
setattr(c, k, v)
|
||
db.commit()
|
||
db.refresh(c)
|
||
return c
|
||
|
||
|
||
# --- Judicial Practice ---
|
||
|
||
@router.get("/judicial-practices", response_model=list[JudicialPracticeOut])
|
||
def list_judicial_practices(
|
||
jurisdiction_id: str | None = Query(None),
|
||
document_id: str | None = Query(None),
|
||
limit: int = Query(100, le=500),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(get_current_user),
|
||
):
|
||
q = db.query(JudicialPractice)
|
||
if jurisdiction_id:
|
||
q = q.filter(JudicialPractice.jurisdiction_id == jurisdiction_id)
|
||
if document_id:
|
||
q = q.filter(JudicialPractice.document_id == document_id)
|
||
# nulls_last портировано под SQLite < 3.30: (col IS NULL) ASC — не-NULL первыми
|
||
return q.order_by(
|
||
JudicialPractice.decision_date.is_(None),
|
||
JudicialPractice.decision_date.desc(),
|
||
JudicialPractice.created_at.desc(),
|
||
)
|
||
return paginate_query(q, 1, limit)
|
||
|
||
|
||
@router.post("/judicial-practices", response_model=JudicialPracticeOut, status_code=status.HTTP_201_CREATED)
|
||
def create_judicial_practice(
|
||
payload: JudicialPracticeCreate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
p = JudicialPractice(**payload.model_dump())
|
||
db.add(p)
|
||
db.commit()
|
||
db.refresh(p)
|
||
return p
|
||
|
||
|
||
@router.patch("/judicial-practices/{pid}", response_model=JudicialPracticeOut)
|
||
def update_judicial_practice(
|
||
pid: str,
|
||
payload: JudicialPracticeUpdate,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
p = db.get(JudicialPractice, pid)
|
||
if not p:
|
||
raise HTTPException(status_code=404, detail="Judicial practice not found")
|
||
for k, v in payload.model_dump(exclude_unset=True).items():
|
||
setattr(p, k, v)
|
||
db.commit()
|
||
db.refresh(p)
|
||
return p
|
||
|
||
|
||
# --- ИИ-анализ (мультиагентный) ---
|
||
|
||
@router.post("/analyze", response_model=AnalysisResponse)
|
||
def analyze_document(
|
||
payload: AnalysisRequest,
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
"""
|
||
Запуск мультиагентного анализа: классификация, соответствие нормам, перекрёстные ссылки,
|
||
подбор правовых комментариев и судебной практики, рекомендации по оформлению.
|
||
"""
|
||
orch = LegalAnalysisOrchestrator(db=db)
|
||
out = orch.run(
|
||
document_id=payload.document_id,
|
||
jurisdiction_id=payload.jurisdiction_id,
|
||
title=payload.title,
|
||
content=payload.content,
|
||
skip_agents=payload.skip_agents,
|
||
save_cross_references=payload.save_cross_references,
|
||
)
|
||
|
||
# Опционально: обновить документ в БД, если document_id передан
|
||
if payload.document_id and out.get("document_type"):
|
||
d = db.get(LegalDocument, payload.document_id)
|
||
if d:
|
||
d.document_type = out["document_type"]
|
||
d.analysis_json = out.get("analysis_json")
|
||
d.compliance_notes = out.get("compliance_notes")
|
||
db.commit()
|
||
|
||
return AnalysisResponse(
|
||
document_type=out["document_type"],
|
||
analysis_json=out.get("analysis_json"),
|
||
compliance_notes=out.get("compliance_notes"),
|
||
results=out.get("results", {}),
|
||
)
|
||
|
||
|
||
@router.post("/documents/{doc_id}/analyze", response_model=AnalysisResponse)
|
||
def analyze_existing_document(
|
||
doc_id: str,
|
||
skip_agents: list[str] | None = Query(None),
|
||
save_cross_references: bool = Query(True),
|
||
db: Session = Depends(get_db),
|
||
user=Depends(require_roles("admin", "authority_inspector")),
|
||
):
|
||
"""Запуск ИИ-анализа для уже существующего документа по id."""
|
||
d = db.get(LegalDocument, doc_id)
|
||
if not d:
|
||
raise HTTPException(status_code=404, detail="Document not found")
|
||
orch = LegalAnalysisOrchestrator(db=db)
|
||
out = orch.run(
|
||
document_id=doc_id,
|
||
jurisdiction_id=d.jurisdiction_id,
|
||
title=d.title,
|
||
content=d.content,
|
||
existing_document_type=d.document_type,
|
||
skip_agents=skip_agents,
|
||
save_cross_references=save_cross_references,
|
||
)
|
||
d.document_type = out["document_type"]
|
||
d.analysis_json = out.get("analysis_json")
|
||
d.compliance_notes = out.get("compliance_notes")
|
||
db.commit()
|
||
db.refresh(d)
|
||
return AnalysisResponse(
|
||
document_type=out["document_type"],
|
||
analysis_json=out.get("analysis_json"),
|
||
compliance_notes=out.get("compliance_notes"),
|
||
results=out.get("results", {}),
|
||
)
|
||
|
||
|
||
# -----------------------------------------------------------------------
|
||
# ДОПОЛНИТЕЛЬНЫЕ ФАП (№5-7 из перечня исходных документов)
|
||
# -----------------------------------------------------------------------
|
||
|
||
FAP_ADDITIONAL = {
|
||
"ФАП-148": {
|
||
"full_name": "Требования к эксплуатантам гражданских воздушных судов по обеспечению поддержания лётной годности",
|
||
"document": "Приказ Минтранса России от 23.06.2003 № 148",
|
||
"status": "Действует",
|
||
"scope": [
|
||
"Обязанности эксплуатанта по ПЛГ",
|
||
"Программа ТО воздушного судна",
|
||
"Контроль за выполнением директив лётной годности",
|
||
"Ведение эксплуатационной документации",
|
||
"Учёт наработки агрегатов и компонентов",
|
||
"Контроль назначенных ресурсов и сроков службы",
|
||
],
|
||
"relevance_to_system": "Базовый документ для модулей: Лётная годность, ТО, Чек-листы, Риски",
|
||
},
|
||
"ФАП-149": {
|
||
"full_name": "Требования к электросветотехническому обеспечению полётов",
|
||
"document": "Приказ Минтранса России от 23.06.2003 № 149",
|
||
"status": "Действует",
|
||
"scope": [
|
||
"Нормы электросветотехнического обеспечения на аэродромах",
|
||
"Требования к светосигнальному оборудованию",
|
||
"Контроль технического состояния электросветотехнических средств",
|
||
"Периодичность проверок и ТО",
|
||
],
|
||
"relevance_to_system": "Учитывается при аудитах аэродромной инфраструктуры и чек-листах",
|
||
},
|
||
"ФАП-10": {
|
||
"full_name": "Сертификационные требования к эксплуатантам коммерческой гражданской авиации",
|
||
"document": "Приказ Минтранса России от 04.02.2003 № 10 (ФАП-246 от 13.08.2015 — актуальная редакция)",
|
||
"status": "Заменён ФАП-246, но ряд положений действует",
|
||
"scope": [
|
||
"Организационная структура эксплуатанта",
|
||
"Требования к руководящему персоналу",
|
||
"Система управления безопасностью полётов",
|
||
"Программа подготовки авиационного персонала",
|
||
"Требования к парку ВС",
|
||
],
|
||
"relevance_to_system": "Базис для модуля Сертификация эксплуатантов (заявки, организации)",
|
||
},
|
||
}
|
||
|
||
|
||
@router.get("/fap-additional", tags=["legal"])
|
||
def get_additional_fap():
|
||
"""Дополнительные ФАП: 148, 149, 10."""
|
||
return FAP_ADDITIONAL
|
||
|
||
|
||
# -----------------------------------------------------------------------
|
||
# ПОРУЧЕНИЕ ПРЕЗИДЕНТА + ФЗ-488 + ВЫСТУПЛЕНИЕ КУДИНОВА + ТЗ АСУ ТК
|
||
# -----------------------------------------------------------------------
|
||
|
||
NATIONAL_PLG_FRAMEWORK = {
|
||
"presidential_order": {
|
||
"name": "Поручение Президента РФ Пр-1379 от 17.07.2019, п.2 пп.«в»",
|
||
"subject": "Гармонизация условий поддержания лётной годности ВС",
|
||
"requirements": [
|
||
"Создание национальной системы поддержания лётной годности",
|
||
"Гармонизация требований с международными стандартами (ICAO, EASA)",
|
||
"Обеспечение непрерывности контроля технического состояния ВС",
|
||
],
|
||
},
|
||
"fz_488": {
|
||
"name": "Федеральный закон от 30.12.2021 № 488-ФЗ",
|
||
"subject": "Введение статьи 37.2 ВК РФ «Поддержание лётной годности»",
|
||
"article_37_2": {
|
||
"text": "Поддержание лётной годности ВС — комплекс мер по обеспечению соответствия ВС "
|
||
"требованиям к лётной годности и поддержанию его безопасной эксплуатации",
|
||
"obligations": [
|
||
"Эксплуатант обязан обеспечивать ПЛГ",
|
||
"ФАВТ осуществляет государственный контроль за ПЛГ",
|
||
"Организация по ТО должна иметь сертификат",
|
||
],
|
||
},
|
||
},
|
||
"kudinov_speech": {
|
||
"name": "Выступление Кудинова В.В., начальника УПЛГ Росавиации",
|
||
"source": "Протокол Общественного совета ФАВТ от 21.10.2025 №14",
|
||
"key_points": [
|
||
"Необходимость создания национальной цифровой системы ПЛГ",
|
||
"Переход от бумажного документооборота к электронному",
|
||
"Интеграция с ФГИС РЭВС и другими информационными системами ФАВТ",
|
||
"Обеспечение прослеживаемости всех операций по ТО и ПЛГ",
|
||
"Автоматизация контроля сроков действия сертификатов и директив",
|
||
],
|
||
"relevance": "Определяет вектор развития АСУ ТК как элемента национальной системы ПЛГ",
|
||
},
|
||
"tz_asu_tk": {
|
||
"name": "Техническое задание на АСУ ТК «Контроль летной годности ВС»",
|
||
"approved_by": "Утверждено заместителем министра транспорта РФ 24.07.2022",
|
||
"scope": [
|
||
"Автоматизация процессов контроля лётной годности",
|
||
"Учёт воздушных судов и их технического состояния",
|
||
"Контроль выполнения программ ТО",
|
||
"Управление сертификационными процедурами",
|
||
"Мониторинг рисков безопасности полётов",
|
||
"Интеграция с системами ФАВТ и эксплуатантов",
|
||
"Обеспечение доступа для регулятора (ФАВТ) к агрегированным данным",
|
||
],
|
||
"system_modules_mapping": {
|
||
"Реестр ВС": "/aircraft, /airworthiness",
|
||
"Организации": "/organizations",
|
||
"Сертификация": "/applications, /regulator/certifications",
|
||
"Чек-листы и аудиты": "/checklists, /audits",
|
||
"Управление рисками": "/risks, /regulator/safety-indicators",
|
||
"Документооборот": "/documents, /inbox",
|
||
"Панель регулятора": "/regulator",
|
||
"Аналитика": "/analytics, /dashboard",
|
||
},
|
||
},
|
||
}
|
||
|
||
|
||
@router.get("/national-plg-framework", tags=["legal"])
|
||
def get_national_plg_framework():
|
||
"""
|
||
Национальная система ПЛГ — Поручение Президента, ФЗ-488,
|
||
выступление Кудинова, ТЗ АСУ ТК.
|
||
"""
|
||
return NATIONAL_PLG_FRAMEWORK
|
||
|
||
|
||
@router.get("/compliance-matrix", tags=["legal"])
|
||
def get_compliance_matrix():
|
||
"""
|
||
Матрица соответствия: 19 исходных документов → модули системы.
|
||
"""
|
||
return {
|
||
"system": "КЛГ АСУ ТК v16",
|
||
"developer": "АО «REFLY»",
|
||
"matrix": [
|
||
{"num": 1, "document": "Воздушный кодекс РФ (60-ФЗ)", "articles": "ст. 8, 35, 36, 37, 37.2",
|
||
"modules": ["Панель ФАВТ", "Сертификация", "Лётная годность", "Реестр ВС"],
|
||
"status": "implemented"},
|
||
{"num": 2, "document": "ФАП-21 (Часть 21)", "articles": "Приказ №184",
|
||
"modules": ["Сертификация АТ", "Организации"],
|
||
"status": "implemented"},
|
||
{"num": 3, "document": "ФАП-128", "articles": "Приказ №128",
|
||
"modules": ["Чек-листы полётов", "Аудиты"],
|
||
"status": "implemented"},
|
||
{"num": 4, "document": "ФАП-145 (Часть 145)", "articles": "Приказ №367",
|
||
"modules": ["ТО ВС", "Организации ТО", "Аудиты ТО"],
|
||
"status": "implemented"},
|
||
{"num": 5, "document": "ФАП-148", "articles": "Приказ №148",
|
||
"modules": ["Лётная годность", "Программы ТО", "Контроль ресурсов"],
|
||
"status": "implemented"},
|
||
{"num": 6, "document": "ФАП-149", "articles": "Приказ №149",
|
||
"modules": ["Аудиты инфраструктуры", "Чек-листы"],
|
||
"status": "implemented"},
|
||
{"num": 7, "document": "ФАП-10 / ФАП-246", "articles": "Приказ №10 / №246",
|
||
"modules": ["Сертификация эксплуатантов", "Организации"],
|
||
"status": "implemented"},
|
||
{"num": 8, "document": "ФАП-147", "articles": "Приказ №147",
|
||
"modules": ["Персонал ТО", "Квалификация экипажей"],
|
||
"status": "implemented"},
|
||
{"num": 9, "document": "EASA Part-M", "articles": "Reg. 1321/2014 Annex I",
|
||
"modules": ["Лётная годность", "Программы ТО"],
|
||
"status": "implemented"},
|
||
{"num": 10, "document": "EASA Part-CAMO", "articles": "Reg. 2019/1383",
|
||
"modules": ["Организации CAMO", "ПЛГ"],
|
||
"status": "implemented"},
|
||
{"num": 11, "document": "ICAO Annex 6", "articles": "Part I, Ch.8",
|
||
"modules": ["Сертификация", "ТО", "Чек-листы"],
|
||
"status": "implemented"},
|
||
{"num": 12, "document": "ICAO Annex 8", "articles": "4th edition",
|
||
"modules": ["Лётная годность", "Сертификация типа"],
|
||
"status": "implemented"},
|
||
{"num": 13, "document": "ICAO Doc 9760", "articles": "3rd edition",
|
||
"modules": ["Лётная годность", "Панель ФАВТ"],
|
||
"status": "implemented"},
|
||
{"num": 14, "document": "ICAO Annex 19", "articles": "2nd edition",
|
||
"modules": ["Управление рисками", "Безопасность полётов"],
|
||
"status": "implemented"},
|
||
{"num": 15, "document": "ICAO Doc 9734", "articles": "Part A, 3rd edition",
|
||
"modules": ["Панель ФАВТ", "Аудиты", "Надзор"],
|
||
"status": "implemented"},
|
||
{"num": 16, "document": "Поручение Президента Пр-1379", "articles": "п.2 пп.«в»",
|
||
"modules": ["Вся система — как элемент нац. системы ПЛГ"],
|
||
"status": "implemented"},
|
||
{"num": 17, "document": "ФЗ-488 (ст. 37.2 ВК)", "articles": "от 30.12.2021",
|
||
"modules": ["Лётная годность", "ПЛГ", "Контроль ФАВТ"],
|
||
"status": "implemented"},
|
||
{"num": 18, "document": "Выступление Кудинова В.В.", "articles": "Протокол ОС №14",
|
||
"modules": ["Цифровизация", "Интеграция ФГИС", "Электронный документооборот"],
|
||
"status": "implemented"},
|
||
{"num": 19, "document": "ТЗ АСУ ТК", "articles": "Утв. 24.07.2022",
|
||
"modules": ["Все модули системы"],
|
||
"status": "implemented"},
|
||
],
|
||
}
|