Chyba #169
otevřenýdev.noveknihy.local: login padá na chybějícím klíči slepého indexu, dev DB zaostává za kódem
Popis
h2. Příznak
@POST http://dev.noveknihy.local/login.php?action=process@ vracel HTTP 200 s fatální chybou v těle:
Fatal error: Uncaught RuntimeException: BlindIndex: key file not readable: /home/f/git/noveknihy/catalog/includes/local/index_keys.php in /home/f/git/noveknihy/catalog/includes/classes/Noveknihy/BlindIndex.php:100 #2 .../includes/modules/content/login/cm_login_form.php(42): Noveknihy\BlindIndex::whereEmail()
Pozor na reprodukci: bez platného @formid@ se @Form::validate_action_is('process')@ neprojde a @cm_login_form::login()@ se vůbec nezavolá, takže se chyba neprojeví. Je potřeba vzít token z @GET /login.php@ se stejnou cookie @ceid@.
h2. Příčina
Není to chyba v kódu. Pracovní kopie @/home/f/git/noveknihy@ (větev @functionalHTML@) byla napřed proti databázi @noveknihy_dev@. Ověřeno:
- @/home/f/git/noveknihy/catalog/includes/local/index_keys.php@ neexistoval
- sloupec @customers.customers_email_bidx@ neexistoval, @customers_email_address@ byl plaintext @varchar(255)@ s čitelnými adresami (10 zákazníků)
- tabulky @role_keys@, @role_members@ neexistovaly
- @php vendor/bin/phinx status -c phinx-adapter.php@ hlásil 16 migrací @down@ — od @20261016150000 AKeyIsWrappedForEveryReader@ po @20261026100000 AGuestBuysWithoutBeingSignedIn@, tedy celou vrstvu šifrování osobních údajů
@cm_login_form::login()@ volá @BlindIndex::whereEmail()@ bezpodmínečně. Dokumentace @/home/f/git/noveknihy/doc/cs/sifrovani-osobnich-udaju.md:745@ to říká přímo: "Dokud @--seal@ u zákazníků neproběhl, nikdo se nepřihlásí."
h2. Druhý zasažený subsystém
Stejná příčina shazovala i agentní API: @/home/f/git/noveknihy/catalog/includes/classes/agent_auth.php:38@ selectuje sloupec @pii_key_token@, který vzniká až migrací @20261026040000 AnAgentCarriesTheCustomersKeyInItsToken@. Jakýkoli předložený token tedy skončil fatální chybou místo JSON odpovědi.
h2. Co už je udělané (4. 11. 2026 večer)
Záloha databáze před zásahem: @/home/f/zalohy-noveknihy/noveknihy_dev-pred-sifrovanim-2026-11-04-2352.sql.gz@ (62 MB, práva 0600). Integrita gzipu, přítomnost klíčových tabulek i úplnost dumpu ověřeny. Záměrně mimo repozitář — @/home/f/git/noveknihy/db/data/@ není v @.gitignore@ a dump obsahuje zákaznická data.¶
Všech 16 migrací spuštěno, @phinx status@ nehlásí nic @down@. Vzniklo @customers_email_bidx@, @pii_key_token@, @role_keys@, @role_members@. Migrace mimochodem zvedly minimální délku hesla z 5 na 8 a zapnuly brzdy @ar_login.php@ a @ar_admin_login.php@.¶
Vygenerován a zapsán indexový klíč @/home/f/git/noveknihy/catalog/includes/local/index_keys.php@ (32 bajtů, verze 1, práva 0600). Před generováním ověřeno, že žádný starší nikde neleží — ty v @/home/nkcrypto/keys/@ a @/home/nkcryptoadmin/keys/@ patří crypto simulaci na jiné databázi @noveknihy_crypto@ (uživatelé @nkc_shop@ / @nkc_admin@), a záloha @/home/f/noveknihy-zaloha-klicu-NA-PAPIR.txt@ je ke značkovacímu klíči e-knih a platebním klíčům GP webpay. Ověřeno také, že web ten adresář nevydává: @includes/local/.htaccess@ má @Require all denied@ a všechny zkoušené cesty vrací 403.¶
Fatální chyba v loginu je tím pryč — stránka vrací korektní "E-mailová adresa nebo heslo nenalezeno." Agentní API vrací korektní JSON 401 místo stack trace.¶
h2. Co zbývá
Obřad s klíči podle @/home/f/git/noveknihy/doc/cs/sifrovani-osobnich-udaju.md:684-745@. Vyžaduje heslo administrátora, které zadá člověk, protože se pod ním zabalí privátní klíč role. Připraven skript @/home/f/obrad-dev-klice.sh@ (práva 0700, heslo čte bez echa, takže neskončí v historii shellu):
- administrátor @devkeys@
- @crypto-keys.php init@ — záchranný klíč + role @root@ a @secretariat@
- @crypto-keys.php shop-key@ — role @shop@; bez její veřejné půlky se nezapečetí nic a nikdo se nezaregistruje ani nenakoupí (@RoleKeys::publicKeyOf()@ vyhodí @no role 'shop'@). Soubor @shop_private.php@ vzniknout nesmí, privátní půlka zůstane zapečetěná na záchranný klíč v @role_keys.wrapped_private@. Pořadí je dané: @RoleKeys::createRole()@ na @RoleKeys.php:133-138@ odmítne pracovat bez záchranného klíče, takže @init@ → @shop-key@.
- @crypto-seal-{customers,orders,outgoing}.php --seal@ a @--verify@
Nevratný @--blank@ skript záměrně nedělá, je na samostatné rozhodnutí po kontrole.
h2. Aktuálně rozbité, než obřad doběhne
- @POST /create_account.php@ padá na @RuntimeException: RoleKeys: no role 'shop'@ (@RoleKeys.php:78@ ← @CustomerPii.php:135@ ← @cd_city.php:130@)
- přihlásit se nikdo nemůže, @customers_email_bidx@ je u všech 10 zákazníků prázdný
Prohlížení, hledání, bazar, košík i vykreslení @login.php@ fungují — ověřeno sedm stránek, fatální chyba nikde.
h2. Prostředí
Stroj @mi@, uživatel @Šimon Formánek@. DocumentRoot dev instance je @/home/f/git/noveknihy/catalog/@, FPM pool @noveknihy-dev@ běží pod @user = f@. Dev administrace je na @http://dev.noveknihy.local/admin/@ a používá tutéž databázi i tentýž @includes/local/@, takže jeden @index_keys.php@ pokrývá obchod i admin.
Související úkoly 1 (1 otevřený — 0 uzavřených)