# Учебный код занятия

Сквозная задача — **реестр сторонних компонентов программного обеспечения**.
SQLite используется как компактный учебный SQL-движок, а Python — только как
драйвер и оболочка для повторяемого запуска.

## Порядок работы

| Файл | Пара | Назначение | Запуск |
|---|---:|---|---|
| `schema.sql` | ПЗ-1 | Таблицы, ограничения и внешние ключи | читает `step1_schema.py` |
| `seed.sql` | ПЗ-1 | Четыре вымышленных компонента | читает `step1_schema.py` |
| `step1_schema.py` | ПЗ-1 | Создание новой БД без перезаписи существующей | `py step1_schema.py` |
| `demo_unsafe_query.py` | ПЗ-2 | Изолированное сравнение склейки SQL и placeholder | `py demo_unsafe_query.py` |
| `step2_secure_queries.py` | ПЗ-2 | Параметризованный поиск и allowlist `ORDER BY` | `py step2_secure_queries.py` |
| `step3_student.py` | ПЗ-3 | Рабочий файл слушателя | редактировать |
| `step3_student_solution.py` | ПЗ-3 | Эталон самопроверки после собственной попытки | `REGISTRY_MODULE=step3_student_solution py -m unittest -v test_student.py` |
| `test_student.py` | ПЗ-3 | 14 проверок результата | `py -m unittest -v test_student.py` |
| `test_examples.py` | ПЗ-1/2 | 6 проверок готовых примеров | `py -m unittest -v test_examples.py` |
| `.gitlab-ci.yml` | ПЗ-3 | Линтер, тесты, SAST и SCA | читает GitLab CI |

## Граница учебной демонстрации

`demo_unsafe_query.py` содержит одну намеренно уязвимую функцию на вымышленных
данных в памяти. Командная строка не принимает произвольный SQL. Этот файл
нужен только для наблюдения CWE-89; копировать `unsafe_search` в рабочий код
нельзя.

## Проверяемое состояние

Готовые примеры должны давать:

```text
py -m unittest -v test_examples.py
Ran 6 tests
OK
```

Студенческий файл до выполнения задания должен быть красным:

```text
py -m unittest -v test_student.py
FAILED
```

После реализации всех пяти функций ожидается:

```text
Ran 14 tests
OK
```

Публичный архив является комплектом для самостоятельного повторения, поэтому
`step3_student_solution.py` включён как эталон самопроверки **после собственной попытки**. Преподавательские ключи и расширенный эталон остаются только в
локальном каталоге `_teacher/`; в оцениваемой группе файл публичного решения
не выдают до завершения задания.
