# 2026-08-06 — Ревизия плана Flask-реестра ## Контекст Переписываем Go-реестр (`server/main.go`) на Python/Flask для managed-сервиса в облаке. Логика 1:1 — те же эндпоинты, та же S3-структура, тот же GPG-ключ. ## Файлы прочитаны | Файл | Строки | Что | |---|---|---| | `server/main.go` | 1-289 | Весь HTTP-сервер: 7 роутов, S3, GPG | | `server/docs.go` | 1-200 | Docs-сервер с кандидатами ключей | | `server/gpg_key.go` | 1-50 | Прокси к `registrykeys` пакету | | `registrykeys/public_key.go` | 1-50 | Константы KeyID + ASCIIArmor | | `CHAT_SUMMARY_2026-08-06.md` | 1-100 | Контекст: архитектура, S3-структура, ENV | ## План (из plan.md) — TL;DR - **Фаза 1**: git checkout -b golang → удалить Go-код из master - **Фаза 2**: `app.py` (~250-300 строк Flask) + `requirements.txt` (flask, boto3) - **Фаза 3**: py_compile → деплой → curl-проверки → terraform init ### Эндпоинты (из Go-кода): | URL | Ответ | |---|---| | `GET /.well-known/terraform.json` | `{"providers.v1": "/v1/providers/"}` | | `GET /v1/providers/{ns}/{name}/versions` | JSON: id, versions[], warnings[] | | `GET /v1/providers/{ns}/{name}/{ver}/download/{os}/{arch}` | JSON: download_url, shasums_url, sig_url, shasum, signing_keys | | `GET /v1/proxy?bucket=...&key=...` | Стриминг файла из S3 | | `GET /docs/{ns}/{name}/{ver}/...` | Статика из S3 (кандидаты ключей) | | `GET /healthz` | `"ok"` 200 | | `GET /readyz` | `"ok"` 200 | | `GET /` | HTML-страница "ONLINE" | ### S3-ключи: ``` {hostname}/{namespace}/{name}/{version}/terraform-provider-{name}_{ver}_{os}_{arch}.zip {hostname}/{namespace}/{name}/{version}/terraform-provider-{name}_{ver}_SHA256SUMS {hostname}/{namespace}/{name}/{version}/terraform-provider-{name}_{ver}_SHA256SUMS.sig docs/{namespace}/{name}/{version}/{path} ``` ### ENV-переменные: - `REGISTRY_HOSTNAME` (default: `localhost:8080`) - `S3_ENDPOINT` - `S3_ACCESS_KEY` - `S3_SECRET_KEY` - `S3_BUCKET` (default: `terraform-registry`) ## 6 замечаний к плану ### 1. ⚠️ S3-пагинация (ВАЖНО) Go: `ListObjects` → канал с авто-пагинацией (все объекты). boto3: `list_objects_v2` → макс 1000 за раз. **Надо:** `Paginator` или цикл с `ContinuationToken`. ### 2. Docs-кандидаты (точность) Go-логика чуть точнее, чем описано в плане: - `rest` пустой → только `index.html` - `rest` не пустой: exact → (если `/` на конце ИЛИ нет расширения → `{rest}/index.html`) → `index.html` - Для `.css`/`.js` НЕ пробуется `{rest}/index.html` ### 3. Content-Length при стриминге Go ставит через `obj.Stat()`. Flask `stream_with_context` — нет. **Надо:** `head_object` → взять `ContentLength` → выставить вручную. ### 4. boto3 + MinIO ```python boto3.client('s3', endpoint_url=f'https://{s3_endpoint}', use_ssl=True, config=Config(signature_version='s3v4') ) ``` Без `s3v4` могут быть ошибки подписи на MinIO. ### 5. /readyz Go: комментарий «Проверить S3», но реально просто `"ok"`. Делать 1:1 → просто `"ok"`. ### 6. Порядок роутов во Flask Flask матчит сверху вниз. `/` должен быть последним, чтобы не перехватить `/docs/`. ## Решения (подтверждены) - GPG: только константа, без python-gnupg ✅ - Прокси: `?bucket=&key=` (НЕ `?url=`) ✅ - Платформы: только `linux_amd64` + `windows_amd64` ✅ - Домен: `registry.pythonk8s.dev.nubes.ru` ✅