diff --git a/mbproxy/docs/design.md b/mbproxy/docs/design.md
index a84c64f..94483f3 100644
--- a/mbproxy/docs/design.md
+++ b/mbproxy/docs/design.md
@@ -218,36 +218,10 @@ Serilog wired through the Microsoft.Extensions.Logging bridge:
- **Console sink** for interactive `--console` runs.
- **Rolling-file sink** under `%ProgramData%\mbproxy\logs\`.
-- **Default level** Information. Per-PLC and per-client scopes via `LogContext.PushProperty("Plc", name)` / `("Client", remoteEp)` so log lines are greppable across the fleet.
+- **Windows Event Log sink** for Error+ events when the service is running under `Microsoft.Extensions.Hosting.WindowsServices`.
+- **Default level** Information. Properties (`Plc`, `RemoteEp`, etc.) are emitted per message via `[LoggerMessage]` templates so log lines are greppable across the fleet.
-Stable event names (keep these stable so log queries don't churn):
-
-| Event | Level | Properties |
-|--------------------------------------|---------|---------------------------------------------|
-| `mbproxy.startup.bind` | Info | `Plc`, `Port` |
-| `mbproxy.startup.bind.failed` | Error | `Plc`, `Port`, `Reason` |
-| `mbproxy.listener.recovered` | Info | `Plc`, `Port`, `AttemptCount` |
-| `mbproxy.client.connected` | Info | `Plc`, `RemoteEp` |
-| `mbproxy.client.disconnected` | Info | `Plc`, `RemoteEp`, `Reason` |
-| `mbproxy.backend.failed` | Warning | `Plc`, `Reason` |
-| `mbproxy.rewrite.partial_bcd` | Warning | `Plc`, `Address`, `ClientStart`, `ClientQty` |
-| `mbproxy.rewrite.invalid_bcd` | Warning | `Plc`, `Address`, `RawValue`, `Direction` |
-| `mbproxy.exception.passthrough` | Info | `Plc`, `Fc`, `ExceptionCode` |
-| `mbproxy.config.reload.applied` | Info | `PlcsAdded`, `PlcsRemoved`, `TagDelta` |
-| `mbproxy.config.reload.rejected` | Error | `Reason` |
-| `mbproxy.admin.bind.failed` | Error | `Port`, `Reason` |
-| `mbproxy.multiplex.backend.connected` | Info | `Plc`, `Host`, `Port` |
-| `mbproxy.multiplex.backend.disconnected` | Warning | `Plc`, `UpstreamCount`, `InFlightCount`, `Reason` |
-| `mbproxy.multiplex.saturated` | Error | `Plc`, `RemoteEp` (16-bit TxId space full) |
-| `mbproxy.multiplex.request.timeout` | Warning | `Plc`, `ProxyTxId`, `OriginalTxId`, `Fc`, `ElapsedMs` |
-| `mbproxy.coalesce.hit` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty`, `PartyCount` |
-| `mbproxy.coalesce.miss` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty` |
-| `mbproxy.coalesce.dead_upstream` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty` |
-| `mbproxy.cache.hit` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty` |
-| `mbproxy.cache.miss` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty` |
-| `mbproxy.cache.store` | Debug | `Plc`, `UnitId`, `Fc`, `Start`, `Qty`, `TtlMs` |
-| `mbproxy.cache.invalidated` | Debug | `Plc`, `UnitId`, `WriteStart`, `WriteQty`, `Count` |
-| `mbproxy.cache.flushed` | Info | `Plc`, `Reason`, `Count` |
+Event names follow the convention `mbproxy..[.]` and are part of the operator contract — once shipped they don't churn (renames require a major version bump). The full catalog of stable event names, their levels, properties, and operator implications lives in [`Reference/LogEvents.md`](Reference/LogEvents.md); each `*LogEvents.cs` static class (e.g. `MultiplexerLogEvents`, `CoalescingLogEvents`, `CacheLogEvents`, `RewriterLogEvents`) is the source of truth.
## Status page — read-only HTTP endpoint