bursa / site / index.html
  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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>bursa — the serverless p2p currency exchange</title>
<style>
  :root {
    --bg: #05060f; --panel: #0b0e1f; --panel-2: #10142a; --border: #1a2140;
    --text: #d8e6ff; --muted: #6b7aa8; --accent: #00f0ff;
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body {
    background: var(--bg); color: var(--text);
    font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    padding: 40px 20px 80px;
  }
  main { max-width: 780px; margin: 0 auto; }
  h1 { font-size: 34px; letter-spacing: 4px; color: var(--accent); text-shadow: 0 0 18px var(--accent); }
  .tag { color: var(--muted); margin: 6px 0 30px; font-size: 17px; }
  h2 { margin: 44px 0 12px; font-size: 22px; color: var(--accent); }
  h3 { margin: 24px 0 8px; font-size: 17px; }
  p, li { color: #b9c6dd; }
  ul { padding-left: 22px; margin: 10px 0; }
  li { margin: 5px 0; }
  a { color: var(--accent); }
  pre {
    background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
    padding: 14px 16px; overflow-x: auto; margin: 12px 0;
    font: 13.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px;
    background: var(--panel-2); border-radius: 5px; padding: 1px 6px; }
  pre code { background: none; padding: 0; }
  .card {
    background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
    padding: 18px 20px; margin: 14px 0;
  }
  .btns { display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 6px; }
  .btn {
    display: inline-block; padding: 10px 18px; border-radius: 8px; text-decoration: none;
    background: #0a1428; border: 1px solid #14406a; color: var(--accent);
    letter-spacing: 1px; font-size: 14px;
  }
  .btn:hover { background: #10305a; box-shadow: 0 0 14px #00f0ff44; }
  footer { margin-top: 60px; color: var(--muted); font-size: 13px; }
</style>
</head>
<body>
<!-- TODO: once the copy below is real, add ro/hu blocks + the language nav
     in the pattern of game1/site/index.html (data-lang-block + localStorage). -->
<main>
  <h1>bursa</h1>
  <p class="tag">orderbooks for the suite's bank currencies, settled atomically — this page is also the git repo.</p>

  <div class="btns">
    <a class="btn" href="https://bursa.ardegazu.ro/">open the app</a>
    <a class="btn" href="browse/index.html">browse the code</a>
    <a class="btn" href="#clone">clone the repo</a>
  </div>

  <h2 id="clone">Clone</h2>
  <p>This site serves the repository over git's dumb-HTTP protocol as plain static
  files (plain files — there is no git server here, or any server at all):</p>
  <pre><code>git clone https://git.ardegazu.ro/bursa.git
cd bursa</code></pre>

  <h2>What it is</h2>
  <p>bursa is a currency exchange with no exchange in it: one encrypted log
  holds the book, every member's replica runs the same matching fold, and a
  trade settles as two bank-held escrow locks under one hashlock — either both
  sides are paid or neither is. Banks come from banca; a match obliges nobody
  until the money locks. Installable PWA — works saved to an
  iOS home screen, safe-area aware.</p>

  <h2>How it works</h2>
  <ul>
    <li><strong>No server.</strong> Browsers are
      <a href="https://libp2p.io">libp2p</a> peers: they meet through a
      circuit-relay-v2 node, discover each other via gossipsub, and upgrade to
      direct WebRTC. The room secret lives in the URL fragment (<code>#…</code>)
      and never leaves the browser.</li>
    <li><strong>Everything is end-to-end encrypted.</strong> Every peer pair is
      noise-encrypted end-to-end (even while frames still cross the relay), and
      room membership is proved with an AES-256-GCM sealed hello derived from
      the room secret — an undecryptable hello means you're not in the room.
      TURN with ephemeral credentials covers the stubborn NATs.</li>
    <li><strong>Hosting without an origin server.</strong> The client is a static
      Vite build served as plain files — there is no backend anywhere. This page
      you're reading works the same way.</li>
  </ul>

  <h2>What's in the repo</h2>
  <div class="card">
    <h3>client/src/app/ — the app</h3>
    <p>TODO: what your app code does. TypeScript, no framework: typed wire
    protocol plus the app's own logic and UI.</p>
  </div>
  <div class="card">
    <h3>client/src/net/ — the p2p layer</h3>
    <p>A thin js-libp2p assembly: relay bootstrap from
    <code>/.well-known/ap2p</code>, a room-scoped protocol with a sealed-hello
    membership handshake, reconnection, and the six-method surface the app
    consumes.</p>
  </div>
  <div class="card">
    <h3>deploy/ — the publish pipeline</h3>
    <p><code>publish-repo.sh</code> builds this very site: landing page + bare
    mirror exploded to loose objects (static file servers and git's dumb-HTTP protocol
    agree on "every path must exist"), with an anonymity gate that refuses to
    publish identity-bearing bytes.</p>
  </div>

  <h2>Run it yourself</h2>
  <pre><code>cd client && npm install && npm run dev   # :4173
# open two tabs on the same #room URL</code></pre>
  <p>Deploy: <code>npm run build</code>, then publish <code>client/dist/</code> as
  static files anywhere — IPFS, a CDN, a folder behind nginx. It needs nothing but
  a libp2p circuit relay it's allowed to talk to (see <code>src/app/config.ts</code>).</p>

  <h2>Guarantees &amp; limits, honestly</h2>
  <ul>
    <li>The relay operator sees connection metadata, opaque room ids, and frame
      sizes/timing. Not content, not names, not what was said.</li>
    <li>Anyone with the room link can join — capability model. Guard the link
      like you'd guard the room.</li>
    <li>TODO: any app-specific trust caveats (who referees, what a malicious
      member could do).</li>
    <li>MIT licensed. Built on WebRTC and WebCrypto.</li>
  </ul>

  <footer>
    Live: <a href="https://bursa.ardegazu.ro/">bursa.ardegazu.ro</a> ·
    this repo: <code>git clone https://git.ardegazu.ro/bursa.git</code> ·
    built on <a href="https://libp2p.io">js-libp2p</a>
  </footer>
</main>
</body>
</html>

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/bursa.git