Plan #7912 — Lager → GitHub + port do et-op (Faza 0: inwentaryzacja)
Issue: #7912 Data: 2026-10-13 Status: Faza 0 zakończona — oczekuje akceptacji właściciela przed Fazą 1
1. Inwentaryzacja GitLab (gitlab.com/pinbox24/et-lager, ID 77031715)
Zebrane 2026-10-13 przez bms-4 worker via GitLab API (GITLAB_ADMIN_PAT — wartości nie są wyświetlane).
1.1 Repozytorium — podstawowe dane
| Atrybut | Wartość |
|---|---|
| Nazwa | et-lager |
| Namespace | pinbox24 |
| Project ID | 77031715 |
| Default branch | master (protected, Developers + Maintainers) |
| Visibility | private |
| Utworzono | 2025-12-11 |
| Ostatnia aktywność | 2026-07-05 |
| Języki | TypeScript 53%, TSX 44%, JavaScript 2%, CSS 1%, Dockerfile 0.1% |
1.2 Branche
| Branch | Domyślna | Protected | Ostatni commit | Autor |
|---|---|---|---|---|
master | ✓ | ✓ | 2026-07-05 | Radek Konarski |
fix/et-lager-security-p0 | — | — | 2026-07-05 | Radek Konarski |
Wniosek: tylko 1 aktywna gałąź robocza (fix zmerge do master przez MR!1). Czyste środowisko, brak brudnych gałęzi.
1.3 Merge Requests (historyczne)
| MR | Tytuł | Status | Data merge |
|---|---|---|---|
| !1 | security: fix P0 vulnerabilities - hardcoded MongoDB URI + SSRF proxy | merged | 2026-07-05 |
Wniosek: 1 MR w historii (fix security). Brak otwartych MR.
1.4 Issues GitLab
Brak (0 issues w GitLab). Tracking odbywa się w GitHub (radieu/p24-infra).
1.5 CI Variables
Brak CI variables w GitLab. Środowisko zarządzane przez Vercel env vars + secrets/et-lager.env.sops (synchronizowane przez secrets-sync.yml).
1.6 CI/CD Pipeline
Brak .gitlab-ci.yml. Pipelines uruchamiane przez Vercel webhook (push → auto-deploy).
Ostatnie pipelines:
- 2026-07-05:
master— success (deploy po MR!1) - 2025-12-11:
master— success (deploy inicjalny)
1.7 Webhooki
| Hook | URL | Eventy | Utworzono |
|---|---|---|---|
| Vercel auto-deploy | https://api.vercel.com/v1/incoming/gitlab?accountId=team_RuXLTWx5DXK6n0HUKoOUTGY3 | push, merge_requests | 2025-12-11 |
Ważne dla Fazy 1: po przeniesieniu git source w Vercel z GitLab na GitHub, ten webhook staje się nieaktywny i należy go usunąć.
1.8 Protected branches
| Branch | Push | Merge |
|---|---|---|
master | Developers + Maintainers | Developers + Maintainers |
2. Analiza struktury kodu Lager
2.1 Struktura route’ów (App Router)
Lager ma dwa równoległe drzewa tras:
Root-level routes (src/app/):
/auth — logowanie
/dashboard — dashboard główny
/invoice-list — lista faktur (root)
/invoice-protocol — protokół faktury
/invoice-view — widok faktury (root)
/invoices — faktury (root)
/invoices-list2 — lista faktur v2 (root)
/language-selection — wybór języka
/missing-products — brakujące produkty (root)
/no-access — brak dostępu
/no-location-products — produkty bez lokalizacji
/profile — profil użytkownika
/protocol-release — zwolnienie protokołu
/protocols — protokoły (root)
/stock — stan magazynu (root)
/warehouse-release — wydanie z magazynu (root)
/workspace — workspace selector
Workspace-scoped routes (src/app/workspace/[workspaceId]/):
/workspace/[id]/dashboard
/workspace/[id]/invoice-protocol
/workspace/[id]/invoice-view
/workspace/[id]/invoices-list2
/workspace/[id]/missing-products
/workspace/[id]/no-location-products
/workspace/[id]/protocols
/workspace/[id]/stock
/workspace/[id]/warehouse-release
Łącznie ~20 stron root + ~9 workspace-scoped + strony pomocnicze ≈ 37 zidentyfikowanych stron.
2.2 API Routes (src/app/api/)
| Ścieżka | Funkcjonalność |
|---|---|
/api/auth | Logowanie Pinbox24 JWT |
/api/invoices | CRUD faktur, PDF, filtrowanie |
/api/invoice-protocols | Powiązanie faktur z protokołami |
/api/protocols | CRUD protokołów magazynowych |
/api/stock | Stan magazynu, lookup SKU |
/api/warehouse-products | Produkty magazynowe |
/api/warehouse-protocols | Protokoły wydań |
/api/workspace | Workspace-scoped warianty powyższych |
/api/public/intercars-proxy | Proxy SSRF do Intercars (z allowlistą) |
/api/missing-products | Tracking brakujących produktów (Atlas) |
/api/bug-report | Zgłoszenie błędu |
/api/profile | Profil użytkownika |
Łącznie: 47+ endpoint’ów (wg API_INVENTORY.md).
2.3 Zależności zewnętrzne
| Zależność | Typ | Uwagi |
|---|---|---|
api.w4.pinbox24.com | REST API | Źródło prawdy dla magazynu/faktur; JWT użytkownika (MD5, 8h TTL) |
Intercars B2B API (api.webapi.intercars.eu) | REST OAuth2 | CLIENT_ID_SECRET nadal hardcoded w src/constants/intercars.constants.ts — #2852 OPEN |
| MongoDB Atlas | Storage | nextjs-db-dev.ncgd33w.mongodb.net; 2 kolekcje: missingProducts, processedInvoices |
| NextAdmin v1.2.1 | Template | Free template, działa jako szkielet UI |
2.4 Znane problemy (z docs/et-lager-operations.md)
P0 (blokuje Fazę 1):
INTERCARS_CLIENT_ID_SECREThardcoded wsrc/constants/intercars.constants.ts— śledzone w #2852 (OPEN). Musi być usunięte z kodu i historii git (git filter-repo) zanim kod trafi na GitHub.
P1 (do rozwiązania w Fazie 4/5):
- Brak token refresh (Pinbox24 JWT wygasa po ~8h)
- Cookie/header mismatch w middleware (auth przez header, nie przez cookie)
- Build script broken na Linux (
set NODE_OPTIONS=...— Windows CMD) next: "^16.0.7"(nie istnieje — resolves do 15.x)
P2 (tech debt, Faza 5):
- Brak CI/CD pipeline
- Duplikacja route’ów workspace vs root
- 2 pliki MongoDB connection
moment+dayjs— zduplikowane- Debug
console.logw produkcji - JWT nie weryfikowany kryptograficznie
- Stub npm packages (
child_process,net) - ~20 plików
.mdz notatkami AI w korzeniu repo (do przeniesienia/usunięcia)
3. Lista decyzji do brainstormu z właścicielem
D1 — Auth/tożsamość użytkownika w et-op
Pytanie: Jak użytkownicy et-lager logują się w zintegrowanym et-op?
| Opcja | Opis | Za | Przeciw |
|---|---|---|---|
| (a) Supabase login + server-stored Pinbox24 credentials | Użytkownik loguje się przez Supabase (email/hasło). W tabeli pinbox24_credentials przechowujemy jego Pinbox24 email+hasło (zaszyfrowane). Na każdy request pobieramy token Pinbox24 server-side. | Jednolity auth stack et-op; ukrywa Pinbox24 przed frontendem | Przechowywanie haseł użytkowników (regulaminowo wątpliwe, Pinbox24 nie ma OAuth); rotacja przy zmianie hasła Pinbox24 wymaga ręcznej aktualizacji |
| (b) Logowanie Pinbox24 → mapowanie na Supabase session | Użytkownik loguje się Pinbox24 credentials; serwer wymienia je na Supabase session + przechowuje Pinbox24 token w sesji. | Brak duplikacji haseł; flow znany z Lager | 2 różne flow logowania w et-op — złożoność UX; Supabase session + Pinbox24 JWT = dwa czasy życia tokena |
| (c) Konto serwisowe Pinbox24 (shared) | Jeden account serwisowy Pinbox24 dla całego et-op. Użytkownicy logują się tylko przez Supabase; wywołania Pinbox24 idą pod kontem serwisowym. | Najprostsze; brak per-user tokenów | Pinbox24 workspace access control oparty na per-user workspaces — konto serwisowe może nie mieć dostępu do workspace’ów konkretnych użytkowników |
Rekomendacja: (b) — Logowanie Pinbox24 → mapowanie na Supabase session. Zachowuje istniejący model auth Lager (Pinbox24 JWT), ale integruje z istniejącym Supabase session management et-op. Niski koszt adaptacji w Fazie 5; brak przechowywania haseł.
Ryzyko wymagające potwierdzenia: Czy workspace access w Pinbox24 API jest per-user (JWT-based)? Jeśli tak, opcja (c) odpada definitywnie.
D5 — Definicja „1:1” (layout + metoda akceptacji wizualnej)
Pytanie: Co konkretnie jest nienowocjonowalne w layoucie Lager? Jak weryfikujemy 1:1?
| Opcja | Opis | Za | Przeciw |
|---|---|---|---|
| (a) Screenshot baseline Playwright (pixel-level) | Dla każdej z 37 stron Lager robimy baseline screenshot (Playwright + Percy/Argos). et-op musi przejść expect(screenshot).toMatchSnapshot() z progiem ≈5% odchylenia. | Obiektywny kontrakt; weryfikowalny automatycznie | ~2-3 tygodnie setup; wrażliwy na różnice dark/light, viewport; NextAdmin vs shadcn = inne klasy CSS, wymaga per-pixel tolerancji |
| (b) Functional parity + layout audit przez właściciela | Definiujemy listę kryteriów funkcjonalnych (tabela X, filtr Y, przycisk Z) + layout guideline (kolumny, sidebar, pagination). Akceptacja przez ręczny przegląd właściciela po każdej fazie. | Pragmatyczna; uwzględnia świadome różnice stylistyczne (shadcn vs NextAdmin) | Subiektywna; możliwe spory przy odbiorze |
| (c) Komponent po komponencie — visual diff przez Storybook | Każdy przeniesiony komponent ma storybookowy screenshot. Diff tylko changed components. | Granularny; łatwy w utrzymaniu | Wymaga pełnego Storybook setup; nie testuje integracji stron |
Rekomendacja: (b) z dokumentem lager-visual-acceptance-criteria.md zawierającym screenshoty kluczowych widoków Lager jako reference obrazy (załącznik do issue Fazy 2). Pełny Playwright screenshot suite jest opcjonalny jako narzędzie pomocnicze (Faza 2), ale nie jako twarda blokada.
D6 — Big-bang vs Strangler Fig
Pytanie: Jak wdrażamy funkcjonalność Lager do et-op?
| Opcja | Opis | Za | Przeciw |
|---|---|---|---|
| (a) Big-bang | Jedna implementacja (Faza 5) zastępuje zarówno et-lager jak i aktualny wh-staff w et-op. Cutover jednorazowy. | Prosta architektura; brak równoległego utrzymania | Ryzyko ~46 osobodni bez działającego produktu; brak rollback’u |
| (b) Strangler Fig (moduł po module) | Każdy ekran Lager jest implementowany w et-op jako osobny PR. Użytkownicy mogą być odsyłani do et-lager.vercel.app dla niezaimplementowanych modułów. | Ciągłe dostawy; rollback per-moduł | Dwupunktowy stan (~6-8 miesięcy dual maintenance) |
| (c) Feature flag + parallel run | Nowe ekrany dostępne za feature flagą. Et-lager pozostaje primary, et-op jako shadow. Cutover dopiero gdy wszystkie ekrany gotowe. | Zero-risk cutover | Wymaga feature flag infrastructure (mamy p24_feature_permissions?) |
Rekomendacja: (b) Strangler Fig — realizm wyceny (~46 osobodni real) wymaga iteracyjnych dostaw. et-lager pozostaje aktywny jako fallback. Moduły wdrażane w kolejności: stock/protocols (Faza 5a) → invoices (Faza 5b) → missing-products (Faza 5c). Cutover po Fazie 5c.
D7 — Limity Vercel/proxy + wspólna warstwa Intercars
Pytanie: Jak zarządzać Intercars API w et-op (nowe proxy w et-op vs shared via bms-4)?
| Opcja | Opis | Za | Przeciw |
|---|---|---|---|
| (a) Next.js API route w et-op (jak w Lager) | /api/intercars-proxy w et-op — analogicznie do Lager. INTERCARS_CLIENT_ID_SECRET w Vercel env et-op. | Izolacja; prosta migracja | Duplikacja proxy logiki; oba projekty potrzebują osobnych sekretów Intercars |
| (b) Shared proxy na bms-4 (n8n lub dedykowana usługa) | n8n workflow lub nowa Hono/Express usługa na bms-4 obsługuje Intercars. et-op używa wewnętrznego URL. | Jeden punkt obsługi Intercars; łatwiejsza rotacja sekretu; cache możliwy | Zależność od bms-4 uptime; SSRF risk przesunięty na bms-4; latency |
| (c) CF Worker jako Intercars proxy | Dedykowany CF Worker (intercars-proxy-worker) na koncie Cloudflare. Sekret trzymany jako CF Secret. | Globalny CDN; zero cold start; bez Vercel limits | Kolejny serwis do utrzymania; Intercars może blokować CF IP ranges |
Rekomendacja: (a) na start — analogicznie do Lager. Wyciągnięcie do shared proxy to osobna decyzja architektoniczna po weryfikacji limitów (Faza 4 spike). Vercel free tier: 100GB/miesiąc bandwidth, 1000 serverless invocations/day (Hobby) vs Vercel Pro (bez limitów) — sprawdzić tier et-op.
Do weryfikacji: czy et-op ma Vercel Pro (bez limitu invocations)? Jeśli Hobby, 1000 invocations/day może być za mało dla aktywnego użycia Intercars.
D8 — Workspaces GENERAL/ACCOUNTING → role vs p24_feature_permissions
Pytanie: Jak modelować workspace access control z Pinbox24 w et-op?
Lager używa workspace kontekstu z Pinbox24 API — użytkownik należy do workspace’ów (GENERAL, ACCOUNTING, itd.), co bramkuje dostęp do funkcji.
| Opcja | Opis | Za | Przeciw |
|---|---|---|---|
| (a) Rola Supabase per workspace | Każdy workspace to rola Supabase (wh_general, wh_accounting). Przypisanie roli = dostęp do workspace. | Spójne z Supabase RLS model | Wymaga synchronizacji Pinbox24 workspace membership → Supabase roles (gdzie/kiedy sync?) |
(b) p24_feature_permissions (istniejące w et-op) | Reusing istniejącego mechanizmu feature flags et-op (tabela p24_feature_permissions?). Workspace access to feature. | Reuse kodu; spójne z istniejącymi wzorcami et-op | Wymaga weryfikacji: czy p24_feature_permissions istnieje i jak działa w et-op? |
| (c) Pass-through: workspace info z Pinbox24 JWT | Przy każdym logowaniu Pinbox24, pobieramy workspace memberships z API i przechowujemy w Supabase session metadata. Kontrola dostępu server-side na podstawie JWT claims. | Zero drift między Pinbox24 a et-op | Każdy page load weryfikuje workspace — latency; zależy od Pinbox24 API availability |
Rekomendacja: (c) jako Faza 5 baseline — minimal viable, pass-through z Pinbox24. Opcja (b) jako ewolucja jeśli p24_feature_permissions jest odpowiednia (weryfikacja w Fazie 4).
Do weryfikacji przez właściciela: czy tabela p24_feature_permissions istnieje w et-op i co obsługuje?
D9 — Czy Faza 3 (stabilizacja Lager) ma sens?
Pytanie: Czy warto stabilizować et-lager (naprawiać P1/P2 bugi) przed portem do et-op?
Faza 3 obejmowałaby: token refresh, cookie/header fix, CI pipeline, routing cleanup, test coverage. Wycena: 0–5 osobodni.
| Opcja | Opis | Rekomendacja |
|---|---|---|
| (a) Pominąć Fazę 3 | Port Lager do et-op to okazja do naprawy — nie warto naprawiać skazańca | ZALECANE — Faza 3 to dług techniczny, który et-op i tak trzeba przepisać |
| (b) Realizować Fazę 3 | Stabilizacja przed portem zmniejsza zakres Fazy 5 | Uzasadnione tylko jeśli et-lager ma być utrzymywany przez >6 miesięcy po Fazie 0 |
Rekomendacja: pominąć Fazę 3. Et-lager zastępuje się modułem wh-staff w et-op — inwestycja w stabilizację Lager ma ROI ≤ 0. Wyjątek: jeśli właściciel planuje utrzymywać et-lager w produkcji przez ≥6 miesięcy po Fazie 1.
D10 — Które ekrany (/invoice-list, /invoices-list2, /invoice-view) są realnie używane?
Pytanie: Mamy zduplikowane ekrany faktur — które są w użyciu produkcyjnym?
| Route | Odpowiednik workspace | Status |
|---|---|---|
/invoice-list | /workspace/[id]/ (brak?) | Duplication root — prawdopodobnie stary widok |
/invoices-list2 | /workspace/[id]/invoices-list2 | ”v2” — prawdopodobnie nowszy |
/invoice-view | /workspace/[id]/invoice-view | Zduplikowany |
/invoices | brak w workspace | Root-only? |
Potrzebna weryfikacja przez właściciela:
- Który z widoków faktur jest domyślny (użytkownicy wchodzą przez który URL)?
- Czy
/invoice-list(root, bez workspaceId) jest w ogóle używany? - Czy
/invoices-list2to “docelowy” widok faktur (najnowszy)?
Rekomendacja dla Fazy 5: portować TYLKO widoki w użyciu. Zalecam portem zająć /workspace/[id]/invoices-list2 i /workspace/[id]/invoice-view jako kanoniczne — root-level duplicates pominąć. Potwierdzenie przez właściciela wymagane.
4. Proponowane issue-dzieci (do stworzenia PO akceptacji przez właściciela)
Faza 1 — Przeniesienie na GitHub (2,5 d)
Prerequisite: #2852 (OPEN — Intercars secret hardcoded) musi być zamknięty PRZED stworzeniem tego issue.
git filter-repowymagane do wyczyszczenia historii.
Issue 1.1: feat(et-lager): mirror repository from GitLab to GitHub with git history
- Scope:
git clone --mirrorz GitLab →git filter-repo --path src/constants/intercars.constants.ts --invert-paths→ push na nowe GitHub reporadieu/et-lager(lubet-lagerjako subpath) → weryfikacja historii - Prereq: zamknięty #2852, nowe repozytorium GitHub utworzone
- Labels:
infra-task(wymaga SSH/git push na bms-4 lub windows-dev) - Waga:
light
Issue 1.2: feat(et-lager): switch Vercel git source from GitLab to GitHub
- Scope: Vercel project
et-lager→ Settings → Git → zmiana git source na GitHub + usunięcie GitLab webhook → test deploy - Labels:
infra-task - Waga:
light
Issue 1.3: docs(et-lager): add CI pipeline (GitHub Actions: type-check, lint, build)
- Scope:
.github/workflows/ci.ymldla nowego repo et-lager —npm run type-check,eslint,npm run build; naprawić build script (set NODE_OPTIONS→cross-env) - Labels:
dev-issue - Waga:
light
Issue 1.4: docs(p24-infra): update et-lager-operations.md for GitHub migration
- Scope: aktualizacja
docs/et-lager-operations.md— nowe URLs, git source, obselete GitLab webhook - Labels:
dev-issue - Waga:
light
Faza 2 — Security review + baseline screenshots (3 d)
Issue 2.1: sec(et-lager): full security audit post-migration
- Scope: przegląd wszystkich 47+ API endpoints pod kątem auth gaps, injection, SSRF; weryfikacja że
INTERCARS_CLIENT_ID_SECRETusunięty z historii; audyt zależności npm (npm audit) - Labels:
sec,dev-issue - Waga:
heavy
Issue 2.2: test(et-lager): Playwright visual baseline — 37 pages screenshot contract
- Scope: Playwright setup w repozytorium et-lager; screenshot każdej z 37 stron przy zalogowanym test user; artefakty jako PR attachment;
lager-visual-acceptance-criteria.mdjako dokument referencyjny - Labels:
dev-issue - Waga:
heavy
Faza 4 — Spec + characterization tests w et-op (4,5 d)
Issue 4.1: design(et-op/wh-staff): Lager port architecture spec
- Scope: design document w
docs/plans/— mapowanie ekranów Lager → komponenty et-op; decyzje D1/D5-D10 zebrane i potwierdzone przez właściciela; schema Supabase dlamissingProducts+processedInvoices(migracja z MongoDB Atlas) - Labels:
plan,dev-issue - Waga:
heavy
Issue 4.2: test(et-op/wh-staff): characterization tests for Pinbox24/Intercars contract
- Scope: testy kontraktu HTTP dla Pinbox24 API endpoints używanych w Lager (snapshot request/response); testy Intercars OAuth flow; MSW mocks dla unit testów
- Labels:
dev-issue - Waga:
heavy
Issue 4.3: feat(et-op): Supabase migration — pinbox24_missing_products + pinbox24_processed_invoices
- Scope: migration SQL dla 2 tabel zastępujących MongoDB; RLS;
dev_r_servicesupdate; script migracji danych z Atlas → Supabase - Labels:
dev-issue - Waga:
heavy
Faza 5 — Implementacja w et-op (≈46 d, podzielona na sub-issues)
Faza 5 jest dekompozycją do podjęcia DOPIERO po zatwierdzeniu spec z Fazy 4.
Issue 5.1: feat(et-op/wh-staff): Pinbox24 auth layer — JWT login flow in Pages Router
- Scope: nowy hook
usePinbox24Auth, interceptor axios, token refresh (naprawienie P1 z Lager), server-side session storage Pinbox24 JWT w Supabase session
Issue 5.2: feat(et-op/wh-staff): stock + product lookup module
- Scope: port
/stock,/warehouse-products+/workspace/[id]/stock; shadcn DataTable; Pinbox24 register API
Issue 5.3: feat(et-op/wh-staff): protocols module (PZ/WZ/ZW + warehouse release)
- Scope: port
protocols,warehouse-release,protocol-release; et-opwh_protocolsintegration; Faza 5 nakłada na istniejące src/pages/wh-staff/*
Issue 5.4: feat(et-op/wh-staff): invoices module (list + view + close)
- Scope: port
invoices-list2,invoice-view,invoice-protocols; Intercars proxy; PDF download
Issue 5.5: feat(et-op/wh-staff): missing products + invoice processing
- Scope: port
missing-products,no-location-products; Supabase tables zamiast MongoDB Atlas
Issue 5.6: feat(et-op/wh-staff): i18n pl+de for all ported screens
- Scope: klucze i18n z Lager (1650 kluczy → ~500 kluczy po filtrze pl+de niekompletnych); tłumaczenia pl+de
Issue 5.7: feat(et-op/wh-staff): workspace access control (Pinbox24 workspace membership)
- Scope: implementacja D8 (wybrany wariant); page guards;
useAuthintegration
5. Podsumowanie ryzyk (ranking dla właściciela)
| Ryzyko | Prawdopodobieństwo | Wpływ | Mitygacja |
|---|---|---|---|
| Intercars secret w historii git — push na GitHub bez filter-repo | Wysoki | P0 (data leak) | Blokuje Fazę 1 — #2852 musi być zamknięty najpierw |
| App Router → Pages Router przepisanie | Wysoki | +20% nakład Fazy 5 | Shadcn działa w Pages Router; priorytet integracji istniejącego wh-staff |
| Niezgodny model auth Pinbox24 JWT vs Supabase | Wysoki | Faza 4 cała może być redesignem | D1 musi być podjęta i potwierdzona przed Fazą 4 |
| Nakładanie z istniejącym wh-staff w et-op | Średni | Duplikacja kodu, spory o “który ekran” | D5 (visual acceptance) + kontrakt w Fazie 4 |
| Praktyczny brak testów w Lager | Wysoki | Faza 5 bez regression safety | Faza 2 issue 2.2 + Faza 4 issue 4.2 tworzą safety net |
| Duplikacja ekranów faktur (root vs workspace) | Średni | Praca na błędnym screenie | D10 — właściciel musi wskazać kanoniczne ekrany |
6. Kolejne kroki
- Właściciel: przejrzyj decyzje D1, D5, D6, D8, D10 i zatwierdź rekomendacje lub wybierz alternatywy
- Po akceptacji D1-D10: stwórz issue-dzieci (Fazę 1 pierwsze — prereq: zamknięty #2852)
- Faza 1 startuje dopiero po: zamknięciu #2852 (Intercars secret rotation)
Wygenerowano przez bms-4 worker (job #13210) · 2026-10-13 · Faza 0 zamknięta