diff --git a/.biber.conf b/.biber.conf
new file mode 100644
index 0000000..0680dba
--- /dev/null
+++ b/.biber.conf
@@ -0,0 +1,4 @@
+
+ out
+ out
+
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..d84c52c
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,3 @@
+use nix
+
+export VIMTEX_OUTPUT_DIRECTORY="out"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..faf7b4f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+out
+latexout
+latex.out
+.direnv
diff --git a/.latexmkrc b/.latexmkrc
new file mode 100644
index 0000000..a6cf24a
--- /dev/null
+++ b/.latexmkrc
@@ -0,0 +1,4 @@
+$pdf_mode = 4; # lualatex
+$bibtex_use = 2; # biber
+$out_dir = out;
+$clean_ext .= ' %R.run.xml %R.bbl %R.bcf %R-blx.bib';
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a0f513b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,58 @@
+# PidI Thesis LaTeX Template
+
+This template follows the specs:
+- A4, margins: left/top **3 cm**, right/bottom **2.5 cm**.
+- Page numbers bottom-center.
+- Font: **Times Newer Roman 12 pt** (`times` class option, default).
+- Line spacing **1.3**, justified text, paragraph spacing **6 pt**, emphasis **bold**.
+- `\emph{}` is mapped to bold.
+
+## File name for submission
+
+` PidI 3 .pdf`
+
+## Build
+
+```sh
+direnv allow # einmalig — setzt Nix-Umgebung auf
+latexmk # baut das PDF (LuaLaTeX + Biber, Ausgabe nach out/)
+latexmk -c # aufräumen
+```
+
+Requires the Nix shell (`shell.nix`) — provides TeX Live, `latexmk`, `mermaid-cli`,
+and Times Newer Roman (fonts are installed into `~/.local/share/fonts/` by the shell hook).
+
+`minted` code listings require shell escape; `latexmk` handles this automatically via
+`$pdf_mode = 4`.
+
+## Rendering Mermaid diagrams
+
+```sh
+# render a single diagram
+mmdc -i figures/diagrams/system-context.mmd -o figures/diagrams/system-context.pdf
+
+# render all diagrams at once
+for f in figures/diagrams/*.mmd; do
+ mmdc -i "$f" -o "${f%.mmd}.pdf"
+done
+```
+
+Render before calling `latexmk` whenever a `.mmd` file changes. The generated `.pdf`
+files are gitignored via `out` (only `out/` is ignored, so diagrams in `figures/` are
+**not** ignored — commit them).
+
+## Structure
+
+```
+main.tex entry point: metadata + \input all chapters
+pidi-thesis.cls enforces the complete layout
+frontmatter/ usage-of-ai, abstract, acknowledgments
+chapters//*.tex one file per \section
+appendix/ appendix.tex bundles tables/diagrams/screenshots/code
+figures/code/ code excerpts as real files (no inline code in appendix)
+figures/diagrams/ *.mmd source + rendered *.pdf
+figures/screenshots/ screenshots
+figures/worksimple/ company logos
+figures/itc/ ITC logo
+references.bib biblatex/biber sources
+```
diff --git a/appendix/appendix-code.tex b/appendix/appendix-code.tex
new file mode 100644
index 0000000..7ffae9b
--- /dev/null
+++ b/appendix/appendix-code.tex
@@ -0,0 +1,10 @@
+% TODO: Code-Ausschnitte — je in center-Umgebung mit \captionof{listing}{...} + \inputminted
+
+% Reihenfolge gemäß Kapiteln:
+% s3-settings-registration.cs, s3-documents-client.cs,
+% documents-page-model.cs, document-view-model.cs, documents-table-body.cshtml,
+% document-type-mapping.cs, document-types.resx,
+% document-search.cs, pagination-continuation-token.cs,
+% zip-download-action.cs, presigned-url.cs, url-file-parsing.cs,
+% org-slug.cs, resolve-customer-prefix.cs, rename-customer-folder.cs,
+% authorization-policy.cs, documents-service-tests.cs
diff --git a/appendix/appendix-diagrams.tex b/appendix/appendix-diagrams.tex
new file mode 100644
index 0000000..15ab173
--- /dev/null
+++ b/appendix/appendix-diagrams.tex
@@ -0,0 +1 @@
+% TODO: eingebundene Diagramme (falls nicht inline in Kapiteln)
diff --git a/appendix/appendix-screenshots.tex b/appendix/appendix-screenshots.tex
new file mode 100644
index 0000000..bbfe415
--- /dev/null
+++ b/appendix/appendix-screenshots.tex
@@ -0,0 +1 @@
+% TODO: Screenshots der fertigen Documents-Seite (Liste, Filter, Suche, PDF-Modal, ZIP-Auswahl)
diff --git a/appendix/appendix-tables.tex b/appendix/appendix-tables.tex
new file mode 100644
index 0000000..7ecd1db
--- /dev/null
+++ b/appendix/appendix-tables.tex
@@ -0,0 +1,2 @@
+% TODO: Zeitplan Soll/Ist, Backlog (PBI-Tabelle), PR-Übersicht,
+% Anforderungsmatrix, Dokumententypen↔Ordner↔Icon, Lookup-Trade-offs, Beteiligte
diff --git a/appendix/appendix.tex b/appendix/appendix.tex
new file mode 100644
index 0000000..acd38d0
--- /dev/null
+++ b/appendix/appendix.tex
@@ -0,0 +1,17 @@
+\section{Tabellen}
+\input{appendix/appendix-tables}
+
+\clearpage
+
+\section{Diagramme}
+\input{appendix/appendix-diagrams}
+
+\clearpage
+
+\section{Screenshots}
+\input{appendix/appendix-screenshots}
+
+\clearpage
+
+\section{Code-Ausschnitte}
+\input{appendix/appendix-code}
diff --git a/chapters/closure/evaluation.tex b/chapters/closure/evaluation.tex
new file mode 100644
index 0000000..8405f56
--- /dev/null
+++ b/chapters/closure/evaluation.tex
@@ -0,0 +1,4 @@
+\section{Zielerreichung}
+\label{sec:evaluation}
+
+% TODO
diff --git a/chapters/closure/outlook.tex b/chapters/closure/outlook.tex
new file mode 100644
index 0000000..8a442e7
--- /dev/null
+++ b/chapters/closure/outlook.tex
@@ -0,0 +1,6 @@
+\section{Ausblick}
+\label{sec:outlook}
+
+% TODO: PBI 10070 (Race Conditions), Search Integration (von AU noch nicht verfügbar),
+% Dashboard-Kacheln (Security Assessments, zuletzt hinzugefügte Dokumente),
+% Abrechnungsdaten
diff --git a/chapters/closure/reflection.tex b/chapters/closure/reflection.tex
new file mode 100644
index 0000000..3708ef0
--- /dev/null
+++ b/chapters/closure/reflection.tex
@@ -0,0 +1,5 @@
+\section{Reflexion}
+\label{sec:reflection}
+
+% TODO: Lessons Learned — S3-Lookup-Entscheidung, Race Conditions als offenes Thema,
+% Infrastruktur-Vorlauf unterschätzt (AU-Kommunikation 2026-07-22 bis 2026-08-07)
diff --git a/chapters/closure/target-comparison.tex b/chapters/closure/target-comparison.tex
new file mode 100644
index 0000000..562cb9f
--- /dev/null
+++ b/chapters/closure/target-comparison.tex
@@ -0,0 +1,4 @@
+\section{Soll-Ist-Vergleich}
+\label{sec:target-comparison}
+
+% TODO: Tabelle Soll-Ist (Zeitplan, Features)
diff --git a/chapters/company/econ-localization.tex b/chapters/company/econ-localization.tex
new file mode 100644
index 0000000..a66c6f9
--- /dev/null
+++ b/chapters/company/econ-localization.tex
@@ -0,0 +1 @@
+% TODO: Kapitel aus PidI 2 übernehmen und auf PidI 3 aktualisieren
diff --git a/chapters/company/products-and-services.tex b/chapters/company/products-and-services.tex
new file mode 100644
index 0000000..a66c6f9
--- /dev/null
+++ b/chapters/company/products-and-services.tex
@@ -0,0 +1 @@
+% TODO: Kapitel aus PidI 2 übernehmen und auf PidI 3 aktualisieren
diff --git a/chapters/company/worksimple.tex b/chapters/company/worksimple.tex
new file mode 100644
index 0000000..a66c6f9
--- /dev/null
+++ b/chapters/company/worksimple.tex
@@ -0,0 +1 @@
+% TODO: Kapitel aus PidI 2 übernehmen und auf PidI 3 aktualisieren
diff --git a/chapters/conception/authorization.tex b/chapters/conception/authorization.tex
new file mode 100644
index 0000000..63b7423
--- /dev/null
+++ b/chapters/conception/authorization.tex
@@ -0,0 +1,13 @@
+\section{Autorisierungskonzept}
+\label{sec:authorization}
+
+% TODO: App-Rolle Documents.Read (Entra ID), Claim efecte:company_id
+% Menüpunkt nur sichtbar mit Rolle, Direktzugriff ohne Rolle → 403 (nicht 404)
+% Sequence-Diagramm auth-sequence.pdf
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.9\textwidth]{figures/diagrams/auth-sequence.pdf}
+% \caption{Autorisierungsablauf}
+% \label{fig:auth-sequence}
+% \end{figure}
diff --git a/chapters/conception/document-types.tex b/chapters/conception/document-types.tex
new file mode 100644
index 0000000..919bc8c
--- /dev/null
+++ b/chapters/conception/document-types.tex
@@ -0,0 +1,7 @@
+\section{Dokumententypen und Icons}
+\label{sec:document-types}
+
+% TODO: 7 Typen hardcoded in Houston (PBI 9560/9549):
+% Service-Protokoll, Abnahme Dokumente, SLA-Reports, Monitoring Reports,
+% Security Assessments, Abrechnungsdaten, Vertragsunterlagen
+% Typzuordnung über Unterordnername, Tabelle im Anhang
diff --git a/chapters/conception/lookup-decision.tex b/chapters/conception/lookup-decision.tex
new file mode 100644
index 0000000..29cd0e7
--- /dev/null
+++ b/chapters/conception/lookup-decision.tex
@@ -0,0 +1,13 @@
+\section{Architekturentscheidung: O(1)-Fast-Path}
+\label{sec:lookup-decision}
+
+% TODO: PBI 10018 — metadatenbasierter Fast-Path
+% ResolveCustomerPrefixAsync: Fast-Path → Kollisions-Fast-Path → O(n)-Fallback + Self-Healing-Rename
+% Houston als führende Instanz für Ordnerbenennung
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=\textwidth]{figures/diagrams/lookup-flow.pdf}
+% \caption{Ablauf \texttt{ResolveCustomerPrefixAsync}}
+% \label{fig:lookup-flow}
+% \end{figure}
diff --git a/chapters/conception/lookup-research.tex b/chapters/conception/lookup-research.tex
new file mode 100644
index 0000000..4317894
--- /dev/null
+++ b/chapters/conception/lookup-research.tex
@@ -0,0 +1,8 @@
+\section{Problem: Lookup des Kundenordners}
+\label{sec:lookup-research}
+
+% TODO: PBI 9857 — S3 kann nicht nach Metadaten-Tags suchen → lineares Scannen aller Top-Level-Prefixes
+% Trade-off-Matrix der 6 Varianten (In-Memory Cache, Claim, Efecte-Feld, S3 SelectObject, Search Integration, Prefix im Namen)
+% \cite{aws-s3-select}, \cite{storagegrid-search-integration}
+
+% Tabelle~\ref{tab:lookup-tradeoffs} im Anhang
diff --git a/chapters/conception/s3-layout.tex b/chapters/conception/s3-layout.tex
new file mode 100644
index 0000000..a2f09a5
--- /dev/null
+++ b/chapters/conception/s3-layout.tex
@@ -0,0 +1,14 @@
+\section{Ablagekonzept im S3-Speicher}
+\label{sec:s3-layout}
+
+% TODO: Ordnerbaum (Feature 484):
+% Bucket → Kundenordner [meta: efecte_org-id] → Typordner/ → Dokumente
+% Typ = Unterordner, nicht Metadatum an der Datei
+% Leere Ordner werden nicht angezeigt
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.75\textwidth]{figures/diagrams/s3-layout.pdf}
+% \caption{S3-Ablagestruktur}
+% \label{fig:s3-layout}
+% \end{figure}
diff --git a/chapters/conception/ui-concept.tex b/chapters/conception/ui-concept.tex
new file mode 100644
index 0000000..7ecdd93
--- /dev/null
+++ b/chapters/conception/ui-concept.tex
@@ -0,0 +1,5 @@
+\section{UI-Konzept und Clickdummy}
+\label{sec:ui-concept}
+
+% TODO: Hanna Ebner, Branch Clickdummy_Dokumente (2026-07-22)
+% Listenansicht, Typfilter oben als Buttons, flexible Tabellenspalten
diff --git a/chapters/execution/architecture.tex b/chapters/execution/architecture.tex
new file mode 100644
index 0000000..a673dad
--- /dev/null
+++ b/chapters/execution/architecture.tex
@@ -0,0 +1,12 @@
+\section{Architektur des Documents-Moduls}
+\label{sec:architecture}
+
+% TODO: Razor Page DocumentsPage.cshtml → DocumentsService → S3DocumentsClient
+% Klassendiagramm module-components.pdf
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.9\textwidth]{figures/diagrams/module-components.pdf}
+% \caption{Komponentenstruktur des Documents-Moduls}
+% \label{fig:module-components}
+% \end{figure}
diff --git a/chapters/execution/document-explorer.tex b/chapters/execution/document-explorer.tex
new file mode 100644
index 0000000..b1ecd74
--- /dev/null
+++ b/chapters/execution/document-explorer.tex
@@ -0,0 +1,5 @@
+\section{Document Explorer}
+\label{sec:document-explorer}
+
+% TODO: PBI 9295 — /documents Seite, ListObjectsV2, Empty State, Fehlerbehandlung
+% Abbildung~\ref{fig:documents-page-model}, \ref{fig:document-view-model}, \ref{fig:documents-table-body}
diff --git a/chapters/execution/downloads.tex b/chapters/execution/downloads.tex
new file mode 100644
index 0000000..509c561
--- /dev/null
+++ b/chapters/execution/downloads.tex
@@ -0,0 +1,13 @@
+\section{Dokumenten-Downloads}
+\label{sec:downloads}
+
+% TODO: PBI 9299 (Einzeldownload), PBI 9296 (ZIP-Download)
+% Streaming: S3 GetObject → ZipArchive → HTTP Response Stream
+% Abbildung~\ref{fig:zip-download-action}
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.9\textwidth]{figures/diagrams/zip-stream.pdf}
+% \caption{ZIP-Download-Ablauf}
+% \label{fig:zip-stream}
+% \end{figure}
diff --git a/chapters/execution/filter-pagination.tex b/chapters/execution/filter-pagination.tex
new file mode 100644
index 0000000..e4f2550
--- /dev/null
+++ b/chapters/execution/filter-pagination.tex
@@ -0,0 +1,6 @@
+\section{Typfilter und Paginierung}
+\label{sec:filter-pagination}
+
+% TODO: PBI 9749 (Typfilter), PBI 9731 (Pagination)
+% ContinuationToken statt Offset-Pagination
+% Abbildung~\ref{fig:pagination-continuation-token}
diff --git a/chapters/execution/folder-management.tex b/chapters/execution/folder-management.tex
new file mode 100644
index 0000000..213c6fb
--- /dev/null
+++ b/chapters/execution/folder-management.tex
@@ -0,0 +1,8 @@
+\section{Ordnerstruktur und Kundenordner-Lookup}
+\label{sec:folder-management}
+
+% TODO: PBI 9560 (Ordneranlage beim ersten Seitenaufruf), PBI 10018 (O(1)-Lookup)
+% OrgSlug: deterministische, S3-konforme Normalisierung des Efecte-Namens (Umlaute bleiben erhalten)
+% IBM-Naming-Constraints: \cite{ibm-s3-naming}
+% ResolveCustomerPrefixAsync, Self-Healing-Rename
+% Abbildung~\ref{fig:org-slug}, \ref{fig:resolve-customer-prefix}, \ref{fig:rename-customer-folder}
diff --git a/chapters/execution/pdf-preview.tex b/chapters/execution/pdf-preview.tex
new file mode 100644
index 0000000..4b38385
--- /dev/null
+++ b/chapters/execution/pdf-preview.tex
@@ -0,0 +1,6 @@
+\section{PDF-Modal-Vorschau und Share-Link-Previews}
+\label{sec:pdf-preview}
+
+% TODO: PBI 9300 (PDF-Modal), PBI 9294 (Share-Link-Previews)
+% Pre-Signed URLs, zeitlich begrenzte Gültigkeit
+% Abbildung~\ref{fig:presigned-url}
diff --git a/chapters/execution/race-conditions.tex b/chapters/execution/race-conditions.tex
new file mode 100644
index 0000000..071c8fd
--- /dev/null
+++ b/chapters/execution/race-conditions.tex
@@ -0,0 +1,15 @@
+\section{Bekannte Grenze: Race Conditions im Lookup}
+\label{sec:race-conditions}
+
+% TODO: PBI 10070 — Houston läuft in mehreren Instanzen, In-Memory-Lock reicht nicht
+% Szenario A: Datenverlust beim parallelen Rename (Rollback löscht Dokumente des Gewinners)
+% Szenario B: Mandantenvermischung beim gleichzeitigen Anlegen gleicher Efecte-Namen
+% Lösungsansätze: Rollback-Absicherung, Conditional Writes, verteiltes Lock, prozessuale Migration
+% Timebox: 4–6 Stunden (Stephan Janßen)
+
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.9\textwidth]{figures/diagrams/race-condition-a.pdf}
+% \caption{Race Condition Szenario A: Datenverlust beim parallelen Rename}
+% \label{fig:race-condition-a}
+% \end{figure}
diff --git a/chapters/execution/s3-client.tex b/chapters/execution/s3-client.tex
new file mode 100644
index 0000000..ff7f07e
--- /dev/null
+++ b/chapters/execution/s3-client.tex
@@ -0,0 +1,5 @@
+\section{Anbindung des S3-Speichers}
+\label{sec:s3-client}
+
+% TODO: AWS SDK für .NET, IAmazonS3, keyed services in Program.cs, S3Settings (DEV/TEST/PROD Buckets)
+% Abbildung~\ref{fig:s3-settings-registration}, \ref{fig:s3-documents-client}
diff --git a/chapters/execution/search.tex b/chapters/execution/search.tex
new file mode 100644
index 0000000..31c6927
--- /dev/null
+++ b/chapters/execution/search.tex
@@ -0,0 +1,6 @@
+\section{Serverseitige Suche}
+\label{sec:search}
+
+% TODO: PBI 9298 — Suchleiste, titelbasiert, Teiltreffer, serverseitiges Filtern
+% S3-API bietet keine direkte Filterung → Houston-seitiger Filter
+% Abbildung~\ref{fig:document-search}
diff --git a/chapters/execution/type-icons.tex b/chapters/execution/type-icons.tex
new file mode 100644
index 0000000..a0a17e2
--- /dev/null
+++ b/chapters/execution/type-icons.tex
@@ -0,0 +1,5 @@
+\section{Dokumenttypen und Icons}
+\label{sec:type-icons}
+
+% TODO: PBI 9549 — Typ-Mapping aus Unterordner, .resx-Lokalisierung
+% Abbildung~\ref{fig:document-type-mapping}, \ref{fig:document-types-resx}
diff --git a/chapters/execution/url-files.tex b/chapters/execution/url-files.tex
new file mode 100644
index 0000000..2d3ca93
--- /dev/null
+++ b/chapters/execution/url-files.tex
@@ -0,0 +1,5 @@
+\section{Support für URL-Dateien}
+\label{sec:url-files}
+
+% TODO: PBI 9301 — .url-Dateien parsen, Verlinkung beliebiger URLs (Teams, SharePoint)
+% Abbildung~\ref{fig:url-file-parsing}
diff --git a/chapters/overview/initial-situation.tex b/chapters/overview/initial-situation.tex
new file mode 100644
index 0000000..eda7156
--- /dev/null
+++ b/chapters/overview/initial-situation.tex
@@ -0,0 +1,5 @@
+\section{Ausgangssituation}
+\label{sec:initial-situation}
+
+% TODO: Feature 484 lag 2,5 Jahre im Backlog (Nicole Kimmel, 2023-11-02).
+% Bisher kein zentraler Dokumentenzugang für Kunden.
diff --git a/chapters/overview/participants.tex b/chapters/overview/participants.tex
new file mode 100644
index 0000000..3fd5465
--- /dev/null
+++ b/chapters/overview/participants.tex
@@ -0,0 +1,4 @@
+\section{Beteiligte und Rollen}
+\label{sec:participants}
+
+% TODO: Tabelle aus note-1787657238720 (Beteiligte)
diff --git a/chapters/overview/project-description.tex b/chapters/overview/project-description.tex
new file mode 100644
index 0000000..5f6ef68
--- /dev/null
+++ b/chapters/overview/project-description.tex
@@ -0,0 +1,4 @@
+\section{Projektbeschreibung}
+\label{sec:project-description}
+
+% TODO
diff --git a/chapters/overview/project-scope.tex b/chapters/overview/project-scope.tex
new file mode 100644
index 0000000..eee8da3
--- /dev/null
+++ b/chapters/overview/project-scope.tex
@@ -0,0 +1,7 @@
+\section{Projektabgrenzung}
+\label{sec:project-scope}
+
+% TODO: Out of Scope aus Feature 484:
+% - Kunde kann Dokumente nicht bearbeiten
+% - Keine neuen Ordner intern wild anlegen
+% - Filestash ist externes Admin-UI (kein Houston-Eigenbau)
diff --git a/chapters/overview/system-landscape.tex b/chapters/overview/system-landscape.tex
new file mode 100644
index 0000000..5f8a746
--- /dev/null
+++ b/chapters/overview/system-landscape.tex
@@ -0,0 +1,12 @@
+\section{Systemlandschaft}
+\label{sec:system-landscape}
+
+% TODO: Houston (ASP.NET Core, Razor Pages) — Efecte — Microsoft Entra ID — S3/StorageGRID — Filestash
+
+% Diagramm:
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=0.9\textwidth]{figures/diagrams/system-context.pdf}
+% \caption{Systemkontext}
+% \label{fig:system-context}
+% \end{figure}
diff --git a/chapters/overview/target-situation.tex b/chapters/overview/target-situation.tex
new file mode 100644
index 0000000..4b60f7e
--- /dev/null
+++ b/chapters/overview/target-situation.tex
@@ -0,0 +1,4 @@
+\section{Zielsituation}
+\label{sec:target-situation}
+
+% TODO: Feature 484 Rev 38 — Dokumentenbereich in Houston, 7 Dokumententypen, S3-Ablage, Filestash als Admin-UI
diff --git a/chapters/planning/backlog.tex b/chapters/planning/backlog.tex
new file mode 100644
index 0000000..b6ecaeb
--- /dev/null
+++ b/chapters/planning/backlog.tex
@@ -0,0 +1,14 @@
+\section{Backlog-Schnitt und Schätzung}
+\label{sec:backlog}
+
+% TODO: 14 PBIs + 1 Bug unter Feature 484
+% Prozess: DoR, DoD, Approval-Team, Sprints 15–17.2026
+% Siehe Tabelle~\ref{tab:backlog} im Anhang
+
+% Gantt:
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=\textwidth]{figures/diagrams/gantt-plan.pdf}
+% \caption{Zeitplanung über Sprints 15–17.2026}
+% \label{fig:gantt}
+% \end{figure}
diff --git a/chapters/planning/feature-analysis.tex b/chapters/planning/feature-analysis.tex
new file mode 100644
index 0000000..2e4b1d6
--- /dev/null
+++ b/chapters/planning/feature-analysis.tex
@@ -0,0 +1,7 @@
+\section{Feature-Analyse}
+\label{sec:feature-analysis}
+
+% TODO: 18.06.2026 — 4 Rückfragen von Linus an Thomas, Antworten im selben Ticket (Feature 484 Rev 17–32)
+% - Autorisierung via Metadatum: ja
+% - Filestash als externe Website (kein Custom-UI): ja
+% - ...
diff --git a/chapters/planning/infrastructure.tex b/chapters/planning/infrastructure.tex
new file mode 100644
index 0000000..8958388
--- /dev/null
+++ b/chapters/planning/infrastructure.tex
@@ -0,0 +1,15 @@
+\section{Infrastrukturbeschaffung}
+\label{sec:infrastructure}
+
+% TODO: Service Requests an Maschinenraum (2026-07-22), Provisionierung durch Advanced Unibyte,
+% 3 Buckets (DEV/TEST/PROD), Credentials in Passbolt (2026-07-27)
+% Anfrage S3 Select (2026-07-30), Aktivierung durch AU (2026-08-07)
+% Search Integration: von AU nicht bereitgestellt (2026-08-17)
+
+% Timeline-Diagramm:
+% \begin{figure}[H]
+% \centering
+% \includegraphics[width=\textwidth]{figures/diagrams/timeline-infra.pdf}
+% \caption{Chronologie der Infrastrukturbeschaffung}
+% \label{fig:timeline-infra}
+% \end{figure}
diff --git a/chapters/planning/onboarding.tex b/chapters/planning/onboarding.tex
new file mode 100644
index 0000000..8c85a3b
--- /dev/null
+++ b/chapters/planning/onboarding.tex
@@ -0,0 +1,5 @@
+\section{Einarbeitung}
+\label{sec:onboarding}
+
+% TODO: S3-API, AWS SDK für .NET, StorageGRID-Dokumentation
+% Quellen: note-1785344962361 (S3-Recherche mit Timo), note-1785413874041
diff --git a/chapters/planning/requirements.tex b/chapters/planning/requirements.tex
new file mode 100644
index 0000000..d701af1
--- /dev/null
+++ b/chapters/planning/requirements.tex
@@ -0,0 +1,5 @@
+\section{Anforderungserhebung}
+\label{sec:requirements}
+
+% TODO: Funktionale und nichtfunktionale Anforderungen aus den PBI-ACs
+% Tabelle: Anforderungsmatrix (funktional / nichtfunktional → PBI)
diff --git a/chapters/planning/schedule.tex b/chapters/planning/schedule.tex
new file mode 100644
index 0000000..29c7bd6
--- /dev/null
+++ b/chapters/planning/schedule.tex
@@ -0,0 +1,4 @@
+\section{Zeit- und Aufwandsplanung}
+\label{sec:schedule}
+
+% TODO: Sprints 15–17.2026, Aufwandsschätzungen (Story Points), 24 Manntage / 192 h gesamt
diff --git a/chapters/qa/acceptance-testing.tex b/chapters/qa/acceptance-testing.tex
new file mode 100644
index 0000000..561ff1d
--- /dev/null
+++ b/chapters/qa/acceptance-testing.tex
@@ -0,0 +1,5 @@
+\section{Abnahmetest}
+\label{sec:acceptance-testing}
+
+% TODO: Maria-Lena Andersz — Sichtbarkeitsproblem des Menüpunkts (2026-08-13)
+% Rollenzuweisung klären, Bug 10134 (Suchfunktion), finale Abnahme 2026-08-24/25
diff --git a/chapters/qa/code-reviews.tex b/chapters/qa/code-reviews.tex
new file mode 100644
index 0000000..b0680af
--- /dev/null
+++ b/chapters/qa/code-reviews.tex
@@ -0,0 +1,7 @@
+\section{Code-Reviews}
+\label{sec:code-reviews}
+
+% TODO: 11 PRs (2154–2196), Reviewer: Timo Walter, Sarah Hinzmann, Robin Noack
+% Reviewfunde: zentrale Auth über Program.cs, keyed Settings, 403 statt 404,
+% Slug-Naming-Constraints (IBM-Doku), Fehlerbehandlung statt stiller leerer Seite
+% Tabelle~\ref{tab:pull-requests} im Anhang
diff --git a/chapters/qa/releases.tex b/chapters/qa/releases.tex
new file mode 100644
index 0000000..7674c5f
--- /dev/null
+++ b/chapters/qa/releases.tex
@@ -0,0 +1,5 @@
+\section{Releases}
+\label{sec:releases}
+
+% TODO: DEV / TEST / PROD je eigener Bucket, Rollenvergabe vor Release
+% PR 2196 noch aktiv bei Dokumentationsabgabe
diff --git a/chapters/qa/test-strategy.tex b/chapters/qa/test-strategy.tex
new file mode 100644
index 0000000..2bc2dc9
--- /dev/null
+++ b/chapters/qa/test-strategy.tex
@@ -0,0 +1,4 @@
+\section{Teststrategie}
+\label{sec:test-strategy}
+
+% TODO: Unit-Tests mit gemocktem IAmazonS3, Abnahmetests durch Maria-Lena Andersz
diff --git a/chapters/qa/unit-tests.tex b/chapters/qa/unit-tests.tex
new file mode 100644
index 0000000..f2075a1
--- /dev/null
+++ b/chapters/qa/unit-tests.tex
@@ -0,0 +1,6 @@
+\section{Unit-Tests}
+\label{sec:unit-tests}
+
+% TODO: DocumentsServiceTests — gemocktes IAmazonS3
+% Pfade: Fast-Path, Fallback, Rename, Create, Kollision, Fehlerfall
+% Abbildung~\ref{fig:documents-service-tests}
diff --git a/figures/diagrams/ado-workflow.mmd b/figures/diagrams/ado-workflow.mmd
new file mode 100644
index 0000000..fef3165
--- /dev/null
+++ b/figures/diagrams/ado-workflow.mmd
@@ -0,0 +1,10 @@
+stateDiagram-v2
+ [*] --> New
+ New --> ToApprove : Linus reicht PBI ein
+ ToApprove --> Approved : Approval-Team
+ Approved --> Committed : Sprint-Planung
+ Committed --> DevCompleted : PR gemerged
+ DevCompleted --> TestCompleted : Abnahme bestanden
+ TestCompleted --> [*]
+ ToApprove --> Removed : Verworfen
+ Removed --> New : Wiederhergestellt
diff --git a/figures/diagrams/auth-sequence.mmd b/figures/diagrams/auth-sequence.mmd
new file mode 100644
index 0000000..a7d7dde
--- /dev/null
+++ b/figures/diagrams/auth-sequence.mmd
@@ -0,0 +1,18 @@
+sequenceDiagram
+ participant B as Browser
+ participant H as Houston
+ participant AAD as Entra ID
+ participant S3 as S3-Speicher
+
+ B->>H: GET /documents
+ H->>H: Prüfe Claim Documents.Read
+ alt Keine Rolle
+ H-->>B: 403 Forbidden
+ else Rolle vorhanden
+ H->>H: Lese efecte:company_id aus Claim
+ H->>S3: ResolveCustomerPrefixAsync(orgId)
+ S3-->>H: Kundenordner-Prefix
+ H->>S3: ListObjectsV2(prefix)
+ S3-->>H: Objektliste
+ H-->>B: Documents-Seite
+ end
diff --git a/figures/diagrams/gantt-plan.mmd b/figures/diagrams/gantt-plan.mmd
new file mode 100644
index 0000000..076517d
--- /dev/null
+++ b/figures/diagrams/gantt-plan.mmd
@@ -0,0 +1,18 @@
+gantt
+ title Zeitplanung PidI 3 (Sprints 15–17.2026)
+ dateFormat YYYY-MM-DD
+ section Planung
+ Feature-Analyse :done, 2026-06-18, 1d
+ Anforderungen & Backlog :done, 2026-07-07, 5d
+ section Sprint 15.2026
+ Document Explorer :done, 2026-07-27, 5d
+ Icons & Suche :done, 2026-08-01, 12d
+ Downloads & PDF-Modal :done, 2026-08-15, 7d
+ section Sprint 16.2026
+ Typfilter & Pagination :done, 2026-08-18, 4d
+ Ordner-Lookup :active, 2026-08-17, 8d
+ section Sprint 17.2026
+ Race Conditions (10070) :2026-08-26, 5d
+ section Qualitätssicherung
+ Abnahmetest :done, 2026-08-13, 12d
+ Release :2026-08-26, 3d
diff --git a/figures/diagrams/lookup-flow.mmd b/figures/diagrams/lookup-flow.mmd
new file mode 100644
index 0000000..a2dd7ae
--- /dev/null
+++ b/figures/diagrams/lookup-flow.mmd
@@ -0,0 +1,10 @@
+flowchart TD
+ A[ResolveCustomerPrefixAsync\norgId, orgName] --> B{Fast-Path:\nGetObjectMetadata\nslug-name/}
+ B -->|Gefunden & ID passt| Z[✓ Fertig\n1 Request]
+ B -->|Nicht gefunden oder\nID passt nicht| C{Kollisions-Fast-Path:\nslug-name orgId /}
+ C -->|Gefunden| Z2[✓ Fertig\n2 Requests]
+ C -->|Nicht gefunden| D[Fallback: O-n\nListObjectsV2 alle\nTop-Level-Prefixes]
+ D -->|Ordner mit\npAssender ID gefunden| E[Rename auf\nkanonischen Namen]
+ E --> Z3[✓ Fertig\nnächster Lookup O-1]
+ D -->|Kein Ordner| F[Anlegen: Ordner +\nUnterstruktur 9560]
+ F --> Z4[✓ Fertig\nSeite leer]
diff --git a/figures/diagrams/module-components.mmd b/figures/diagrams/module-components.mmd
new file mode 100644
index 0000000..22f65b0
--- /dev/null
+++ b/figures/diagrams/module-components.mmd
@@ -0,0 +1,29 @@
+classDiagram
+ class DocumentsPage {
+ +OnGetAsync()
+ +OnGetDownloadAsync()
+ +OnGetZipAsync()
+ }
+ class DocumentsService {
+ +ListDocumentsAsync(orgId, search, type, token)
+ +GetDownloadUrlAsync(orgId, key)
+ +GetZipStreamAsync(orgId, keys)
+ +ResolveCustomerPrefixAsync(orgId, orgName)
+ }
+ class S3DocumentsClient {
+ -IAmazonS3 _s3
+ +ListObjectsAsync(prefix, delimiter, token)
+ +GetObjectMetadataAsync(key)
+ +GetPresignedUrlAsync(key)
+ }
+ class OrgSlug {
+ +Slugify(name) string
+ }
+ class S3Settings {
+ +BucketName string
+ +ServiceUrl string
+ }
+ DocumentsPage --> DocumentsService
+ DocumentsService --> S3DocumentsClient
+ DocumentsService --> OrgSlug
+ S3DocumentsClient --> S3Settings
diff --git a/figures/diagrams/race-condition-a.mmd b/figures/diagrams/race-condition-a.mmd
new file mode 100644
index 0000000..301570c
--- /dev/null
+++ b/figures/diagrams/race-condition-a.mmd
@@ -0,0 +1,15 @@
+sequenceDiagram
+ participant A as Request A
+ participant S3 as S3-Speicher
+ participant B as Request B
+
+ Note over A,B: Ordner AltName/ mit 200 Objekten, Zielname: Kunde GmbH/
+ A->>S3: CanClaim(Kunde GmbH) → Missing → true
+ B->>S3: CanClaim(Kunde GmbH) → Missing → true
+ A->>S3: Kopiere 200 Objekte nach Kunde GmbH/
+ B->>S3: Kopiere Objekte #1–60 nach Kunde GmbH/
+ A->>S3: DeleteObjects(AltName/*) ✓
+ B->>S3: Kopie #61 → NoSuchKey ✗
+ B->>S3: catch: DeleteObjects(copiedKeys #1–60)
+ Note over S3: 60 Objekte aus Kunde GmbH/ gelöscht!
+ Note over S3: AltName/ existiert nicht mehr → Datenverlust
diff --git a/figures/diagrams/s3-layout.mmd b/figures/diagrams/s3-layout.mmd
new file mode 100644
index 0000000..47ec228
--- /dev/null
+++ b/figures/diagrams/s3-layout.mmd
@@ -0,0 +1,9 @@
+flowchart TD
+ B[(S3-Bucket\ndocuments-houston-prod)]
+ B --> KA["Kunde A/\n[meta: efecte_org-id=42]"]
+ B --> KB["Kunde B/\n[meta: efecte_org-id=77]"]
+ KA --> D1[doc1.pdf\nuntyped]
+ KA --> T1["Service-Protokoll/"]
+ KA --> T2["Vertragsunterlagen/"]
+ T1 --> D2[bericht-2026-07.pdf]
+ T2 --> D3[SLA-2026.pdf]
diff --git a/figures/diagrams/system-context.mmd b/figures/diagrams/system-context.mmd
new file mode 100644
index 0000000..095c3d8
--- /dev/null
+++ b/figures/diagrams/system-context.mmd
@@ -0,0 +1,18 @@
+flowchart LR
+ subgraph Kunde
+ K[Kundenportal\nHouston]
+ end
+ subgraph WorkSimple
+ H[Houston\nASP.NET Core]
+ F[Filestash\nS3-Browser]
+ end
+ subgraph Infrastruktur
+ E[Efecte\nCMDB]
+ S3[(S3-Speicher\nStorageGRID)]
+ AAD[Microsoft\nEntra ID]
+ end
+ K -->|HTTPS| H
+ H -->|REST| E
+ H -->|AWS SDK| S3
+ H -->|OpenID Connect| AAD
+ F -->|S3-API| S3
diff --git a/figures/diagrams/timeline-infra.mmd b/figures/diagrams/timeline-infra.mmd
new file mode 100644
index 0000000..234d839
--- /dev/null
+++ b/figures/diagrams/timeline-infra.mmd
@@ -0,0 +1,10 @@
+%%{init: {'theme': 'base'}}%%
+timeline
+ title Infrastrukturbeschaffung S3-Speicher
+ 2026-07-22 : Service Request erstellt (Maschinenraum)
+ 2026-07-23 : Request Alexander Wagner zugewiesen
+ 2026-07-27 : 3 Buckets durch AU erstellt, Credentials in Passbolt
+ 2026-07-30 : Anfrage S3 Select + Search Integration
+ 2026-08-04 : Lennart Meinert kontaktiert AU
+ 2026-08-07 : S3 Select für alle 3 Buckets aktiviert
+ 2026-08-17 : Search Integration von AU abgelehnt
diff --git a/figures/diagrams/zip-stream.mmd b/figures/diagrams/zip-stream.mmd
new file mode 100644
index 0000000..6b0af7a
--- /dev/null
+++ b/figures/diagrams/zip-stream.mmd
@@ -0,0 +1,15 @@
+sequenceDiagram
+ participant B as Browser
+ participant P as PageModel
+ participant S as DocumentsService
+ participant S3 as S3-Speicher
+
+ B->>P: POST /documents?handler=Zip&keys=[...]
+ P->>S: GetZipStreamAsync(orgId, keys)
+ loop je Dokument
+ S->>S3: GetObjectAsync(key)
+ S3-->>S: Stream
+ S->>S: ZipArchive.CreateEntry + CopyToAsync
+ end
+ S-->>P: ZipStream
+ P-->>B: application/zip (streaming)
diff --git a/figures/itc/IT-Center_Dortmund_Logo.svg.png b/figures/itc/IT-Center_Dortmund_Logo.svg.png
new file mode 100644
index 0000000..98efa2e
Binary files /dev/null and b/figures/itc/IT-Center_Dortmund_Logo.svg.png differ
diff --git a/frontmatter/abstract.tex b/frontmatter/abstract.tex
new file mode 100644
index 0000000..a8f3ea8
--- /dev/null
+++ b/frontmatter/abstract.tex
@@ -0,0 +1,4 @@
+% \chapter*{Kurzfassung}
+% \addcontentsline{toc}{chapter}{Kurzfassung}
+% TODO
+% \clearpage
diff --git a/frontmatter/acknowledgments.tex b/frontmatter/acknowledgments.tex
new file mode 100644
index 0000000..291bc1b
--- /dev/null
+++ b/frontmatter/acknowledgments.tex
@@ -0,0 +1,4 @@
+% \chapter*{Danksagung}
+% \addcontentsline{toc}{chapter}{Danksagung}
+% TODO
+% \clearpage
diff --git a/frontmatter/usage-of-ai.tex b/frontmatter/usage-of-ai.tex
new file mode 100644
index 0000000..7df3ae2
--- /dev/null
+++ b/frontmatter/usage-of-ai.tex
@@ -0,0 +1,10 @@
+\chapter*{Nutzung von KI}
+\addcontentsline{toc}{chapter}{Nutzung von KI}
+
+Bei der Erstellung dieser Dokumentation wurde KI ausschließlich für die folgenden Bereiche verwendet:
+\begin{itemize}
+ \item Erlernen von \LaTeX-Syntax und Suche von entsprechenden \LaTeX-Packages für diese Dokumentation
+ \item Formatierung und Umformulierung von Inhalt, der vom Autor verfasst wurde, in den Kapiteln \ref{chap:company}, \ref{chap:overview}, \ref{chap:planning}, \ref{chap:conception}, \ref{chap:execution}, \ref{chap:qa} und \ref{chap:closure}
+\end{itemize}
+
+\clearpage
diff --git a/main.tex b/main.tex
new file mode 100644
index 0000000..95ba8b4
--- /dev/null
+++ b/main.tex
@@ -0,0 +1,102 @@
+\documentclass[times]{pidi-thesis}
+
+% --- Bibliography
+\usepackage[backend=biber,style=authoryear,sorting=nyt]{biblatex}
+\addbibresource{references.bib}
+
+% Language
+\selectlanguage{ngerman}
+
+% --- Metadata
+\setthesismeta
+ {Houston Dokumente: Kundendokumente aus S3}
+ {Houston Dokumente}
+ {Linus Nagel}
+ {2024008}
+ {Bachelor of Science - IT und Software Systeme}
+ {ITC Dortmund}
+ {Informatik}
+ {WorkSimple GmbH}
+ {Sarah Hinzmann}
+
+\setdates
+{TODO -- TODO}
+{TODO}
+
+\begin{document}
+
+\renewcommand{\companylogo}{figures/worksimple/Logo_Normal.png}
+\renewcommand{\unilogo}{figures/itc/IT-Center_Dortmund_Logo.svg.png}
+\renewcommand{\headerlogo}{figures/worksimple/Icon.png}
+\frontmatterpages
+
+\chapter{Vorstellung des Unternehmens}
+\label{chap:company}
+\input{chapters/company/worksimple}
+\input{chapters/company/products-and-services}
+\input{chapters/company/econ-localization}
+
+\chapter{Projektüberblick}
+\label{chap:overview}
+\input{chapters/overview/project-description}
+\input{chapters/overview/initial-situation}
+\input{chapters/overview/system-landscape}
+\input{chapters/overview/target-situation}
+\input{chapters/overview/project-scope}
+\input{chapters/overview/participants}
+
+\chapter{Planung und Vorbereitung}
+\label{chap:planning}
+\input{chapters/planning/onboarding}
+\input{chapters/planning/feature-analysis}
+\input{chapters/planning/requirements}
+\input{chapters/planning/backlog}
+\input{chapters/planning/schedule}
+\input{chapters/planning/infrastructure}
+
+\chapter{Konzeption}
+\label{chap:conception}
+\input{chapters/conception/s3-layout}
+\input{chapters/conception/authorization}
+\input{chapters/conception/document-types}
+\input{chapters/conception/ui-concept}
+\input{chapters/conception/lookup-research}
+\input{chapters/conception/lookup-decision}
+
+\chapter{Umsetzung}
+\label{chap:execution}
+\input{chapters/execution/architecture}
+\input{chapters/execution/s3-client}
+\input{chapters/execution/document-explorer}
+\input{chapters/execution/type-icons}
+\input{chapters/execution/search}
+\input{chapters/execution/filter-pagination}
+\input{chapters/execution/downloads}
+\input{chapters/execution/pdf-preview}
+\input{chapters/execution/url-files}
+\input{chapters/execution/folder-management}
+\input{chapters/execution/race-conditions}
+
+\chapter{Qualitätssicherung und Auslieferung}
+\label{chap:qa}
+\input{chapters/qa/test-strategy}
+\input{chapters/qa/unit-tests}
+\input{chapters/qa/code-reviews}
+\input{chapters/qa/acceptance-testing}
+\input{chapters/qa/releases}
+
+\chapter{Projektabschluss}
+\label{chap:closure}
+\input{chapters/closure/target-comparison}
+\input{chapters/closure/evaluation}
+\input{chapters/closure/reflection}
+\input{chapters/closure/outlook}
+
+\appendix
+
+\chapter{Anhang}
+\input{appendix/appendix}
+
+\printrefs
+
+\end{document}
diff --git a/pidi-thesis.cls b/pidi-thesis.cls
new file mode 100644
index 0000000..3ca30bb
--- /dev/null
+++ b/pidi-thesis.cls
@@ -0,0 +1,246 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesClass{pidi-thesis}[2025/09/03 v1.0 PidI Thesis Class]
+
+\newif\if@times
+\newif\if@calibri
+\newif\if@arial
+\@timestrue % default
+
+\DeclareOption{times}{\@timestrue \@arialfalse \@calibrifalse}
+\DeclareOption{calibri}{\@calibritrue \@arialfalse \@timesfalse}
+\DeclareOption{arial}{\@arialtrue \@calibrifalse \@timesfalse}
+
+% pass through unknown options to base class if needed
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}
+\ProcessOptions\relax
+
+% size depends on font choice: Times (12pt) vs sans (11pt)
+\if@times
+\LoadClass[12pt,a4paper]{report}
+\else
+\LoadClass[11pt,a4paper]{report}
+\fi
+
+% --- Packages
+\RequirePackage[a4paper,left=3cm,right=2.5cm,top=3cm,bottom=2.5cm,headsep=1cm,footskip=10mm,includehead,includefoot]{geometry}
+\RequirePackage{float}
+\RequirePackage{iftex}
+\RequirePackage{microtype}
+\RequirePackage{setspace}
+\RequirePackage{graphicx}
+\RequirePackage{booktabs}
+\RequirePackage{tabularx}
+\RequirePackage{caption}
+\RequirePackage{titlesec}
+\RequirePackage{enumitem}
+\RequirePackage{fancyhdr}
+\RequirePackage{hyperref}
+\RequirePackage{xcolor}
+\RequirePackage[ngerman,english]{babel}
+\RequirePackage{csquotes}
+\RequirePackage{transparent}
+\RequirePackage[absolute,overlay]{textpos}
+\RequirePackage{changepage}
+\RequirePackage{listings}
+\RequirePackage{minted}
+\RequirePackage{pdfpages}
+\RequirePackage{longtable}
+\RequirePackage[htt]{hyphenat}
+
+% Code highlighting
+\usemintedstyle{default}
+
+% Fonts: sans (Arial/Calibri) in 11pt, or Times New Roman 12pt
+\ifPDFTeX
+\if@times
+\RequirePackage{newtxtext}
+\else
+\RequirePackage[scaled=0.95]{helvet}
+\renewcommand{\familydefault}{\sfdefault}
+\fi
+\else
+\RequirePackage{fontspec}
+\if@times
+\setmainfont{TimesNewerRoman-Regular.otf}[
+BoldFont = TimesNewerRoman-Bold.otf,
+ItalicFont = TimesNewerRoman-Italic.otf,
+BoldItalicFont = TimesNewerRoman-BoldItalic.otf
+]
+\else
+\if@calibri
+\setmainfont{Calibri}
+\else
+\setmainfont{Arial}
+\fi
+\fi
+\fi
+
+% Line spacing
+\setstretch{1.3}
+
+% Paragraph spacing
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{6pt}
+
+% Headings: bold + clear visual hierarchy
+\titleformat{\chapter}{\bfseries\LARGE}{\thechapter\quad}{0pt}{}
+\titlespacing*{\chapter}{0pt}{*2}{*1}
+\titleformat{\section}{\bfseries\Large}{\thesection\quad}{0pt}{}
+\titlespacing*{\section}{0pt}{*1.5}{*0.8}
+\titleformat{\subsection}{\bfseries\large}{\thesubsection\quad}{0pt}{}
+\titlespacing*{\subsection}{0pt}{*1.2}{*0.6}
+
+% Emphasis should be bold as per spec
+\renewcommand{\emph}[1]{\textbf{#1}}
+
+% Captions a bit tighter
+\captionsetup{font=small,labelfont=bf}
+
+% Lists tighter by default
+\setlist{itemsep=3pt plus 1pt, topsep=6pt}
+
+% Header & footer: page number bottom-center; optional header with short title
+\pagestyle{fancy}
+\fancyhf{} % clear
+\fancyfoot[C]{\thepage}
+\renewcommand{\headrulewidth}{0pt}
+\renewcommand{\footrulewidth}{0pt}
+
+% Redefine 'plain' style to ensure chapter starting pages also use bottom-center numbering
+\fancypagestyle{plain}{
+ \fancyhf{}
+ \fancyfoot[C]{\thepage}
+ \renewcommand{\headrulewidth}{0pt}
+ \renewcommand{\footrulewidth}{0pt}
+}
+
+% Optional header content command; placed 1cm above text via headsep=1cm
+\newcommand{\shorthead}{}
+\fancyhead[L]{\shorthead}
+
+\newcommand{\headerlogo}{}
+\fancyhead[R]{\IfFileExists{\headerlogo}{\includegraphics[height=1em]{\headerlogo}}{}}
+
+\renewcommand{\headrulewidth}{0.4pt}
+
+% Hyperref setup
+\hypersetup{
+pdftitle={},
+pdfauthor={},
+colorlinks=true,
+linkcolor=[rgb]{0.0,0.2,0.6},
+citecolor=[rgb]{0.0,0.2,0.6},
+urlcolor=[rgb]{0.0,0.2,0.6}
+}
+
+% --- Meta fields
+\newcommand{\thesistitle}{}
+\newcommand{\thesisshorttitle}{}
+\newcommand{\authorname}{}
+\newcommand{\matrikel}{}
+\newcommand{\degree}{}
+\newcommand{\institution}{}
+\newcommand{\faculty}{}
+\newcommand{\course}{Praktikum in der Industrie (PidI 3)}
+\newcommand{\company}{}
+\newcommand{\advisor}{}
+\newcommand{\daterange}{}
+\newcommand{\submissiondate}{}
+
+\newcommand{\setthesismeta}[9]{%
+\renewcommand{\thesistitle}{#1}%
+\renewcommand{\thesisshorttitle}{#2}%
+\renewcommand{\authorname}{#3}%
+\renewcommand{\matrikel}{#4}%
+\renewcommand{\degree}{#5}%
+\renewcommand{\institution}{#6}%
+\renewcommand{\faculty}{#7}%
+\renewcommand{\company}{#8}%
+\renewcommand{\advisor}{#9}%
+}
+
+\newcommand{\setdates}[2]{%
+\renewcommand{\daterange}{#1}%
+\renewcommand{\submissiondate}{#2}%
+}
+
+% Update header and pdf meta when title/author set
+\AtBeginDocument{%
+\renewcommand{\shorthead}{\thesisshorttitle}%
+\hypersetup{pdftitle=\thesistitle, pdfauthor=\authorname}%
+}
+
+% Title page per spec, clean & simple
+\newcommand{\companylogo}{}
+\newcommand{\unilogo}{}
+\newcommand{\maketitlepage}{%
+\begin{titlepage}
+
+\newcommand{\hlogo}{1.5cm}
+
+\centering
+
+{\bfseries\LARGE \thesistitle\par}
+\vspace{2em}
+{\Large \course\par}
+\vspace{2em}
+{\large \textbf{Autor/in:} \authorname \\
+\textbf{Matrikelnummer:} \matrikel \par}
+\vspace{1em}
+{\large \textbf{Studiengang/Abschluss:} \degree \par}
+\vspace{1em}
+{\large \textbf{Hochschule:} \institution \\
+\textbf{Fakultät/Bereich:} \faculty \par}
+\vspace{1em}
+{\large \textbf{Partnerunternehmen:} \company \\
+\textbf{Betreuer/in im Unternehmen:} \advisor \par}
+
+\vspace{2em}
+\includegraphics[height=\hlogo]{\companylogo}
+\hfill
+\includegraphics[height=\hlogo]{\unilogo}
+\vfill
+{\large \textbf{Tätigkeitszeitraum:} \daterange \par}
+\vspace{0.5em}
+{\large \textbf{Abgabedatum:} \submissiondate \par}
+
+\addcontentsline{toc}{chapter}{Titelseite}
+\end{titlepage}
+}
+
+% Confirmation page (Bescheinigung)
+\newcommand{\confirmationpage}{%
+\chapter*{Bescheinigung}
+Hiermit wird bestätigt, dass \textbf{\authorname} das Praktikum \textbf{\course} im Partnerunternehmen \textbf{\company} im Zeitraum \textbf{\daterange} selbständig durchgeführt hat. Es wurden mindestens \textbf{24 Manntage} an dem Projekt gearbeitet. Der Einsatz von KI beschränkt sich maximal auf die erlaubten Zwecke.
+
+\vspace{4em}
+\begin{tabularx}{\textwidth}{X X}
+\hrulefill & \hrulefill \\
+Ort, Datum & Unterschrift Betreuer/in \\
+\end{tabularx}
+
+\addcontentsline{toc}{chapter}{Bescheinigung}
+\clearpage
+}
+
+% Abstract & declarations convenience
+\newcommand{\frontmatterpages}{%
+\pagenumbering{roman}
+\maketitlepage
+\renewcommand*\contentsname{Inhaltsangabe}
+\tableofcontents
+\addcontentsline{toc}{chapter}{Inhaltsangabe}
+\confirmationpage
+\input{frontmatter/usage-of-ai}
+\input{frontmatter/abstract}
+\input{frontmatter/acknowledgments}
+\clearpage
+\pagenumbering{arabic}
+}
+
+% Bibliography (biblatex expected)
+\newcommand{\printrefs}{%
+\clearpage
+\addcontentsline{toc}{chapter}{Literaturverzeichnis}
+\printbibliography
+}
diff --git a/references.bib b/references.bib
new file mode 100644
index 0000000..c55a17a
--- /dev/null
+++ b/references.bib
@@ -0,0 +1,92 @@
+@comment{Quellen für PidI 3 — Houston Dokumente}
+
+@online{aws-s3-select,
+ author = {{Amazon Web Services}},
+ title = {Selecting content from objects},
+ url = {https://docs.aws.amazon.com/AmazonS3/latest/userguide/selecting-content-from-objects.html},
+ urldate = {2026-08-25}
+}
+
+@online{aws-listobjectsv2,
+ author = {{Amazon Web Services}},
+ title = {ListObjectsV2},
+ url = {https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html},
+ urldate = {2026-08-25}
+}
+
+@online{aws-s3-naming,
+ author = {{Amazon Web Services}},
+ title = {Object key naming guidelines},
+ url = {https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html},
+ urldate = {2026-08-25}
+}
+
+@online{aws-conditional-writes,
+ author = {{Amazon Web Services}},
+ title = {Conditional requests for Amazon S3},
+ url = {https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-requests.html},
+ urldate = {2026-08-25}
+}
+
+@online{aws-presigned-urls,
+ author = {{Amazon Web Services}},
+ title = {Sharing objects with presigned URLs},
+ url = {https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html},
+ urldate = {2026-08-25}
+}
+
+@online{storagegrid-s3-select,
+ author = {{NetApp}},
+ title = {Use S3 Select Object Content},
+ url = {https://docs.netapp.com/us-en/storagegrid/s3/select-object-content.html},
+ urldate = {2026-08-25}
+}
+
+@online{storagegrid-search-integration,
+ author = {{NetApp}},
+ title = {Use the StorageGRID search integration service},
+ url = {https://docs.netapp.com/us-en/storagegrid-enable/product-feature-guides/storagegrid-search-integration-service.html},
+ urldate = {2026-08-25}
+}
+
+@online{ibm-s3-naming,
+ author = {{IBM}},
+ title = {Naming constraints for object storage},
+ url = {https://www.ibm.com/docs/en/ahts/4.4.x?topic=reference-naming-constraints},
+ urldate = {2026-08-25}
+}
+
+@online{filestash-s3,
+ author = {{Mickael Kerjean}},
+ title = {Filestash — S3 Browser},
+ url = {https://www.filestash.app/s3-browser.html},
+ urldate = {2026-08-25}
+}
+
+@online{dotnet-keyed-di,
+ author = {{Microsoft}},
+ title = {Keyed services in .NET dependency injection},
+ url = {https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#keyed-services},
+ urldate = {2026-08-25}
+}
+
+@online{dotnet-zip,
+ author = {{Microsoft}},
+ title = {ZipArchive Class},
+ url = {https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.ziparchive},
+ urldate = {2026-08-25}
+}
+
+@online{entra-app-roles,
+ author = {{Microsoft}},
+ title = {Add app roles to your application and receive them in the token},
+ url = {https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-app-roles-in-apps},
+ urldate = {2026-08-25}
+}
+
+@online{razor-pages,
+ author = {{Microsoft}},
+ title = {Introduction to Razor Pages in ASP.NET Core},
+ url = {https://learn.microsoft.com/en-us/aspnet/core/razor-pages/},
+ urldate = {2026-08-25}
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..2b506e3
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,47 @@
+with import {}; let
+ fonts = [
+ times-newer-roman
+ ];
+ # This is not reccocgnised by latexmk, so we will have to put our
+ # font files in ~/.local/share/fonts
+ # fontsConf = makeFontsConf {
+ # fontDirectories = fonts;
+ # };
+ # export FONTCONFIG_FILE="${fontsConf}"
+in
+ mkShell {
+ nativeBuildInputs = fonts;
+ packages = [
+ latexrun
+ mermaid-cli
+ times-newer-roman
+ (texlive.withPackages (ps:
+ with ps; [
+ transparent
+ times
+ hyphenat
+ changepage
+ biblatex
+ listings
+ minted
+ upquote
+ biber
+ fontaxes
+ newtxtt
+ newtx
+ newtxsf
+ csquotes
+ enumitem
+ titlesec
+ latexmk
+ scheme-medium
+ textpos
+ ]))
+ ];
+ shellHook = ''
+ # install fonts
+ DEST=~/.local/share/fonts/TimesNewerRoman
+ mkdir -p $DEST
+ cp -r ${toString times-newer-roman}/share/fonts/opentype "$DEST"
+ '';
+ }