5.9 KiB
5.9 KiB
Changelog
0.9.1 — 2026-06-23
- Fix:
createEventSyncEngine-Factory verdrahtet densyncConsentLoaderjetzt automatisch gegen mana-auth (fetchSyncConsent), wennconfig.requireSyncConsentgesetzt 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(Defaultfalse→ 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 dannAnonymous. Die Einwilligung wird beimstart()über den injiziertensyncConsentLoadergeladen (HelperfetchSyncConsent(...)liest mana-authGET /api/v1/settings; App-Override vor globaler Präferenz, fehlend = aus; gleiche Quelle wie Web). Neu:EventSyncEngine.setSyncConsent(granted)(Konto-Toggle:trueclaimt anonyme Events + startet Sync wiesignIn,falsestoppt den Server-Sync, lokale Daten bleiben),syncConsentRequired,hasSyncConsent, pureparseSyncConsent(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(Server402),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-sync0.9.0 +mana-swift-event-sync0.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 injiziertershredScopeImpl(Factory baut ScopeVaultClient).
0.5.0 — 2026-06-16
- Per-Mandant-Crypto-Shredding (A3), Parität zu
@mana/event-sync0.7.0 +mana-swift-event-sync0.6.0:CryptoContext+ optionalesuspend- context-Varianten vonencryptPayload/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 eineMasterKeyCryptoProvider- 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 identischenc:1:, abwärtskompatibel, bestehende Tests grün.
0.4.0 — 2026-06-10
- Decrypt-Failures sichtbar statt Silent-Skip (Parität zu
@mana/event-sync0.6.0 +mana-swift-event-sync): Ein nicht- entschlüsselbares Event aus dem Pull wurde bisher viarunCatching{}.getOrNull()still verworfen — die App sah nie, dass ihr Daten fehlen (derenc:1-Footgun). Jetzt:- persistenter Zähler in Meta (
decrypt-failure-count,…-last-at,…-last-event), abfragbar viastats()→decryptFailures/decryptFailureLastAt, Reset viaclearDecryptFailures(); - neuer Hook
onDecryptFailure: ((DecryptFailure) -> Unit)?pro Event, zusätzlich feuertonErrormitEventSyncError.DecryptFailed(eventId); decryptPulledPayload(payload, eventId, provider)wirft auch, wenn der Provider den Ciphertext unangetastet durchreicht (NoOp ohne Key) — vorher wäre derenc:1:-String als „Plaintext" in der Projektion gelandet. Der Pull-Cursor wandert trotz Failures weiter — Sync hängt nicht fest.
- persistenter Zähler in Meta (
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;SyncHttpClientimplementiertSyncTransport.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).
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.