A stocktake of the machine-readable Jahresrechnung in Switzerland · 255 public documents, every statement with its source and its date

Two standards, 26 cantons · Part 12 of 14

12 · What we built — and what it cannot do

Anyone who writes about schema drift must supply their own score with it. So that comes first, unvarnished.

For the 42 line items of the OR-Mindestgliederung our generator emits 42 paths into an eCH-0276 instance. Against the V1.0.0 version published on ech.ch, 42 of 42 hold. Against the version shipped inside the swissdec Transmitter package of 06.03.2026 — eCH-0276-1-0-4_20260115.xsd —, 40 of 42 hold. Against the V2.0.0 draft of 23.07.2026, 39 of 42 hold. Three files, two of them with an identical namespace http://www.ech.ch/xmlns/eCH-0276/1 and an identical version statement, all three called eCH-0276 — and against two of them our file is faulty. This is the only paragraph in this chapter that speaks against us, and therefore the only one a reader should believe without further ado.

The provenance of our build target we recomputed ourselves, we did not assert it. The eCH-0276-1-0.xsd that sits in our code and the file pulled from ech.ch carry the same SHA-256:

14a0d6cb3abce06b2bb55c5b9a311ec79ceea42d16314e5f7f705d1fea2accad

So we build against the published version of the standard. Part 10 showed what that is worth: the swissdec container binds the same namespace via schemaLocation to a different file. Anyone travelling via the Distributor is not validating against what stands on ech.ch. Our 42/42 hold against the norm; our 40/42 hold against the channel.

The artefact we have and nobody has published

Between the OR-Jahresrechnung, the declaration format eCH-0276 and the XBRL CH-Taxonomie there is publicly not one line that brings all three together. We have it: mapping-42-to-ch-taxonomy.csv, 42 rows, each with the eCH-0276 path and the ct: concept of the CH-Taxonomie on the same row, plus balance-sheet side and context type.

The distribution, counted again today: 38 DIRECT · 2 CONTEXT · 2 DERIVE. 30 instant, 12 duration. 22 credit, 20 debit. 42 keys land on 41 different ct: concepts — gewinnvortrag and gewinnvortrag_neu hit the same concept ct:ProfitOrLossCarriedForward and are separated by the context date alone, start of period against end of period. eCH-0276 needs two elements for that, XBRL needs one concept and two contexts. That is not a nicety, that is the difference between a form field and a data model.

In the same directory sits the counter-evidence, and it belongs with it: ch-taxonomy-uncovered-concepts.txt, 167 concepts of the CH-Taxonomie that our 42-key surface does not cover — from ct:AdvertisingExpense through ct:CapitalLossesOnInvestments to ct:ChangesInventoriesUnfinishedFinishedGoodsAndUnbilledServices. A mapping that does not count its own gap is a sales document.

The two DERIVE rows are the most interesting, because they show where a mapping honestly stops. Verbatim from the notes column:

«ct:OperatingIncome = ‹Betrieblicher Ertrag, insgesamt› is BROADER than our eCH totalOperatingRevenueFromDeliveriesAndServices: it also rolls up OtherOperatingIncome + ChangesInventories … Not the same number unless those are nil.»

«BALANCE-SHEET concept (Bilanzgewinn), instant. Group 400 has NO ‹zur Verfügung der GV› total; in XBRL it is the roll-up ProfitOrLossCarriedForward(start) + ProfitOrLoss.»

Two standards describing the same country, and in two of 42 places the same German label does not mean the same figure. Anyone who holds the two formats to be interchangeable has not laid them side by side.

The order of magnitude, because it is a fact

The CH engine is 494 lines across six modulesline_items.py 150, structured_input.py 123, preview.py 97, engine.py 70, eligibility.py 25. The work is not in the code. It is in the mapping, and the mapping is a reading job on other people's documents.

In engine.py there is one line that sets the whole frame:

submitted: bool = False   # ALWAYS False — CH is generate-only

We generate a file. We transmit nothing. We have never imported a file into a cantonal portal — not in Zürich, not anywhere else, in no format. Everything in this text stands on documents, not on a test.

Where we refuse — and where the canton says the same

The sharpest design decision in our generator is a refusal. Verbatim from our source, line_items.py:

«Die Gewinnverwendung ist ein Beschluss Ihrer Organe, keine Rechnung — eBilanz Fabrik unterstellt sie nicht.» (the appropriation of profit is a resolution of your governing bodies, not an account — eBilanz Fabrik does not assume it)

If the Gewinnverwendung is missing, the run aborts instead of assuming «keine Ausschüttung» (no distribution). Software that quietly fills register E with zeros puts a substantive statement into a file that goes to the tax administration.

And now beside it, formulated independently of it, the Steueramt of the Kanton Zürich in its questions and answers of 08.09.2025, on the question of how the statements get into the return from tax year 2025 onwards:

«Gemäss aktuellem Informationsstand wird XBRL entsprechende Informationen enthalten. Dort wo diese Informationen nicht enthalten sind, werden manuelle Eingaben (z.B. für Dividenden) oder das Hochladen von zusätzlichen Beilagen möglich sein.» (on current information XBRL will contain corresponding information; where that information is not contained, manual entries — e.g. for dividends — or the upload of additional attachments will be possible)

Two houses, the same point, the same answer: the dividend does not come out of the bookkeeping. It comes out of a resolution, and a resolution is something somebody types in.

Why «auf Knopfdruck» (at the push of a button) cannot add up arithmetically

This is not a value judgement, it is a count. eCH-0276 V1.0.0 declares 890 distinct element names (counted today with an XML parser over the published XSD, not with grep). The XBRL CH-Taxonomie declares 453 concepts in the 2024-06-23 version and 465 in the 2025 version.

The declaration format is roughly twice the size of the Jahresrechnung taxonomy. Well over half of the target fields have no source in the books — because it was never there. The SSK rule set shows the same picture from the other side: 401 of its 1'432 rules fall on the dialogues L (Steuerausscheidung) and P (verdecktes Eigenkapital) alone, that is, on matters no bookkeeping knows. An E-Bilanz fills the Jahresrechnung. It does not fill the Steuererklärung.

The only externally counted part of our record

Everything named so far we measured ourselves. There is exactly one figure about us that an authority collected: the monthly Herstellerstatistik of the German tax administration, delivered on 03.08.2026 for the July 2026 period. It counts real payload blocks only — test cases are excluded — and shows 15 for us.

Our reconciliation against it: 19 production attempts, minus 4 certificate cases rejected by ELSTER, gives 15 accepted transmissions, against 15 invoiced filings, with identical Transferticket sets. Zero deviation. In the language we otherwise use: 15 e-Bilanzen for 14 companies, officially counted — one company filed a Berichtigung afterwards, which counts twice.

What the figure is not: no Bescheid, no audit report, no statement about whether a tax authority accepted the content. It counts what the receiving server accepted — no more, and we ascribe no more to it either.

And the limit belongs with it, otherwise the figure is an assertion: «Ein Monat ohne Verkehr und ein weggelassener Monat sehen im Bericht gleich aus.» (a month with no traffic and an omitted month look the same in the report) Any argument we would draw from a missing month would be an argument from silence — and is marked as such.

This German base is also what carries the Swiss effort estimate at all: a production XBRL adapter accepted by ERiC with 1'028 lines, already emitting xbrli:xbrl, link:schemaRef, instant and duration contexts, xbrli:entity/identifier with scheme URI, iso4217 units as well as decimals= and unitRef=. None of that has to be invented for the Swiss side.

What it does not carry stands in our own effort note of 04.08.2026. Seven working days for a CH XBRL adapter are estimable; the filing is not:

«‹Days› buys a file that Arelle validates offline. It does not buy a filing.»

«Arelle ist ein Spezifikations-Orakel, kein Akzeptanz-Orakel. Eine Zahl für Teil B zu nennen hiesse, einen Erfolg zu behaupten, den ich nicht wissen kann.» (Arelle is a specification oracle, not an acceptance oracle; naming a figure for part B would mean claiming a success I cannot know)

In Germany EricPruefe closes that gap — a check call that confirms acceptance in advance. For the Swiss side our corpus contains no published tool with that function; whether one exists that we did not pull is untested.

The watch — with the correction that goes with it

So that this text stays checkable, on 04.08.2026 we built a watcher: 10 sources (two Zendesk APIs, six page counts, two asset hashes) and 8 word-boundary signal terms. Baseline recorded 04.08.2026 20:58:32 +0200. The honesty rule stands in the source code and is publishable verbatim:

«Silence means nothing changed — never that the check failed. A fetch failure is reported as manual-check-due, never as green.»

And the correction that gets published with it: the watch does not run daily. There is no launchd plist, no cron entry, no entry in expected-crons.json. It ran once, to write the baseline. Anyone who wants to check whether we mean it does not look at this page, but at whether the next report appears.

The baseline itself is the falsification basis for Part 14. zh-help: 70 articles, all eight terms 0. zh-jp and zh-umsteigen: all eight 0. drtax-help: eCH-0276 0, XBRL 0, E-Bilanz 0. ow-publik: E-Bilanz 5. swissdec: E-Bilanz 42. The first figure that moves decides more about the next two years than everything that stands in this chapter.