Skip to content

Commit cc9c862

Browse files
committed
site: publish from wyrd@3b8e20eafc33b30f3a359c7a02a1f16b1fa6962b getwyrd/wyrd@3b8e20e
1 parent bf64ddd commit cc9c862

5 files changed

Lines changed: 259 additions & 102 deletions

architecture/05-building-block-view.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ <h2>5.1 The actor view — the components and how they collaborate</h2>
105105
<tr>
106106
<td><strong>Metadata store</strong> <em>(the commit point)</em></td>
107107
<td>Holds the map and hosts the single atomic mutation that makes a write visible.</td>
108-
<td>The linchpin. Inodes, dirents, chunk maps, the pending-chunk ledger, version counters. The atomicity guarantee — the project's reason to exist — lives in <em>one mutation here</em>, not in any other component. <code>redb</code> embedded / TiKV production, behind <code>MetadataStore</code>.</td>
108+
<td>The linchpin. Inodes, dirents, chunk maps, the pending-chunk ledger, version counters. The atomicity guarantee — the project's reason to exist — lives in <em>one mutation here</em>, not in any other component. <code>redb</code> embedded (dev) / <strong>FoundationDB</strong> production (ADR-0042), behind <code>MetadataStore</code>; TiKV is a retained fallback with development stood down (#443).</td>
109109
</tr>
110110
<tr>
111111
<td><strong>Client</strong> <em>(the thick brain)</em></td>
@@ -283,7 +283,7 @@ <h3>L4 — Zonal file system (the Colossus analog, one per datacenter)</h3>
283283
<tbody>
284284
<tr>
285285
<td>Metadata store</td>
286-
<td><code>redb</code> (embedded) / TiKV (prod), behind <code>MetadataStore</code> trait</td>
286+
<td><code>redb</code> (embedded, dev) / <strong>FoundationDB</strong> (prod, ADR-0042), behind <code>MetadataStore</code> trait; TiKV retained as a stood-down fallback (#443)</td>
287287
<td>Inodes, dirents, chunk maps, the pending-chunk GC ledger, version counters. Hosts the single atomic mutation that <em>is</em> the commit point.</td>
288288
</tr>
289289
<tr>
@@ -310,7 +310,7 @@ <h4>The metadata model</h4>
310310
<li><code>inode:&lt;id&gt;</code> → attributes, chunk map (or inline data for small files), state, version.</li>
311311
<li><code>dirent:&lt;parent_id&gt;/&lt;name&gt;</code> → child inode id.</li>
312312
</ul>
313-
<p>This makes rename a single dirent mutation (atomic under the same mechanism as a write) instead of a mass key rewrite, and makes cross-zone sharing expressible (a dirent pointing at an inode owned elsewhere). It is the strongest concrete driver of the TiKV-over-HBase choice, because file creation must atomically write both the inode and its dirent — a multi-key transaction. See section 6 and ADR-0008.</p>
313+
<p>This makes rename a single dirent mutation (atomic under the same mechanism as a write) instead of a mass key rewrite, and makes cross-zone sharing expressible (a dirent pointing at an inode owned elsewhere). It is the strongest concrete driver of the requirement that the metadata store offer an <strong>atomic multi-key transaction</strong>, because file creation must atomically write both the inode and its dirent. That requirement is what disqualified HBase-class stores and what every backend choice since has had to satisfy; the backend satisfying it in production is now FoundationDB (ADR-0042, superseding ADR-0008's TiKV). See section 6.</p>
314314
<h4>The write protocol (the commit point)</h4>
315315
<p>The same collaboration described in §5.1 as actor interaction, here in terms of
316316
the L4 mechanics it touches:</p>
@@ -390,7 +390,7 @@ <h2>5.3 Cross-cutting components</h2>
390390
</tr>
391391
</tbody>
392392
</table>
393-
<p>The dependency rule (ADR-0010): implementations and consumers depend on <code>traits</code>, never on each other's concretes. Only <code>server</code> knows the concrete backends, which is what makes &quot;swap redb for TiKV&quot; or &quot;in-memory for etcd&quot; a composition change rather than a refactor.</p>
393+
<p>The dependency rule (ADR-0010): implementations and consumers depend on <code>traits</code>, never on each other's concretes. Only <code>server</code> knows the concrete backends, which is what makes &quot;swap redb for FoundationDB&quot; or &quot;in-memory for etcd&quot; a composition change rather than a refactor. The seam earned its keep in M4: swapping the production backend from TiKV to FoundationDB (ADR-0042) touched the <code>server</code> wiring and added a crate, and changed no consumer.</p>
394394

395395
</article>
396396
</main>

architecture/07-deployment-view.html

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ <h2>7.1 The three deployment profiles</h2>
7878
<td>Small multi-node</td>
7979
<td>3-node etcd</td>
8080
<td>step-ca (SPIRE reserved)</td>
81-
<td>TiKV (small) / redb</td>
81+
<td><strong>FoundationDB</strong> / redb</td>
8282
<td>none — single-zone</td>
8383
<td>local-disk D servers</td>
8484
<td>replication(n) or rs(k,m)</td>
@@ -88,14 +88,16 @@ <h2>7.1 The three deployment profiles</h2>
8888
<td>Provider fleet</td>
8989
<td>dedicated etcd per zone</td>
9090
<td>step-ca, HA (SPIRE reserved)</td>
91-
<td>TiKV</td>
91+
<td><strong>FoundationDB</strong></td>
9292
<td>TiDB + L3 replication (multi-region)</td>
9393
<td>local-disk D servers</td>
9494
<td>rs(k,m)</td>
9595
<td>Production</td>
9696
</tr>
9797
</tbody>
9898
</table>
99+
<p><strong>The production metadata backend is FoundationDB</strong> (ADR-0042, which supersedes ADR-0008's TiKV choice). It cleared the M4 fault + contention battery — the go/no-go gate on our mapping layer, not on FDB itself (<code>docs/design/reviews/m4-fdb-go-no-go.md</code>, #442). The canonical single-zone stack is <code>deploy/small-multi-node-fdb/</code>.</p>
100+
<p><strong>TiKV is a retained fallback, and active development on it is stood down</strong> (#443). The <code>metadata-tikv</code> crate, the <code>tikv</code> feature, the CLI backend variant and the TiKV deploy stacks all remain in the tree, buildable and community-continuable — nothing was removed, and the continuation backlog stays open under the <em>Metadata Store TiKV</em> milestone. But it is not a production path: <code>tikv-client</code> 0.4.0 is abandoned upstream and carries unpatched advisories in its TLS stack, including a live DoS in CRL parsing (RUSTSEC-2026-0104, high); the exposure boundary is recorded in <code>deny-all-features.toml</code> (#543). Choose it only if you are continuing that backlog, never for a new deployment.</p>
99101
<p>The single-binary profile collapses all components into one process: gateway, embedded metadata, one logical D server, custodians, in-memory coordination, and a built-in <strong>dev-CA</strong> in place of the production CA (ADR-0025, ADR-0036) so a one-process system is not gated on a full PKI. It exists for development and evaluation and carries <strong>no production durability promise</strong> — a single chassis cannot deliver independent failure domains.</p>
100102
<p>The <strong>Identity / PKI</strong> column tracks the trust plane behind the mTLS fabric (§8.5, ADR-0005/0025): a built-in dev-CA in the single binary, and a <strong>self-hosted provider CA — <code>step-ca</code> now, with SPIRE reserved</strong> — for the production profiles (ADR-0036). It follows the same dev→fleet gradient as coordination, and — because internal mTLS is fail-closed (ADR-0025) — it is a first-class control-plane dependency, not an afterthought (see §7.3 and the §6.5 restore order). SPIRE (secret-less workload attestation) is the <em>reserved</em> upgrade, adopted at the fleet scale where its benefit outweighs its operational cost — a SPIRE Server plus a per-node Agent and attestation config; until then <code>step-ca</code> issues the short-lived, auto-rotated certs behind a <code>CertificateAuthority</code> seam, so the eventual switch is a composition change. The full rationale (why step-ca now, why SPIRE deferred, why not Vault) lives in ADR-0036.</p>
101103
<p><strong>There is no separate L2/L3 below the multi-zone tier.</strong> The single-binary and small-multi-node profiles are <em>single-zone</em>: there is one home zone, so file→home-zone is trivial and the global namespace folds into the zonal store — <code>NamespaceStore</code> is backed by the same redb instance as <code>MetadataStore</code>, and cross-zone replication (L3) does not exist. A distinct, geo-distributed <strong>L2</strong> (TiDB behind <code>NamespaceStore</code>, ADR-0020) and the <strong>L3</strong> replication layer appear only at the <strong>provider-fleet</strong> profile — the first genuinely multi-region tier. This is why the build order (section 9) puts L2/L3 last.</p>
@@ -186,11 +188,11 @@ <h2>7.5 Communication paths, ports, and protocols</h2>
186188
<td>direct <strong>bulk fragment</strong> I/O; ADR-0025; <code>crates/server/src/cli.rs:32</code></td>
187189
</tr>
188190
<tr>
189-
<td>Gateway / client lib → metadata (TiKV)</td>
190-
<td>gRPC</td>
191-
<td>PD <code>2379</code>, TiKV <code>20160</code></td>
192-
<td>mTLS</td>
193-
<td>atomic multi-key commit; ADR-0008. <em>redb backend is embedded — in-process, no port</em></td>
191+
<td>Gateway / client lib → metadata (<strong>FoundationDB</strong>)</td>
192+
<td>FDB client protocol (<code>libfdb_c</code>)</td>
193+
<td><code>4500</code> (coordinators)</td>
194+
<td>TLS</td>
195+
<td>atomic multi-key commit; ADR-0042, §7.6. <em>redb backend is embedded — in-process, no port</em></td>
194196
</tr>
195197
<tr>
196198
<td>Custodian → D servers</td>
@@ -200,11 +202,18 @@ <h2>7.5 Communication paths, ports, and protocols</h2>
200202
<td>scrub / repair / reconstruct</td>
201203
</tr>
202204
<tr>
203-
<td>Custodian → metadata (TiKV)</td>
205+
<td>Custodian → metadata (<strong>FoundationDB</strong>)</td>
206+
<td>FDB client protocol (<code>libfdb_c</code>)</td>
207+
<td><code>4500</code></td>
208+
<td>TLS</td>
209+
<td>under-replication scan, chunk-maps</td>
210+
</tr>
211+
<tr>
212+
<td><em>(fallback)</em> → metadata (TiKV)</td>
204213
<td>gRPC</td>
205214
<td>PD <code>2379</code>, TiKV <code>20160</code></td>
206215
<td>mTLS</td>
207-
<td>under-replication scan, chunk-maps</td>
216+
<td>the retained-fallback path only (#443); ADR-0008, superseded by ADR-0042</td>
208217
</tr>
209218
<tr>
210219
<td>All components → Coordination (etcd)</td>
@@ -236,8 +245,8 @@ <h2>7.5 Communication paths, ports, and protocols</h2>
236245
</tr>
237246
</tbody>
238247
</table>
239-
<p><strong>Port honesty.</strong> Only <code>50051</code> (the D-server gRPC bind) is fixed in Wyrd's own code today (<code>crates/server/src/cli.rs:32</code>). The metadata, coordination, and telemetry ports — PD <code>2379</code> / TiKV <code>20160</code>, etcd <code>2379</code>/<code>2380</code>, OTLP <code>4317</code>/<code>4318</code> — are the <strong>upstream projects' conventional defaults</strong>, not Wyrd's to assign. The S3, SDK, management, and Prometheus-scrape <em>listen</em> addresses are <strong>operator-configured</strong>; M4 fixes the exact flag names (see the blueprint's <code>[wyrd-config]</code> markers). All internal service-to-service dials are <strong>mTLS under the provider CA with no plaintext fallback</strong> (ADR-0005, ADR-0025); a plaintext internal dial is refused (M2).</p>
240-
<p><strong>Two planes.</strong> Bulk <strong>fragment</strong> data flows directly client/gateway → D servers (the gRPC chunk path that scales with the fleet); the <strong>metadata commit</strong> is a separate, smaller gRPC path to TiKV. Keeping them distinct is the Colossus-class separation that lets throughput scale with D servers rather than through a metadata bottleneck. On a private-network deployment (e.g. Hetzner vSwitch) only the gateway's S3 port is exposed publicly; every other path stays on the internal network.</p>
248+
<p><strong>Port honesty.</strong> Only <code>50051</code> (the D-server gRPC bind) is fixed in Wyrd's own code today (<code>crates/server/src/cli.rs:32</code>). The metadata, coordination, and telemetry ports — FDB <code>4500</code>, PD <code>2379</code> / TiKV <code>20160</code>, etcd <code>2379</code>/<code>2380</code>, OTLP <code>4317</code>/<code>4318</code> — are the <strong>upstream projects' conventional defaults</strong>, not Wyrd's to assign. The S3, SDK, management, and Prometheus-scrape <em>listen</em> addresses are <strong>operator-configured</strong>; M4 fixes the exact flag names (see the blueprint's <code>[wyrd-config]</code> markers). All internal service-to-service dials are <strong>mTLS under the provider CA with no plaintext fallback</strong> (ADR-0005, ADR-0025); a plaintext internal dial is refused (M2).</p>
249+
<p><strong>Two planes.</strong> Bulk <strong>fragment</strong> data flows directly client/gateway → D servers (the gRPC chunk path that scales with the fleet); the <strong>metadata commit</strong> is a separate, smaller path to the metadata store (FoundationDB in production). Keeping them distinct is the Colossus-class separation that lets throughput scale with D servers rather than through a metadata bottleneck. On a private-network deployment (e.g. Hetzner vSwitch) only the gateway's S3 port is exposed publicly; every other path stays on the internal network.</p>
241250
<p><strong>Out of single-zone scope.</strong> Cross-zone replication (L3) uses <strong>NATS JetStream</strong> (client <code>4222</code>) and appears only at the <strong>provider-fleet</strong> profile (M9+); it is not part of a single-zone deployment (ADR-0027).</p>
242251
<h2>7.6 FoundationDB metadata backend: packaging and version coupling</h2>
243252
<p>ADR-0042 chose FoundationDB (<code>fdb</code>, behind the off-by-default <code>--features fdb</code>) as the production <code>MetadataStore</code> for the Small multi-node and Provider fleet profiles (§7.1). Unlike the pure-Rust TiKV client, the <code>foundationdb</code> crate binds a <strong>shared C library</strong> (<code>libfdb_c</code>) whose wire protocol is <strong>exactly</strong> coupled to the cluster's — a client built against one FDB version cannot talk to a cluster running another, at all, ever. This section is the packaging contract that follows from that fact: how the client library reaches a Wyrd process, and what happens when it disagrees with the cluster (#441).</p>

architecture/09-build-order-and-roadmap.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ <h2>The milestones</h2>
114114
<tr>
115115
<td>M4</td>
116116
<td>Production metadata backend</td>
117-
<td>pluggability is real: redb→TiKV behind the unchanged trait is a composition change, not a refactor</td>
118-
<td>next — proposal 0007</td>
117+
<td>pluggability is real: redb→FoundationDB behind the unchanged trait is a composition change, not a refactor — proven twice, since the backend choice itself moved from TiKV to FDB (ADR-0042) without touching a consumer</td>
118+
<td>FoundationDB is the production backend (ADR-0042, #442 &quot;go&quot;); TiKV retained as a stood-down fallback (#443) — proposals 0007, 0015</td>
119119
</tr>
120120
<tr>
121121
<td>M5</td>

architecture/10-quality-risks-glossary.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ <h3>13.1 The principle: simulation is primary, real environments are complementa
271271
<li><strong>Real performance</strong> — actual latency, real EC encode/decode throughput on real CPUs, real disk and network throughput, tail latencies, and the linear-throughput-scaling claim (scenario Q6).</li>
272272
<li><strong>Real I/O and OS behaviour</strong> — honest fsync semantics, real filesystem quirks, io_uring, page cache, the real network stack under load.</li>
273273
<li><strong>Unmodeled faults</strong> — the failures we did <em>not</em> think to inject: a disk failing slowly rather than cleanly, a NIC corrupting rather than dropping, an OOM-killer intervening, clock skew weirder than the model.</li>
274-
<li><strong>Real integration</strong> — actual etcd, actual TiKV, actual gRPC over a real network, behaving as they really do rather than as their in-memory fakes do.</li>
274+
<li><strong>Real integration</strong> — actual etcd, actual FoundationDB, actual gRPC over a real network, behaving as they really do rather than as their in-memory fakes do.</li>
275275
</ul>
276276
<p>A real environment is therefore never used to test correctness the simulation already covers. If validating the commit protocol's atomicity seems to need a real cluster, that is a signal something is wrong — that is DST's job.</p>
277277
<p><strong>The compounding loop.</strong> Every real-world discovery is promoted back into DST: a fault or workload shape found on real hardware is encoded as a new seed-driven DST scenario, becoming a permanent, free, reproducible regression test. The real tiers are <em>fault-discovery</em> tools; their findings become cheap simulation tests. This is the highest-leverage idea in the strategy — it turns expensive, one-off real-world findings into permanent CI coverage.</p>
@@ -372,7 +372,7 @@ <h3>13.4 Mapping to the arc</h3>
372372
</tr>
373373
<tr>
374374
<td>M4 — production metadata backend</td>
375-
<td>Tier 0–2 against real TiKV</td>
375+
<td>Tier 0–2 against real FoundationDB, incl. the fault + contention battery that gated the &quot;go&quot; (#442). TiKV keeps the same suites as the retained fallback, but its Tier-1 leg is currently red (#537) and its nightly conformance is unbuilt (#420) — under the stand-down (#443) the standing bar is build-only</td>
376376
</tr>
377377
<tr>
378378
<td>M5 — internal CA (step-ca)</td>

0 commit comments

Comments
 (0)