# KISA Connector Observability & Localisation

The KISA/KNVD connector now ships with structured telemetry, richer logging, and a localisation brief so Docs/QA can extend operator material without reverse-engineering the source.

## Telemetry counters

All metrics are emitted from `KisaDiagnostics` (`Meter` name `StellaOps.Feedser.Source.Kisa`).

| Metric | Description | Tags |
| --- | --- | --- |
| `kisa.feed.attempts` | RSS fetch attempts per scheduled job. | — |
| `kisa.feed.success` | Successful RSS fetches (increments even when no new items). | — |
| `kisa.feed.failures` | RSS fetch failures. | `reason` (exception type) |
| `kisa.feed.items` | Number of items returned by the RSS window. | — |
| `kisa.detail.attempts` | Advisory detail fetch attempts. | `category` (Hangul category from RSS) |
| `kisa.detail.success` | Detail payloads fetched and persisted. | `category` |
| `kisa.detail.unchanged` | HTTP 304 responses reused from cache. | `category` |
| `kisa.detail.failures` | Detail fetch failures or empty payloads. | `category`, `reason` |
| `kisa.parse.attempts` | Documents pulled from Mongo for parsing. | `category` |
| `kisa.parse.success` | Documents parsed into DTOs. | `category` |
| `kisa.parse.failures` | Download or JSON parse failures. | `category`, `reason` |
| `kisa.map.success` | Canonical advisories persisted. | `severity` (e.g. `High`, `unknown`) |
| `kisa.map.failures` | Mapping or DTO hydration failures. | `severity`, `reason` |
| `kisa.cursor.updates` | Published cursor advanced after ingest. | — |

> `category` tags surface the original Hangul labels (for example `취약점정보`), normalised to NFC. Downstream dashboards should render them as-is; do not transliterate or trim.

## Logging patterns

- `Information` level summary when the RSS feed completes (`ItemCount`), on each persisted detail document (IDX, category, documentId), and when a canonical advisory is written (IDX/severity).
- `Debug` level logs capture cache hits (304) and cursor movements (`Published` timestamp).
- `Warning` level emits when a document or DTO is missing so operators can correlate with parse/map counters.
- `Error` level retains exception context for feed/detail/parse/map failures; state repository backoffs are still applied.

The messages use structured properties (`Idx`, `Category`, `DocumentId`, `Severity`) so Grafana/Loki dashboards can filter without regex.

## Localisation notes for Docs & QA

- Hangul fields (`title`, `summary`, `category`, `reference.label`, product vendor/name) are normalised to NFC before storage. Sample category `취약점정보` roughly translates to “vulnerability information”.
- Advisory HTML is sanitised via `HtmlContentSanitizer`, stripping script/style while preserving inline anchors for translation pipelines.
- Metrics carry Hangul `category` tags and logging keeps Hangul strings intact; this ensures air-gapped operators can validate native-language content without relying on MT.
- Fixtures live under `src/StellaOps.Feedser.Source.Kisa.Tests/Fixtures/`. Regenerate with `UPDATE_KISA_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Kisa.Tests/StellaOps.Feedser.Source.Kisa.Tests.csproj`.
- The regression suite asserts canonical mapping, state cleanup, and telemetry counters (`KisaConnectorTests.Telemetry_RecordsMetrics`) so QA can track instrumentation drift.

For operator docs, link to this brief when documenting Hangul handling or counter dashboards so localisation reviewers have a single reference point.
