Files
Fuchs_Intranet/Fuchs/Docs/Decisions
StefanandClaude Sonnet 5 f407341f5f Parallelize invoice image fetch, add telemetry, generalize HtmlConverter
- InvoiceService.ResolveInlineImagesAsync now fetches an invoice's
  distinct whitelisted images concurrently (SemaphoreSlim-capped at 4)
  instead of one at a time. It ran inline on every invoice render,
  including repeated draft-preview renders, so N sequential mfr-portal
  round-trips could otherwise add N x latency to a user-facing request.
- Add fuchs.invoice.inlineimages.fetches (counter, tagged by outcome:
  success/http_error/bad_content_type/oversized/exception) and
  fuchs.invoice.inlineimages.resolve.duration (histogram) to
  FuchsTelemetry, matching the project's observability convention for
  outbound-HTTP operations.
- MigraDocExtensions.HtmlConverter's pre-resolved-image parameter is
  renamed inlineImages -> resolvedImages with generic docs: the
  converter fetches nothing and knows nothing about invoices — which
  images to resolve, and any whitelist/network policy, is entirely the
  caller's concern (InvoiceService, ADR 0018 today; any future caller
  tomorrow).
- Add tests asserting fetches actually overlap (not just faster) and
  that the new counter/histogram are recorded.
- Update ADR 0018 to describe the concurrent fetch, telemetry, and the
  generalized converter parameter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 21:17:09 +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.