Co dokładnie zmienialiśmy w każdej wersji SISL Time Machine — bez marketingowych okrągłych zdań, z konkretnymi nazwami plików, klas, kolumn SQL i endpointów.
password_hash, rp_token, confirmation i liczniki prób logowania twardo zablokowane w DeltaExtractor — audyt klientów nigdy nie może stać się wyciekiem poświadczeń.
catalog_category_save_after rejestruje zmiany nazwy, statusu, rodzica, url_key, pozycji. Tu chowają się drogie pomyłki: ktoś wyłącza kategorię albo przepina drzewo i sklep cicho traci całą sekcję nawigacji.
CategoryRepository->save() — pełny plugin chain + audit-of-audit (samo cofnięcie też się zapisuje jako event ze źródłem rollback).
/metrics w formacie Prometheus/OpenMetrics: events_ingested_total{entity_type,source}, rollbacks/replays/timelines, build_info, uptime. Zero dodatkowych zależności — service zostaje jednym samodzielnym binarnym plikiem.
/health/deep — pełna transakcja write→read→verify→delete + liczba partycji. Zielony = „ta instancja realnie przyjmie event", nie tylko „PG odpowiada SELECT 1". Kubernetes/Swarm wypchnie półmartwą instancję zamiast cicho gubić eventy.
LOG_FORMAT=json) — jednoliniowe, gotowe do ELK / Splunk / Loki. Domyślnie zostaje czytelny format dla dev.
EventContextResolver — wspólna logika who/where-from dla observerów produktu i kategorii (ProductSaveAfter schudł z ~200 do ~75 linii). Suite testów .NET: 274 zielone (+17 dla MetricsCollector, w tym sanityzacja wrogich labeli i 1000-wątkowy test bezstratności).
license.sisl.pl/check (Traefik dokleja prefix → backend /api/licenses/check). Poprzedni default sisl.pl/api/licenses/check + ścieżka /api/licenses/check dawały podwójny prefix i 404. Ujednolicone z Optima Connector.
obscure (backend Encrypted) — Magento odszyfrowuje je samo przy odczycie, a Helper wołał decrypt() drugi raz, zamieniając klucz w binarny śmieć (crash json_encode: „Malformed UTF-8”). Usunięte — czytamy wartość wprost, jak Sisl_Optima.
https://license.sisl.pl (config.xml + Helper). Zweryfikowane e2e na żywym serwerze: valid:true, Ed25519 verified:true.
rollback, HMAC, REST API, Tenant ID, base64, event) zachowane bo admin Magento ich oczekuje.
admin_ui → „Panel admina”, cli → „CLI / skrypt”, cron → „Zadanie cykliczne (cron)”, unknown → „Nieznane”.
system.xml: numerowane podgrupy („1. Ogólne”, „2. Połączenie z usługą”, „3. Zakres przechwytywania”), wszystkie field labele + commenty po polsku. „coming soon” → „dostępne wkrótce”.
GET /api/v1/analytics/overview?tenant=X&days=30&topN=10 w .NET service. Pięć SQL aggregations w jednym round-tripie — istniejące indeksy (events_entity_lookup, events_actor_recent, events_source_recent) pokrywają wszystkie zapytania.
sisl_changelog_lite w MySQL, bez microservice'u, bez rollbacku. Wbudowany upgrade CTA → Time Machine PRO. Top-of-funnel lead generation.
SISL-TMC-XXXX-XXXX-XXXX-XXXX. Bez waznego klucza eventy nie sa wysylane do .NET service'u, a rollback jest zablokowany.
sisl_timemachine_check_license o 03:00 odnawia werdykt — inline <schedule> w crontab.xml, dziala na fresh install bez interwencji admina.
EventSender::send robi silent skip + log warning (capture w spokoju czeka na reaktywacje), Rollbacker::rollbackProduct rzuca RollbackException nawet dla dry-run — admin UI dostaje HTTP 409 z czytelnym komunikatem.
rollback, sam rollback też można cofnąć w przyszłości.
RollbackAction.php zwraca już pełny plan (sku, as_of, events_replayed, changes_planned). To wyłącznie warstwa prezentacji w timeline.phtml.
from → to. Zielony badge now = ta zmiana wciąż obowiązuje, bursztynowy = została później nadpisana.
Timeline.php ładuje produkt raz, mapuje pola, przekazuje do bloku jako current_values. Brak per-event repository call.
events.source w PG: admin_ui / rest_api / rollback / cron / cli / unknown. Migracja 002 idempotentna — auto-load w docker-entrypoint-initdb.
admin:42.
RollbackContext singleton — Rollbacker oznacza swoje save'y żeby observer wiedział, że to nie zwykła edycja w panelu.
RollbackContext > area code crontab > URL /rest/|/soap/|/graphql > admin session > PHP_SAPI cli > unknown. Resolution order matters — rollback always happens inside an admin session.
sisl/timemachine-service:0.5.0.
deploy/ dla klienta: docker-compose.yml, .env.example, migrations/, INSTALL.md. cp .env.example .env && docker compose up -d i działa.
INSTALL.md pokrywa Linux Docker, Windows Server (Docker Desktop) i natywny Windows (Windows Service + EDB PostgreSQL).
openssl rand -base64 32) lub compose odmówi startu.
.env.
/admin/sisl_timemachine/product/timeline z renderowaną historią eventów per produkt + AJAX rollback flow z dry-run preview.
Sisl_TimeMachine::timemachine_admin.
from → to per pole, status pill per event, JS confirmation flow przed apply.
Rollbacker rekonstruuje stan encji o czasie T (przez .NET replay), aplikuje przez ProductRepository->save() — odpalają się wszystkie pluginy / walidacje / observery.
from values pierwszego diffu.
GET /api/v1/replay/{type}/{id}?at=ISO — pure replay, applies events in order, zwraca rekonstruowany stan pól o danym czasie.
GET /api/v1/timeline/{type}/{id} — raw event list newest-first, z paginacją.
catalog_product_save_after + DeltaExtractor (per-attribute diff, blacklist internal fields, skip from: null dla istniejących encji).
/health + POST /api/v1/events. HMAC-SHA256 middleware (constant-time MAC + ±60s clock skew).
events table z monthly partitions, GIN index na JSONB delta, dedup table dla idempotency.
event_ids — partitioned UNIQUE musiałoby zawierać partition key (psuje dedup). Claim przez CTE INSERT … ON CONFLICT DO NOTHING.
Roadmap pokazuje co planujemy w v0.8 (multi-entity capture), v0.9 (snapshots + bulk rollback) i v1.0 (publiczna premiera Q3 2026). Każde major-version upgrade jest w cenie subskrypcji.