CVRN logoCVRN Docs
DocsArchitekturaPlanyChangelog
Sections
  • Zaklady
  • Architektura
  • Komunita
  • Legal
  • Plany
  • Changelog
Zaklady
  • O dokumentacii
  • Ako citat dokumentaciu
  • Struktura repozitara
Architektura
  • Ako aplikacia funguje
  • Diagramy
Komunita
  • Prehlad komunitnych pravidiel
  • CVRN desatoro
  • Onboarding a aktivacia clena
  • Prevadzkove pravidla (draft)
  • Treningovy mod (navrh)
  • WhiteBikes poznamky
  • Analyza Rekola
  • Analyza Slovnaft BAjk
Legal
  • Zasady ochrany osobnych udajov (navrh)
  • GDPR brief pre pravnika
  • RoPA template
  • Reklamacny a incidencny poriadok (draft)
Plany
  • Prehlad planov
  • Stavovy guard model
  • Nahlasene nepozicatelne biky
  • Email notifikacie (outbox)
  • Dynamicky kod a historia
  • Mapa a stanovista
  • Statistiky a historia jazd
  • Logo hover header
  • Backlog whitebikes inspired
Changelog
  • Sync a automatizacia
  • CVRN App Changelog

Dynamicky kod a historia

PreviousNext

Plan automatickej rotacie kodov, historie a recovery postupov.

status: planned
type: plan
#plany
#kod
#zamok

Migrovane z docs-old-cvrn/plans/PLAN_DYNAMICKY_KOD.md.

1) Ciel

Automatizovat proces zmeny zamku kodu tak, aby:

  • admin nemusel manualne menit kod raz za mesiac,
  • system vedel evidovat historiu kodov na kazdy bicykel,
  • existoval audit "kto, kedy, z akeho kodu na aky kod menil",
  • pri probleme bol dostupny recovery postup (posledne kody + stav overenia),
  • onboarding usera obsahoval povinne potvrdenie pravidiel pri prvom prihlaseni.

2) Rozsah

In scope

  • evidencia historie kodov,
  • automaticka rotacia kodu pri vrateni bicykla,
  • potvrdenie funkcnosti kodu pri nasledujucom prenajme,
  • admin obrazovka pre audit/recovery,
  • terms acceptance (prve prihlasenie + verzovanie pravidiel),
  • stavovy model pre "kod overeny/neovereny/podozrivy".

Out of scope (v tejto faze)

  • hardverove smart lock API (zamok sa stale nastavuje manualne clovekom),
  • push notifikacie/SMS,
  • pokrocile anti-fraud mechanizmy.

3) Vychodiskovy stav (teraz)

  • bikes.secret_code drzi aktualny kod.
  • Pri rent sa kod zobrazi userovi.
  • Pri return sa kod nemeni automaticky.
  • Historia kodov nie je oddelena tabulka.
  • Terms acceptance flow zatial nie je implementovany.

4) Cielovy stav (po implementacii)

  1. Pri return:
    • system vygeneruje novy 4-ciferny kod,
    • user potvrdi, ze kod fyzicky nastavil na zamku,
    • system ulozi rotaciu do historie.
  2. Pri dalsom rent:
    • user potvrdi "kod fungoval pri odomknuti",
    • system oznaci poslednu rotaciu ako verified.
  3. Ak user oznaci "kod nefungoval":
    • bicykel prejde do code_status='suspect',
    • admin vidi posledne kody a moze riesit recovery.
  4. Pri prvom prihlaseni:
    • user musi potvrdit aktualnu verziu pravidiel.

5) Datovy model (decision-complete)

5.1 Upravy existujucich tabuliek

public.bikes

Pridat stlpce:

  • code_version int not null default 1
  • code_status text not null default 'verified'
    • allowed: verified, pending_verification, suspect
  • last_code_change_at timestamptz null
  • last_code_changed_by uuid null references public.profiles(id)

Constraint:

  • check (code_status in ('verified','pending_verification','suspect'))

public.rentals

Pridat stlpce:

  • unlock_verification text null
    • allowed: ok, failed, not_provided
  • unlock_verified_at timestamptz null
  • unlock_verified_by uuid null references public.profiles(id)
  • code_version_used int null

Constraint:

  • check (unlock_verification in ('ok','failed','not_provided') or unlock_verification is null)

public.profiles

Pridat stlpec:

  • training_completed boolean not null default false

5.2 Nove tabulky

public.bike_code_history

Audit historia kodov:

  • id bigint generated by default as identity primary key
  • bike_id bigint not null references public.bikes(id) on delete cascade
  • rental_id bigint null references public.rentals(id) on delete set null
  • old_code text not null
  • new_code text not null
  • old_version int not null
  • new_version int not null
  • changed_at timestamptz not null default now()
  • changed_by uuid not null references public.profiles(id)
  • change_source text not null
    • allowed: return_flow, admin_manual
  • verification_status text not null default 'pending'
    • allowed: pending, verified, failed
  • verified_at timestamptz null
  • verified_by uuid null references public.profiles(id)
  • verification_note text null

Indexy:

  • (bike_id, changed_at desc)
  • (verification_status, changed_at desc)

public.terms_versions

  • id bigint generated by default as identity primary key
  • version text not null unique (napr. 2026-02-v1)
  • title text not null
  • content_md text not null
  • is_active boolean not null default false
  • published_at timestamptz not null default now()
  • created_by uuid null references public.profiles(id)

Constraint:

  • partial unique index na is_active=true (max 1 aktivna verzia)

public.terms_acceptances

  • id bigint generated by default as identity primary key
  • user_id uuid not null references public.profiles(id) on delete cascade
  • terms_version_id bigint not null references public.terms_versions(id) on delete cascade
  • accepted_at timestamptz not null default now()
  • ip text null
  • user_agent text null

Constraint:

  • unique(user_id, terms_version_id)

6) Stavovy model kodu

bikes.code_status

  • verified: posledna rotacia bola potvrdena dalsim uzivatelom.
  • pending_verification: kod bol zmeneny pri return, ale este nebol potvrdeny dalsim rentom.
  • suspect: niekto nahlasil, ze kod nefunguje, alebo verifikacia zlyhala.

Prechod stavov:

  • return + rotacia -> pending_verification
  • next rent verifikacia OK -> verified
  • next rent verifikacia failed -> suspect
  • admin recovery/manual reset -> pending_verification alebo verified (podla admin rozhodnutia)

7) API / RPC zmeny

7.1 Nove RPC

  1. rotate_code_on_return(note_text text, confirm_changed boolean)
    • predpoklad: user ma aktivny rental.
    • ak confirm_changed=false: return odmietnut (biznis pravidlo).
    • vygeneruje novy kod, update bikes.secret_code, code_version+1, status pending_verification.
    • vlozi bike_code_history riadok (pending).
    • uzavrie rental (returned_at, return_note, code_version_used).
  2. verify_unlock_result(rental_id bigint, result text, note text default null)
    • result in ('ok','failed').
    • ok: posledna rotacia verified, bike verified.
    • failed: posledna rotacia failed, bike suspect.
    • update rentals.unlock_verification....
  3. admin_get_bike_code_history(bike_id bigint, limit_count int default 20)
    • vrati posledne rotacie daneho bicykla.
  4. admin_mark_code_recovered(bike_id bigint, working_code text, note text default null)
    • admin potvrdi realne fungujuci kod po fyzickej kontrole.
    • update bikes.secret_code, code_version+1, history row admin_manual.
    • status verified alebo pending_verification (default verified).
  5. get_active_terms()
    • vrati aktivnu verziu pravidiel.
  6. accept_terms(terms_version_id bigint)
    • ulozi akceptaciu pre usera.
  7. has_accepted_active_terms()
    • bool pre middleware gating.

7.2 Zmena existujucich RPC

  • rent_bike(...):
    • po uspesnom rent vrati aj code_status a code_version.
  • return_bike(...):
    • nahradit za rotate_code_on_return(...) (alebo ponechat ako fallback pre admin emergency flow).

8) Generovanie kodu (presne pravidla)

Format kodu:

  • 4 cifry 0000-9999.

Bezpecny generator:

  • Postgres gen_random_bytes/gen_random_uuid derivacia alebo generovanie v server action cez crypto.
  • Preferencia: generovat v DB RPC (single source of truth).

Pravidla pre vyber:

  • zakazat opakovanie poslednych N=5 kodov pre dany bike,
  • max K=20 pokusov o random draw,
  • ak sa nepodari, fallback: linear scan od nahodneho startu.

9) UI/UX zmeny

9.1 Dashboard user

Pri aktivnej jazde:

  • zobrazit aktualny kod ako dnes.
  • pri vrateni pridat checkbox:
    • Potvrdzujem, ze som fyzicky nastavil novy kod na zamku.
  • po submit zobrazit "Novy kod bol ulozeny v systeme."

Pri najblizsom dalsom rent (po odomknuti):

  • modal s 2 tlacidlami:
    • Kod fungoval,
    • Kod nefungoval.

9.2 Admin

Na /admin pridat sekciu:

  • tabulka historie kodov (bike, old/new version, changed_by, verification_status, changed_at),
  • filter podla bike a statusu,
  • quick action Mark recovered + zadanie realne fungujuceho kodu.

9.3 Terms acceptance

Nove route:

  • /terms - zobrazi aktivny text pravidiel + accept tlacidlo.

Middleware:

  • prihlaseny user bez akceptacie aktivnej verzie -> redirect na /terms.

10) RLS a bezpečnost

Pravidla:

  • bezny user nevidi globalnu historiu kodov.
  • bezny user moze vidiet iba aktualny kod svojho pozicaneho bicykla.
  • bike_code_history select len admin.
  • terms read pre authenticated, write acceptance len pre vlastneho usera (cez RPC).

Audit:

  • kazda zmena kodu ma changed_by, changed_at, change_source.
  • kazde zlyhanie verifikacie ma verification_note.

11) Migracny plan (bez downtime pre MVP)

Faza A: Historia bez zmeny flow

  1. DB migration:
    • nove tabulky + nove stlpce.
  2. Admin UI:
    • historia kodov read-only.
  3. Manual zmena kodu adminom zapisuje aj history row.

Outcome:

  • okamzite mas audit trail, aj ked flow pre usera sa nemenil.

Faza B: Automaticka rotacia pri return

  1. Nove RPC rotate_code_on_return.
  2. UI return flow s potvrdenim.
  3. bikes.code_status prejde na pending_verification.

Outcome:

  • admin uz nemusi mesacne menit kod.

Faza C: Verifikacia pri dalsom rent + recovery

  1. UI potvrdenie "kod fungoval/nefungoval".
  2. RPC verify_unlock_result.
  3. Admin recovery ak suspect.

Outcome:

  • system rozlisuje doverovany a podozrivy kod.

Faza D: Terms acceptance gate

  1. terms tabulky + route /terms.
  2. middleware gate.
  3. admin publishing novej verzie pravidiel.

Outcome:

  • pravna/operacna disciplina pri prvom login a pri zmenach pravidiel.

12) Testy a akceptacne scenare

12.1 Funkcne scenare

  1. Return s potvrdenim:
    • vytvori sa history row,
    • bike ide do pending_verification,
    • rental sa zavrie.
  2. Next rent verifikacia OK:
    • posledna history row -> verified,
    • bike -> verified.
  3. Next rent verifikacia failed:
    • history row -> failed,
    • bike -> suspect,
    • admin vidi alert v dashboarde.
  4. User bez acceptance:
    • po login redirect /terms.
  5. User po acceptance:
    • standard flow na /.
  6. RLS:
    • bezny user nedokaze citat bike_code_history.

12.2 Edge cases

  • dva paralelne return requesty na rovnaky bike (transaction lock),
  • bike v service sa neda pozicat,
  • generator kodu nenajde kod v random pokusoch (fallback funguje),
  • admin manual recovery pocas aktivneho rentalu (zakazane).

13) Operacne metriky

Merat:

  • pocet rotacii kodov za den/tyzden,
  • podiel failed verifikacii,
  • pocet bicyklov v suspect,
  • median cas od pending_verification do verified.

Alert podmienka:

  • ak bike ostane pending_verification viac ako X dni,
  • ak failed verifikacie prekrocia limit za tyzden.

14) Otvorene rozhodnutia (default nastavene)

  1. Dlzka kodu:
    • default: 4 cifry (ponechat).
  2. User moze vratit bike bez potvrdenia zmeny kodu?
    • default: nie (blokovat return bez confirm checkboxu).
  3. Kolko historickych kodov odporucat adminovi v recovery UI?
    • default: poslednych 10.
  4. Admin recovery po fyzickej kontrole nastavi stav:
    • default: verified.

15) Minimalny implementacny backlog (poradie)

  1. SQL migration pre bike_code_history, terms_versions, terms_acceptances, nove stlpce.
  2. RPC: rotate_code_on_return, verify_unlock_result, admin_get_bike_code_history.
  3. Update actions.ts a dashboard return flow.
  4. Admin page: historia kodov + filter + recover action.
  5. Terms route + middleware gate.
  6. Testy scenarov + rollout najprv na malej skupine userov.

16) Kompatibilita s planom reported bicykla

Plan PLAN_NAHLASENE_NEPOZICATELNE_BIKY.md zavadza os stavu bikes.status='reported', ktora je odlisna od bikes.code_status.

Integracne pravidlo:

  • status (available/rented/service/reported) = operacna pozicatelnost bicykla,
  • code_status (verified/pending_verification/suspect) = doveryhodnost kodu zamku.

Tieto osi sa nesmu zamienat ani prepinat jedna druhu implicitne. Ak je bike reported, kodovy flow moze bezat iba v rozsahu, ktory neobchadza operacny blok prenajmu pre bezneho usera.

Email notifikacie (outbox)Mapa a stanovista

On This Page

1) Ciel2) RozsahIn scopeOut of scope (v tejto faze)3) Vychodiskovy stav (teraz)4) Cielovy stav (po implementacii)5) Datovy model (decision-complete)5.1 Upravy existujucich tabuliek5.2 Nove tabulky6) Stavovy model kodubikes.code_status7) API / RPC zmeny7.1 Nove RPC7.2 Zmena existujucich RPC8) Generovanie kodu (presne pravidla)9) UI/UX zmeny9.1 Dashboard user9.2 Admin9.3 Terms acceptance10) RLS a bezpečnost11) Migracny plan (bez downtime pre MVP)Faza A: Historia bez zmeny flowFaza B: Automaticka rotacia pri returnFaza C: Verifikacia pri dalsom rent + recoveryFaza D: Terms acceptance gate12) Testy a akceptacne scenare12.1 Funkcne scenare12.2 Edge cases13) Operacne metriky14) Otvorene rozhodnutia (default nastavene)15) Minimalny implementacny backlog (poradie)16) Kompatibilita s planom reported bicykla
© CVRN dokumentacia