86 lines
5.9 KiB
Markdown
86 lines
5.9 KiB
Markdown
# Changelog
|
|
|
|
## 0.9.1 — 2026-06-23
|
|
|
|
- **Fix:** `createEventSyncEngine`-Factory verdrahtet den `syncConsentLoader` jetzt automatisch gegen mana-auth (`fetchSyncConsent`), wenn `config.requireSyncConsent` gesetzt ist. Damit reicht in der App das eine Config-Flag — kein manuelles Loader-Wiring nötig (Parität zu iOS, wo die Engine den Settings-GET selbst macht). In 0.9.0 fehlte die Durchreichung über die Factory.
|
|
|
|
## 0.9.0 — 2026-06-23
|
|
|
|
- **Cloud-Sync-Opt-in-Gate (DSGVO Art. 25), Parität zu Web + iOS.** Neues `EventSyncConfig.requireSyncConsent` (Default `false` → abwärtskompatibel, kein Verhaltenswechsel für nicht-adoptierende Apps). Ist es gesetzt, synct die Engine nur mit expliziter Nutzer-Einwilligung mit dem Server: ohne Zustimmung läuft sie lokal-only (anonym, Events stauen in der Outbox), auch bei Login — `authMode()` liefert dann `Anonymous`. Die Einwilligung wird beim `start()` über den injizierten `syncConsentLoader` geladen (Helper `fetchSyncConsent(...)` liest mana-auth `GET /api/v1/settings`; App-Override vor globaler Präferenz, fehlend = aus; gleiche Quelle wie Web). Neu: `EventSyncEngine.setSyncConsent(granted)` (Konto-Toggle: `true` claimt anonyme Events + startet Sync wie `signIn`, `false` stoppt den Server-Sync, lokale Daten bleiben), `syncConsentRequired`, `hasSyncConsent`, pure `parseSyncConsent(json, appId)`. Schließt die Inkonsistenz, dass Native bisher per Default synct, Web aber Opt-in ist.
|
|
|
|
## 0.8.0 — 2026-06-17
|
|
|
|
- **402-Handling (kein aktives Cloud-Sync-Abo).** `EventSyncError.SubscriptionRequired` (Server `402`), `EventSyncEngine.onSyncRequired`-Hook + `isSyncRequired()`. Push/Pull behandeln 402 sauber: Events BLEIBEN in der Outbox (kein Verlust, KEIN Attempt-Increment), event-getriggerte Push/Pull werden unterdrückt, der Poll prüft weiter (force) → Auto-Recovery, sobald das Abo aktiv ist. Wire-Parität zu `@mana/event-sync` 0.9.0 + `mana-swift-event-sync` 0.9.0. Siehe `../mana/docs/SYNC_SETTINGS.md`.
|
|
|
|
## 0.7.0 — 2026-06-16
|
|
|
|
- `EventSyncEngine.purgeAggregatePrefix(idPrefix)` + `EventStore.purgeByAggregatePrefix` (Default no-op, InMemory override) — lokaler Klartext-Wipe per aggregateId-Prefix (A3). RoomEventStore-Override im Adapter.
|
|
|
|
## 0.6.0 — 2026-06-16
|
|
|
|
- `EventSyncEngine.shredScope(scopeId, shredAfterIso?)` — App-API zum Crypto-Shredding eines Scope-Sub-Keys (Mandant löschen). `null` → sofort (privat/Art. 17), sonst geplant (Firma/GeBüV-Frist). Via injizierter `shredScopeImpl` (Factory baut ScopeVaultClient).
|
|
|
|
## 0.5.0 — 2026-06-16
|
|
|
|
- **Per-Mandant-Crypto-Shredding (A3), Parität zu `@mana/event-sync` 0.7.0 +
|
|
`mana-swift-event-sync` 0.6.0:** `CryptoContext` + optionale `suspend`-
|
|
context-Varianten von `encryptPayload`/`decryptPayload` (Default forwarden zur
|
|
synchronen Basis → bestehende Provider + Tests unverändert). `ScopeVaultClient`
|
|
(Ktor: getOrMint/get/shred gegen `/encryption-vault/scopes/:appId/:scopeId/key`,
|
|
404→`ScopeNotFoundException`, 410→`ScopeShreddedException`).
|
|
`ScopedCryptoProvider` (delegiert pro Scope an eine `MasterKeyCryptoProvider`-
|
|
Instanz mit dem Sub-Key, Mutex-Cache, Master-Fallback; geschreddert → wirft).
|
|
`createScopedKeyProviderFromVault`. `EventSyncConfig.scopeResolver` → Factory
|
|
baut den Scoped-Provider; Context an emit/pull/reencrypt durchgereicht. Wire
|
|
identisch `enc:1:`, abwärtskompatibel, bestehende Tests grün.
|
|
|
|
## 0.4.0 — 2026-06-10
|
|
|
|
- **Decrypt-Failures sichtbar statt Silent-Skip** (Parität zu
|
|
`@mana/event-sync` 0.6.0 + `mana-swift-event-sync`): Ein nicht-
|
|
entschlüsselbares Event aus dem Pull wurde bisher via
|
|
`runCatching{}.getOrNull()` still verworfen — die App sah nie, dass ihr
|
|
Daten fehlen (der `enc:1`-Footgun). Jetzt:
|
|
- persistenter Zähler in Meta (`decrypt-failure-count`, `…-last-at`,
|
|
`…-last-event`), abfragbar via `stats()` → `decryptFailures` /
|
|
`decryptFailureLastAt`, Reset via `clearDecryptFailures()`;
|
|
- neuer Hook `onDecryptFailure: ((DecryptFailure) -> Unit)?` pro Event,
|
|
zusätzlich feuert `onError` mit `EventSyncError.DecryptFailed(eventId)`;
|
|
- `decryptPulledPayload(payload, eventId, provider)` wirft auch, wenn der
|
|
Provider den Ciphertext unangetastet durchreicht (NoOp ohne Key) —
|
|
vorher wäre der `enc:1:`-String als „Plaintext" in der Projektion
|
|
gelandet.
|
|
Der Pull-Cursor wandert trotz Failures weiter — Sync hängt nicht fest.
|
|
|
|
## 0.2.0 — 2026-06-04 (Phase 2 Teil 2)
|
|
|
|
- **`EventSyncEngine`** — vollständige Orchestrierung (Port von Swift):
|
|
Anonymous-First-Identität, Emit (lokal + Outbox + Crypto-Wire), Pull-Loop
|
|
(decrypt + Projektion + Cursor), `signIn`-Claim (anon→sub Re-Attribution +
|
|
Re-Encrypt + Drain), Poll-Timer, Soft-Fail, Schema-Outdated-Stop,
|
|
Crypto-Degraded-Outbox-Pause, Aggregate-Change-Listener.
|
|
- **`EventStore`** (Interface) + **`InMemoryEventStore`** — Event-Log +
|
|
Outbox + Meta + Retention; Room-Adapter folgt im App-Modul.
|
|
- **`SyncTransport`** / **`SyncWebSocket`** — Abstraktionen; `SyncHttpClient`
|
|
implementiert `SyncTransport`.
|
|
- **`createEventSyncEngine(...)`** — Produktions-Verdrahtung (HTTP + Vault).
|
|
- `EventSyncConfig` / `AuthMode` / `ClaimResult` / `EngineStats` /
|
|
`AnonymousRetention`.
|
|
- 36 Tests (inkl. Crypto-Roundtrip über zwei Geräte, signIn-Claim,
|
|
Schema-Outdated). Braucht mana-kotlin-core 0.2.0.
|
|
|
|
## 0.1.0 — 2026-06-04 (Phase 2 Teil 1)
|
|
|
|
Erstes Skelett. Phase 2 (Teil 1) des Android-Plans
|
|
([`WORDECK_ANDROID_GREENFIELD.md`](../mana/docs/playbooks/WORDECK_ANDROID_GREENFIELD.md)).
|
|
|
|
- `MasterKeyCryptoProvider` (AES-GCM-256) + `NoOpCryptoProvider` — wire-
|
|
kompatibel zu Swift/TS, byte-genau bewiesen per WebCrypto-Golden-Vektor.
|
|
- `VaultClient` + `createMasterKeyProviderFromVault` (Key-Fetch, ZK-Erkennung).
|
|
- `EventEnvelope` + `ActorContext` + flexibler Long-Serializer
|
|
(sequenceNumber als String oder Zahl).
|
|
- `Ulid` (Port der Swift-Generierung).
|
|
- `SyncHttpClient` (append/pull gegen mana-sync, 422→SchemaOutdated).
|
|
- 26 Tests grün.
|
|
|
|
Offen (Teil 2): WebSocket-Client, Room-EventStorage, EventSyncEngine.
|