ED02 - The SME Organizational Model: Tenants, Spheres, Roles

Problem

An entrepreneur founds an organization - and faces the question: How do I structure my organization so that compliance obligations are mapped in a cleanly separated, traceable, and audit-proof manner?

Current practice in the SME sector knows no clean separation:

Key Message

Structuring an organization as a GitCover federation means: Tenant (organization), Sphere (area of activity for non-profits) and Role (function of the actor) are defined as mandatory fields of every artifact - not as optional metadata. Git hooks check on every commit that the separation is complete. This creates Compliance by Design: The structure of the organization is anchored in the structure of the repo.

Compliance by Design: Tenant, sphere, and role are not labels added afterwards - they are structural mandatory fields without which an artifact is not accepted into the repo.

The Three-Level Model: Tenant, Sphere, Role

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#FBFAF7','primaryTextColor':'#0F1B33','primaryBorderColor':'#6B7280','lineColor':'#6B7280'}}}%% flowchart LR A["Artefakt
(Beleg, Tagebucheintrag, Grundbuch-Eintrag)"] A --> T["Tenant
Welche Organisation?"] A --> S["Sphäre
Welcher Tätigkeitsbereich?
(nur gemeinnützig)"] A --> R["Rolle
In welcher Funktion handelt der Akteur?"] T --> T1["ORG-1 (KMU)"] T --> T2["ORG-1a (Tochter)"] T --> T3["ORG-1b (Tochter)"] S --> S1["ideell"] S --> S2["vermögensverwaltend"] S --> S3["zweckbetrieblich"] S --> S4["wirtschaftlich"] R --> R1["GF (Geschäftsführer)"] R --> R2["Buchhalter"] R --> R3["Lohnverantwortlicher"] R --> R4["F&E-Leiter"] R --> R5["Administrator"] style A fill:#0F1B33,stroke:#0F1B33,color:#FBFAF7 style T fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style S fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style R fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style T1 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style T2 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style T3 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style S1 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style S2 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style S3 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style S4 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style R1 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R2 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R3 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R4 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R5 fill:#FDBA74,stroke:#C2410C,color:#0F1B33

Level 1 - Tenant (Organization)

A Tenant is a legally independent organizational unit for which separate record-keeping obligations exist. In the GitCover federation, each tenant is maintained as its own Organization (Git User) with associated Git repos (or its own branch namespace).

Tenant Type Example (Placeholder) Own Obligations
Sole proprietorship ORG-1 (SME) GoBD, AO, e-invoicing
Holding with subsidiaries ORG-1 (holding), ORG-1a/ORG-1b (subsidiaries) Separate bookkeeping and separate annual financial statements for each company
Non-profit organization ORG-1 (non-profit) Additionally: sphere separation, § 52 AO, VBG exemption
Consortium / federation ORG-1, ORG-2, ORG-3 One tenant per organization, cross-references via V7GUID

Practical example: An entrepreneur (E1) runs a holding (ORG-1) with two subsidiaries (ORG-1a, ORG-1b). Each subsidiary is its own tenant with its own repo. The holding has a meta-repo that links the subsidiaries via V7GUID references - but the subsidiaries' books remain separate.

Level 2 - Sphere (Area of Activity, only for Non-Profits)

The Sphere is only relevant for non-profit organizations - but then it is mandatory. Tax law (§ 51–68 AO) requires the separation of the four spheres so as not to jeopardize non-profit status.

Sphere Meaning Example
ideell (ideal) Purpose-driven activity within the meaning of the articles of association, tax-exempt Workshop series, educational program
vermögensverwaltend (asset-managing) Management of the foundation assets, tax-exempt Interest from investments, rental income
zweckbetrieblich (purpose-related) Commercial business operations that serve the purpose, tax-exempt (§ 65 AO) Membership fees, admission fees
wirtschaftlich (commercial) Commercial business operations that do not serve the purpose, taxable Merchandising, advertising revenue
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#FBFAF7','primaryTextColor':'#0F1B33','primaryBorderColor':'#6B7280','lineColor':'#6B7280'}}}%% flowchart LR V["Geschäftsvorfall"] V --> I["ideell
steuerfrei
§ 52 AO"] V --> VV["vermögensverwaltend
steuerfrei"] V --> Z["zweckbetrieblich
steuerfrei
§ 65 AO"] V --> W["wirtschaftlich
steuerpflichtig
§ 64 AO"] I --> F["Freibetrag
§ 3 Nr. 26/26a EStG"] Z --> F W --> ST["USt/KSt
pflichtig"] style V fill:#0F1B33,stroke:#0F1B33,color:#FBFAF7 style I fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style VV fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style Z fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style W fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style F fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style ST fill:#FDBA74,stroke:#C2410C,color:#0F1B33

Risk of missing sphere separation: Commingling of assets (§ 55 Abs. 1 Nr. 5 AO) is a ground for revoking non-profit status. A non-profit organization that does not separate commercial and ideal transactions risks revocation of its non-profit status - and with it retrospective taxation of reserves (up to 15(!) years retroactively).

Level 3 - Role (Function of the Actor)

The Role documents in which function an actor acted. This is important because in many organizations one person often holds several roles (especially in SMEs) - and because the role determines which obligations apply.

Role Function Typical Obligations
GF (Managing Director) External representation, overall responsibility GoBD, AO, deadlines, power of representation
Buchhalter (Accountant) Bookkeeping, voucher archive GoBD, e-invoicing, retention
Lohnverantwortlicher (Payroll Officer) Payroll accounting, social security notifications SGB IV, DEÜV, LStDV
F&E-Leiter (Head of R&D) Research, FZul hour records FZulG, BSFZ, R&D vs. administration
Administrator Repo management, hooks, access Git, GPG, access rights

Practical example: The entrepreneur E1 is simultaneously GF, bookkeeper, researcher, developer, and head of R&D. For every artifact, the repo documents in which role he acted - e.g., role: "GF" for a resolution, role: "F&E-Leiter" for an FZul hour record. This keeps it traceable whether a record originated from the GF perspective (administration) or the R&D perspective (research).

Implementation in the Git Repo

Directory Structure

ORG-1/                          # Tenant: KMU
├── .gitcover/                  # GitCover-Konfiguration
│   ├── LEGAL_ENTITY.v7g.json   # Tenant-Identität (V7GUID)
│   ├── dictionaries/           # Sphären, Rollen, Beleg-Typen
│   └── schemas/                # JSON-Schemata für Artefakte
├── diary/                      # Tagebuch (SSoT)
│   ├── entries/                # Tages-Einträge
│   └── tenants/                # Tenant-Sichten (Symlinks)
├── registry/                   # Behörden-Identifikatoren
├── sources/                    # Belegarchiv (PDF, XML, EML)
├── sidecars/                   # .v7g.md Sidecars
├── checks/                     # Fristen-Check, Sphären-Check
└── {weitere bei Bedarf}/

JSON Artifact with Tenant, Sphere, Role

Every artifact (diary entry, voucher, land register entry) contains tenant, sphere, and role as mandatory fields. Central core principle of temporal traceability: The capture time is not a separate field but is anchored in the uuidV7 itself - as a 48-bit timestamp according to RFC 9562 §5.7. The uuidV7 can be generated from a predefined timestamp (not only now()) via the GitCover helper (UuidV7Gen), with the remainder filled with randomness. As a result, the capture time is cryptographically linked to the identity of the artifact and cannot be changed afterwards.

Important - What ends up in the Git repo: Only these structured artifacts (JSON entries, sidecars, vouchers) are added to the Git repo. Private documents are never added to the repo unless they have been explicitly introduced and classified as artifacts. Once it's in, it's in.

{
  "$schema": "https://gitcover.org/schemas/diary-entry-1.0.schema.json",
  "V7GUID": "<V7GUID-Class-aus-Registry>",
  "uuidV7": "<uuidV7-Object-mit-vorgegebener-Zeitmarke>",
  "author": "E1",
  "role": "GF",
  "tenant": "ORG-1",
  "sphere": "ideell",
  "source": "E1",
  "source_sha256": "<SHA-256-...>",
  "tags": ["lohnabrechnung", "sv-meldung"]
}

Composite key explanation: V7GUID (Class Identifier) classifies the document/action based on the .gitcover registry (what/which type). uuidV7 (Object ID) is the concrete object identifier with the predefined timestamp (RFC 9562 §5.7, 48-bit Unix-ms). Together they form the GCPN Sidecar Composite Key V7GUID:uuidV7. A separate datetime or date string representation is redundant and is not maintained at the facts level - the 48-bit timestamp is already embedded in the uuidV7. String representations for DTO/HTMX transfer are the harness's responsibility, not the facts level.

Git Hooks Check the Separation

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#FBFAF7','primaryTextColor':'#0F1B33','primaryBorderColor':'#6B7280','lineColor':'#6B7280'}}}%% flowchart TD C["Commit"] C --> H1["Pre-Commit-Hook"] H1 --> P1{"Tenant
vorhanden?"} P1 -->|nein| R1["Commit abgelehnt
Tenant fehlt"] P1 -->|ja| P2{"Sphäre
vorhanden?
(nur gemeinnützig)"} P2 -->|nein| R2["Commit abgelehnt
Sphäre fehlt"] P2 -->|ja| P3{"Rolle
vorhanden?"} P3 -->|nein| R3["Commit abgelehnt
Rolle fehlt"] P3 -->|ja| P4{"Sphäre
gültig?"} P4 -->|nein| R4["Commit abgelehnt
ungültige Sphäre"] P4 -->|ja| OK["Commit akzeptiert"] style C fill:#0F1B33,stroke:#0F1B33,color:#FBFAF7 style H1 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style P1 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style P2 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style P3 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style P4 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style R1 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R2 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R3 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style R4 fill:#FDBA74,stroke:#C2410C,color:#0F1B33 style OK fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33
Hook Check Fails on
Pre-Commit tenant field present and valid Missing or unknown tenant
Pre-Commit sphere field present (non-profit only) Missing sphere for non-profit tenant
Pre-Commit sphere value valid (ideell/vermögensverwaltend/zweckbetrieblich/wirtschaftlich) Invalid sphere value
Pre-Commit role field present and valid Missing or unknown role
Post-Commit Automatic index generation per tenant and sphere -

Tenant Federation: Multiple Organizations

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#FBFAF7','primaryTextColor':'#0F1B33','primaryBorderColor':'#6B7280','lineColor':'#6B7280'}}}%% flowchart TD H["ORG-1 (Holding)
Meta-Repo"] H --> R1["ORG-1a (Tochter 1)
eigenes Repo"] H --> R2["ORG-1b (Tochter 2)
eigenes Repo"] H --> R3["ORG-1c (Tochter 3)
eigenes Repo"] R1 --> V1["V7GUID-Referenz
auf ORG-1"] R2 --> V2["V7GUID-Referenz
auf ORG-1"] R3 --> V3["V7GUID-Referenz
auf ORG-1"] H --> M["Meta-Repo
Querverweise über V7GUID
keine Buchungen"] style H fill:#0F1B33,stroke:#0F1B33,color:#FBFAF7 style R1 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style R2 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style R3 fill:#DBEAFE,stroke:#1D4ED8,color:#0F1B33 style V1 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style V2 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style V3 fill:#D1FAE5,stroke:#0A7F5C,color:#0F1B33 style M fill:#10A987,stroke:#0A7F5C,color:#FBFAF7

A tenant federation (holding with subsidiaries, consortium) is linked via V7GUID references - not via shared repos. Each tenant keeps its own bookkeeping, but the holding's meta-repo can reference the subsidiaries' vouchers and entries without copying them.

Important: The meta-repo contains no postings - only cross-references. Bookkeeping remains with each tenant. The meta-repo is an index layer, not an accounting layer.

Risk Leverage

Today (cheap) Tomorrow (audit-proof) Risk Mitigated
tenant field per artifact Clear assignment during holding audits Commingling of assets between companies
sphere field per entry Non-profit status defensible Revocation under § 55 AO (commingling of assets)
role field per entry Traceable in which function the action was taken Role conflict, unauthorized representation
Pre-commit hook checks sphere Airtight sphere separation Manual sphere errors
V7GUID reference instead of copy Unambiguous assignment without duplicates Inconsistencies between copies

Harness Requirements (Preview)

Derivable from ED02:

ID Requirement Priority
FA-1.4 Tenant assignment (tenant: "ORG-1") per entry MUST
FA-3.1 Sphere tags: ideell/vermögensverwaltend/zweckbetrieblich/wirtschaftlich MUST (non-profit)
FA-3.2 Sphere tag mandatory per land register entry and diary entry MUST (non-profit)
FA-3.3 Pre-commit hook checks sphere tag completeness MUST (non-profit)
TA-2.3 Pre-commit hook: sphere tag check (non-profit only) MUST (non-profit)
FA-1.3 V7GUID per entry (uniqueness across tenants) MUST

The complete list of requirements can be found in Harness-Anforderungen.md.

Sources

Role Location Purpose
Primary / SSoT git.gitcover.org/GCC Canonical repository (GPG-signed, versioned)
Public OSS Mirror / CDN codeberg.org/gitcover-commons Read-only mirror; FLOSS discovery
Community Hub github.com/gitcover-commons Issues & Discussions; source code reference to Codeberg

Note: This mapping of sources, mirror, and community hub reflects the current state and may change. Please check the respective canonical source on gitcover.org for the current state.