Files
Fuchs_Intranet/Fuchs/Docs/Decisions
StefanandClaude Sonnet 5 bcf1f2dbb6
Playwright Tests / test (push) Canceled after 0s
feat: migrate DB error logging onto the generic OCORE MultiLogger SQL sink
Retires Fuchs_intranet.debug_log() and every direct EXECUTE [dbo].[fds__admin_logdebug]
call in favor of a single path: ILogger. A new SQL log sink (OCORE.MultiLogger.SqlLoggerProvider,
gated by Fuchs:Logging:SqlSink:Enabled, default on) mirrors every _logger.LogWarning/-Error/
-Critical call into [dbo].[fds__debuglog] via a new fds__admin_logdebug_ext proc, at Warning+.

- Program.cs registers the sink and RequestLogScopeMiddleware (request id/path/authenticated
  user, pushed after UseAuthentication) so every log line in a request — including ones written
  deep inside OCORE's SQL helpers — is attributed automatically.
- FIS_SQLOptions, IntranetController.Do's catch-all, PdfPreviewAsync, and the banking-upload
  handlers now log once, with an explicit EventId preserving the exact CodeReference text the
  retired debug_log() calls used to write, so existing dashboards/queries over fds__debuglog
  keep working unchanged.
- Fuchs_DataService/FdsMfr.cs's FdsSqlOptions had the identical double-write hazard (it's hosted
  in the same process per ADR 0010) — the original 2026-09-16 log review's mfr__getSchema/
  fds__getUpdateableRequests deadlock rows came from exactly this class. Fixed the same way.
- fds__debuglog gains LogLevel/Machine/Category/Account/AuthUser/IsDebug columns; the legacy
  fds__admin_logdebug proc is left in place unused, not dropped.
- FdsDebug.DebugLog (Fuchs_DataService's other ~9 call sites) deliberately left on its direct
  DB-write path — no ILogger call sits alongside it there, so no duplication risk today.

See ADR 0024 (supersedes 0023) and Docs/Concepts/error-logging-pipeline.md.

New tests: ErrorLoggingTests (FIS_SQLOptions), FdsSqlOptionsTests, RequestLogScopeMiddlewareTests.
694/694 pass (the 4 PdfPipelineTests failures seen under full-suite parallel runs are a
pre-existing, unrelated PdfSharp global-font-resolver test-isolation flake — they pass both
individually and in most full-suite runs).

Bumps the OCORE submodule to 3137b56 (SQL sink hardening: redaction matches short fragments
as whole identifier segments, per-entry-tolerant serialization, lazy dataSerialized, opt-in
SqlLoggerOptions.IncludeCategory, LogEntry.Category/AuthUser capture).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 17:20:06 +02:00
..

Decisions

This folder holds Architecture Decision Records (ADRs) — short, immutable records of a specific technical choice, why it was made, and what it implies going forward.

What belongs here

A decision, not a how-to. If it answers "why do we do X this way, and what else did we consider," it's a decision. If it explains "how subsystem X currently works," that belongs in ../Concepts instead (and a decision often triggers a concept doc to be created/updated).

File naming

NNNN-kebab-case-title.md, four-digit zero-padded, sequential across the whole folder (0001-..., 0002-...). Never reuse or renumber.

Required YAML frontmatter

Every decision file starts with:

---
status: Accepted        # Proposed | Accepted | Superseded
date: 2026-07-03         # date the decision was accepted
applyTo:                 # glob(s) — files/areas this decision governs
  - "Fuchs/Notifications/**"
supersededBy: ""         # filename of the decision that replaced this one, if any
---

Agents (Claude, Copilot, Codex) must scan the YAML frontmatter of every file in this folder first (cheap — no need to read the body) and only read the full body of decisions whose applyTo glob matches the files they're about to touch, or whose subject is otherwise clearly relevant to the task. This keeps decision-following cheap even as the folder grows.

Body template

# NNNN — Title

## Context
What problem/situation forced a choice.

## Decision
What was decided, stated plainly.

## Consequences
What this implies for future code — constraints, follow-ups, trade-offs
accepted knowingly.

## Alternatives considered
Options that were rejected and why (optional but preferred).

Rules

  • Decisions are immutable once Accepted. Do not edit the Decision/ Consequences of an existing file to reverse it. Instead, write a new decision, set its applyTo/subject accordingly, and set the old file's status: Superseded + supersededBy: NNNN-new-file.md.
  • Follow existing decisions. Before implementing anything in an area covered by an Accepted decision, read it and conform to it. If you believe a decision is wrong, raise it with the user rather than silently deviating.
  • Capture new decisions as they happen. Whenever the user (or the code you're writing) settles a non-obvious architectural or cross-cutting choice — not a routine implementation detail — add a decision here in the same change, and create/update the matching concept doc in ../Concepts.