-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy patharchitecture.tex
More file actions
223 lines (186 loc) · 10.4 KB
/
Copy patharchitecture.tex
File metadata and controls
223 lines (186 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
\documentclass[11pt,a4paper]{article}
\input{preamble}
\fancyhead[L]{\small\textsc{tcfs}}
\fancyhead[R]{\small Architecture}
\title{tcfs Architecture}
\author{tcfs / TummyCrypt}
\date{February 2026}
\begin{document}
\maketitle
\tableofcontents
\newpage
% ─────────────────────────────────────────────────────────────────────────────
\section{Overview}
\tcfs{} (TummyCrypt FileSystem) is a FOSS, self-hosted, S3-first synchronization
system that replaces proprietary cloud storage clients (odrive, Dropbox, etc.)
with platform-specific filesystem surfaces that transparently hydrate files on
demand.
\subsection{Design Goals}
\begin{enumerate}
\item \textbf{Self-hosted first} --- all data stays on user-controlled infrastructure (SeaweedFS).
\item \textbf{On-demand hydration} --- remote files appear locally as clean
names or platform placeholders and are downloaded only when accessed.
\item \textbf{End-to-end encryption} --- client-side XChaCha20-Poly1305 encryption
before upload; storage operator never sees plaintext.
\item \textbf{Content-addressed deduplication} --- FastCDC chunking with BLAKE3
hashing eliminates redundant storage.
\item \textbf{Cross-platform} --- Linux (FUSE3), macOS/iOS (FileProvider), Windows (Cloud Files API).
\item \textbf{Kubernetes-native backend} --- stateless sync workers scaled by KEDA,
NATS JetStream for reliable task dispatch.
\end{enumerate}
% ─────────────────────────────────────────────────────────────────────────────
\section{System Architecture}
The system is divided into client-side and server-side components connected
via S3 API and NATS JetStream.
\subsection{Client Side}
The client runs on user machines and consists of:
\begin{description}
\item[\tcfsd{} (daemon)] Long-running process exposing a gRPC service over a
Unix domain socket. Manages Linux FUSE mounts, credential loading, sync state,
and Prometheus metrics. Reports readiness via \code{sd\_notify(READY=1)}.
\item[\tcfs{} (CLI)] Command-line interface for push, pull, mount, unmount,
sync-status, and unsync operations.
\item[\code{tcfs-tui} (TUI)] Interactive terminal dashboard built with
ratatui~0.30, connecting to the daemon via gRPC. Five tabs: Dashboard,
Config, Mounts, Secrets, Conflicts.
\item[\code{tcfs-mcp} (MCP server)] Model Context Protocol server for AI
agent integration. Seven non-resolution tools over stdio JSON-RPC transport.
\end{description}
\subsection{Server Side (Kubernetes Model)}
\begin{description}
\item[SeaweedFS cluster] Distributed blob storage. Three Raft masters for
metadata consensus, volume servers on Drobo 5C for data.
\item[NATS JetStream] Reliable task queue with two streams:
\code{SYNC\_TASKS} and \code{HYDRATION\_EVENTS}.
\item[Sync workers] Stateless \tcfsd{} instances running in
\code{--mode=worker}. Designed for horizontal KEDA scaling based on NATS
queue depth; full rollout proof is still tracked separately.
\item[Prometheus + Grafana] Observability stack monitoring throughput,
queue depth, and FUSE latency.
\end{description}
% ─────────────────────────────────────────────────────────────────────────────
\section{Crate Map}
All Rust code lives in \filepath{crates/}. The workspace contains 18 product
crates plus an end-to-end test crate:
\begin{longtable}{llp{8cm}}
\toprule
\textbf{Crate} & \textbf{Type} & \textbf{Purpose} \\
\midrule
\endhead
\code{tcfs-core} & library & Shared types, config schema, protobuf defs \\
\code{tcfs-crypto} & library & XChaCha20-Poly1305, Argon2id KDF, HKDF, BIP-39 \\
\code{tcfs-auth} & library & TOTP, WebAuthn/FIDO2, session, and enrollment helpers \\
\code{tcfs-secrets} & library & SOPS/age/KDBX credential chain \\
\code{tcfs-storage} & library & OpenDAL abstraction, SeaweedFS native API \\
\code{tcfs-chunks} & library & FastCDC chunking, BLAKE3 hashing, zstd compression \\
\code{tcfs-sync} & library & Sync engine, JSON state cache, NATS consumers \\
\code{tcfs-vfs} & library & Shared virtual filesystem, disk cache, stubs, hydration \\
\code{tcfs-fuse} & library & Linux FUSE driver (fuse3 crate) \\
\code{tcfs-nfs} & library & NFS loopback mount backend \\
\code{tcfs-cloudfilter} & library & Windows Cloud Files API (skeleton) \\
\code{tcfs-sops} & library & SOPS+age fleet secret propagation \\
\code{tcfs-file-provider} & library & macOS/iOS FileProvider FFI (RFC 0002) \\
\code{tcfs-dbus} & library & Linux D-Bus desktop status integration \\
\code{tcfsd} & binary & Daemon: gRPC, Linux FUSE, metrics, systemd \\
\code{tcfs-cli} & binary & CLI: push, pull, mount, status, unsync \\
\code{tcfs-tui} & binary & TUI: ratatui dashboard \\
\code{tcfs-mcp} & binary & MCP server: 7 non-resolution tools, stdio transport \\
\bottomrule
\end{longtable}
% ─────────────────────────────────────────────────────────────────────────────
\section{Physical Stub File Format}
Physical sync-root and compatibility paths can represent files as \code{.tc}
stubs. Mounted VFS views normally expose clean filenames and hydrate from remote
index entries; macOS FileProvider uses platform placeholders / APFS dataless
files. A physical \code{.tc} stub is a small sorted key/value text file:
\begin{lstlisting}
version https://tummycrypt.io/tcfs/v1
chunks 23
compressed 0
fetched 0
oid blake3:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e239
origin seaweedfs://filer.example.com/bucket/path/to/file
size 94371840
\end{lstlisting}
Directory stubs use the \code{.tcf} extension for physical directory
dehydration/compatibility paths. Mounted directory listings normally come from
remote \filepath{\{prefix\}/index/...} entries.
% ─────────────────────────────────────────────────────────────────────────────
\section{Hydration Sequence}
When a remote-backed file is opened through the mounted VFS:
\begin{enumerate}
\item The mount backend's \code{open()} handler intercepts the file access
request.
\item \tcfsd{} fetches the manifest from
\filepath{\{prefix\}/manifests/\{file\_hash\}}.
\item Chunks are fetched in parallel from
\filepath{\{prefix\}/chunks/\{chunk\_hash\}}.
\item Each chunk is decompressed (zstd), decrypted (XChaCha20-Poly1305),
and verified (BLAKE3).
\item Chunks are concatenated in order to reconstruct the original file.
\item The file is served to the caller and cached for future reads.
\item Unsync/dehydrate evicts cached content or creates a physical
\code{.tc} stub, depending on the surface.
\end{enumerate}
% ─────────────────────────────────────────────────────────────────────────────
\section{Credential Chain}
\tcfsd{} discovers age identities in order of precedence:
\begin{enumerate}
\item \code{\$CREDENTIALS\_DIRECTORY/age-identity} --- systemd
\code{LoadCredentialEncrypted}
\item \code{\$SOPS\_AGE\_KEY\_FILE} --- path to an age key file
\item \code{\$SOPS\_AGE\_KEY} --- literal age key content
\item \filepath{\textasciitilde/.config/sops/age/keys.txt} --- default fallback
\end{enumerate}
Once loaded, the age identity decrypts SOPS-encrypted credential YAML files,
providing S3 access keys to the OpenDAL operator. An mtime watcher
auto-reloads credentials when the file changes on disk.
% ─────────────────────────────────────────────────────────────────────────────
\section{Phase Roadmap}
\begin{longtable}{clp{9cm}}
\toprule
\textbf{Phase} & \textbf{Status} & \textbf{Scope} \\
\midrule
\endhead
0 & Complete & Repo foundation, SOPS migration, Rust workspace stubs \\
1 & Complete & Core daemon + secrets + gRPC \\
2 & Complete & Sync engine + chunking + NATS \\
3 & Complete & FUSE driver + clean VFS hydration + physical stubs \\
4 & Scaffolded / proof pending & K8s backend + HPA + OpenTofu deploy models; full rollout/apply proof pending \\
5 & Complete & Release pipeline + packaging + docs site \\
6 & Partial & macOS FileProvider lab lane + Windows CFAPI skeleton \\
7 & Partial & Benchmark snapshot, fleet ops, Darwin RFC, production hardening \\
\bottomrule
\end{longtable}
% ─────────────────────────────────────────────────────────────────────────────
\section{Infrastructure}
\subsection{Local Network (Bare-Metal)}
\begin{longtable}{ll}
\toprule
\textbf{Role} & \textbf{Address} \\
\midrule
\endhead
SeaweedFS master-1 & 192.168.101.249:9333 \\
SeaweedFS master-2 & 192.168.101.184:9333 \\
SeaweedFS master-3 & 192.168.101.248:9333 \\
Volume server (Drobo 5C) & 192.168.101.171:8080 \\
Filer / S3 gateway & 192.168.101.146:8333 \\
\bottomrule
\end{longtable}
\subsection{Legacy Civo Kubernetes}
This table records the earlier Civo deployment shape. Current live/on-prem
authority is tracked in \texttt{docs/ops/onprem-authority-recovery.md} and
\texttt{docs/ops/product-reality-and-priority.md}.
\begin{longtable}{ll}
\toprule
\textbf{Property} & \textbf{Value} \\
\midrule
\endhead
Cluster & bitter-darkness-16657317 \\
Namespace & tcfs \\
In-cluster SeaweedFS & seaweedfs.tcfs.svc.cluster.local:8333 \\
In-cluster NATS & nats.tcfs.svc.cluster.local:4222 \\
Container image & ghcr.io/jesssullivan/tcfsd \\
\bottomrule
\end{longtable}
\end{document}