git-trace

romele / git-trace public

62 commits · 1 branch · 1 tag · 1 contributor (top: Romele) · first commit 3d ago · last push 18m ago

doc/architecture.md

# Architecture

```
   browser / git client / MTA / sshd
                 |
                 v
          +-------------+        +--------+
          |  git-trace  |------->| SQLite |  users, ACLs, issues, MRs,
          |  (one proc, |        |  file  |  patch sets, mirrors,
          |   threads)  |        +--------+  webhooks, CI runs, audit
          +-------------+
            |    |     |
     fork+exec   |      \__ in-process, server-rendered HTML
            |    |           (no JS framework, no templates)
            v    v
        git http-backend    bare repos  repos/<owner>/<name>.git
        hooks (update,      filesystem-isolated, quota-checked
        post-receive)
```

Everything that is not a SQL row or an HTML string is delegated to
the system `git` — transport is `git http-backend`, policy is a
per-repo `update` hook, mirroring is `git fetch`/`git push`.

## Design principles

1. **Zero dependencies** — libc, SQLite3, pthreads; `git`/`tar`/`sh`
   as processes.  Nothing else links, nothing else runs.
2. **GNU-style workflows** — patch sets and email review are
   first-class, not an afterthought.
3. **No JavaScript** — the UI is HTML + a little inline CSS; Atom
   feeds come with an XSL so browsers render them.
4. **Readable machinery** — plain C11, one concern per file, parsers
   you can audit in an afternoon.
5. **Security first** — see `security.md`.

## Design decisions

- **Protocol**: we do not reimplement pkt-line negotiation. Requests are
  bridged to `git http-backend` (the CGI shipped with Git) via
  fork/exec with a scrubbed environment (`GIT_PROJECT_ROOT`, `PATH_INFO`,
  `QUERY_STRING`, `GIT_PROTOCOL`, `REMOTE_USER`, ...). We get Smart HTTP,
  dumb protocol and protocol v2 for free.
- **Concurrency**: one pthread per connection; git work happens in child
  processes with `RLIMIT_CPU`/`RLIMIT_NOFILE`/`RLIMIT_NPROC` ceilings.
- **Safety**: repo components are whitelisted (`[A-Za-z0-9][A-Za-z0-9._-]*`,
  `..` forbidden), resolved with `realpath()` and confined to the repos
  root; CGI path tails pass a per-segment whitelist; user refs/paths are
  never interpolated into shell commands (argv-only exec, leading `-`
  rejected). Unauthenticated requests to protected endpoints get a
  proper `401` challenge so git credential helpers work.

## Source layout

```
src/
  main.c    CLI (serve|mkrepo|useradd|passwd|mktoken) and routing
  httpd.c   HTTP/1.1 server: sockets, request parsing, thread-per-connection
  cgi.c     bridge to `git http-backend` (the protocol engine)
  auth.c    users, sessions, HTTP tokens, SSH keys, repo ACLs
  crypto.c  SHA-256, HMAC, PBKDF2, scrypt (RFC 7914), base64 —
            implemented from scratch; password formats are versioned
            (`scrypt$…` current, `pbkdf2$…` legacy) with transparent
            rehash-on-login; secret buffers wiped with gt_bzero()
  ssh.c     forced-command shell, authorized_keys generation
  gitx.c    subprocess helpers + ref/path argument validation
  repo.c    repo name policy and canonical-path confinement
  web.c     server-rendered pages (tree, blob, log, commit, refs, login)
  collab.c  issues, comments, merge requests, repo settings, CSRF
  patchset.c  GNU workflow: mbox parse, series preview, index-only apply
  wcommit.c browser commits: plumbing-only blob/tree/commit/CAS
  mirror.c  pull + push mirroring, trigger endpoint, validators
  ops.c     doctor / backup / restore
  ratelimit.c per-IP auth throttling (exponential backoff + ban)
  db.c      SQLite open + schema bootstrap + column migrations
  util.c    buffers, url/html codecs
tests/
  e2e.sh    full matrix harness: spins a fresh container, asserts the
            whole access/collab/security surface
  fuzz.sh   ASan/UBSan campaign (`make fuzz [iters]`)
  fuzzdrv.c unit-level fuzz driver linked against ASan objects
  fuzzrace.pl concurrent web-commit hammer (CAS verification)
  fuzznet.pl socket-level HTTP request fuzzer
sql/
  schema.sql  relational schema (embedded at build time)
hooks/
  update      per-ref policy hook installed into every repo (embedded)
deploy/       production bundle: systemd units, forge sshd conf,
              Caddy snippet, backup cron, one-shot install.sh
```