|
| 1 | +# AGENTS.md — Bungate |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +Bungate is a production-grade HTTP gateway and load balancer built on **Bun** runtime |
| 6 | +with **0http-bun** router and **fetch-gate** proxy. It provides TLS 1.3, JWT auth, |
| 7 | +8+ load balancing strategies, circuit breakers, clustering, and OWASP Top 10 security. |
| 8 | + |
| 9 | +- **Runtime:** Bun (NOT Node.js) |
| 10 | +- **Language:** TypeScript (strict mode, `bundler` module resolution) |
| 11 | +- **Package manager:** `bun` |
| 12 | +- **Test framework:** `bun:test` (`bun test`) |
| 13 | +- **Proxy engine:** `fetch-gate` |
| 14 | +- **Router:** `0http-bun` |
| 15 | + |
| 16 | +## Development Environment |
| 17 | + |
| 18 | +```bash |
| 19 | +# Run inside Docker — Dev |
| 20 | +docker exec -i projects-dev bash |
| 21 | +export PATH=$HOME/.bun/bin:$PATH |
| 22 | +cd /workspace/bungate |
| 23 | +``` |
| 24 | + |
| 25 | +## Build & Test Commands |
| 26 | + |
| 27 | +```bash |
| 28 | +# TypeScript type-check (no emit) |
| 29 | +bun run build # tsc --project tsconfig.build.json |
| 30 | + |
| 31 | +# Full test suite |
| 32 | +bun test # All 803 tests across 44 files |
| 33 | + |
| 34 | +# Specific test files |
| 35 | +bun test test/security/utils.test.ts |
| 36 | +bun test test/gateway/ |
| 37 | +bun test test/load-balancer/ |
| 38 | + |
| 39 | +# Coverage |
| 40 | +bun test --coverage # Currently 98.97% lines / 94.55% funcs |
| 41 | + |
| 42 | +# Format |
| 43 | +bun run format # Prettier |
| 44 | +bun run format:check # Prettier check-only |
| 45 | +``` |
| 46 | + |
| 47 | +## Project Structure |
| 48 | + |
| 49 | +``` |
| 50 | +src/ |
| 51 | +├── gateway/gateway.ts # Main BunGateway class (746 lines) |
| 52 | +├── proxy/gateway-proxy.ts # fetch-gate wrapper |
| 53 | +├── load-balancer/http-load-balancer.ts # 8+ strategies, health checks, sticky sessions |
| 54 | +├── cluster/cluster-manager.ts # Multi-process clustering |
| 55 | +├── logger/pino-logger.ts # Pino-based structured logging |
| 56 | +├── interfaces/ # TypeScript interfaces (no runtime code) |
| 57 | +│ ├── gateway.ts, middleware.ts, proxy.ts, route.ts, load-balancer.ts |
| 58 | +│ └── index.ts |
| 59 | +├── security/ |
| 60 | +│ ├── config.ts # Security config schema + validation + defaults |
| 61 | +│ ├── types.ts # ValidationResult, ValidationRules, SecurityContext |
| 62 | +│ ├── utils.ts # sanitizePath, recursiveDecodeURIComponent, entropy, etc. |
| 63 | +│ ├── input-validator.ts # Path/header/query validation against blocked patterns |
| 64 | +│ ├── validation-middleware.ts # Middleware wrapping InputValidator |
| 65 | +│ ├── error-handler.ts # SecureErrorHandler (production/development modes) |
| 66 | +│ ├── error-handler-middleware.ts # Middleware with circuit breaker detection |
| 67 | +│ ├── jwt-key-rotation.ts # JWKS refresh, multi-secret key rotation |
| 68 | +│ ├── jwt-key-rotation-middleware.ts |
| 69 | +│ ├── security-headers.ts # HSTS, CSP, X-Frame-Options, etc. |
| 70 | +│ ├── session-manager.ts # 128-bit entropy session management |
| 71 | +│ ├── size-limiter.ts # Request size validation |
| 72 | +│ ├── size-limiter-middleware.ts |
| 73 | +│ ├── tls-manager.ts # TLS certificate loading + validation |
| 74 | +│ ├── trusted-proxy.ts # Secure client IP extraction |
| 75 | +│ └── http-redirect.ts # HTTP→HTTPS redirect server |
| 76 | +└── index.ts # Public API exports |
| 77 | +``` |
| 78 | + |
| 79 | +## Security Design Principles |
| 80 | + |
| 81 | +### Path Validation (input-validator.ts + utils.ts) |
| 82 | + |
| 83 | +**Two-pass validation** against double-encoding attacks: |
| 84 | +1. **First pass:** Check raw path against `blockedPatterns` (catches null bytes, `../`) |
| 85 | +2. **Recursive decode:** `recursiveDecodeURIComponent()` decodes up to 5 layers until stable |
| 86 | +3. **Second pass:** Check fully-decoded path (catches `%252f` → `%2f` → `/`) |
| 87 | + |
| 88 | +Never validate before decoding — attackers hide behind encoding layers. |
| 89 | + |
| 90 | +### Health Checks (http-load-balancer.ts) |
| 91 | + |
| 92 | +Threshold-based to prevent flapping and cascade failures: |
| 93 | +- `failureThreshold` (default 3): consecutive failures before marking unhealthy |
| 94 | +- `successThreshold` (default 2): consecutive successes before marking healthy again |
| 95 | +- `minHealthyTargets` (default 1): floor check — refuses to mark the last healthy target down |
| 96 | + |
| 97 | +Floor exempts when ALL targets are already unhealthy (genuine outage, not a cascade to prevent). |
| 98 | + |
| 99 | +### Rate Limiting (gateway.ts) |
| 100 | + |
| 101 | +Uses gateway's `getClientIP()` as the rate limit key generator, NOT `X-Forwarded-For`. |
| 102 | +`getClientIP()` consults `TrustedProxyValidator` when enabled, otherwise falls back to |
| 103 | +secure header priority (`cf-connecting-ip` > `x-real-ip`). |
| 104 | + |
| 105 | +### Error Handling |
| 106 | + |
| 107 | +Global error handler registered on the 0http-bun router. In production: |
| 108 | +- Returns sanitized `{"error":"Internal server error"}` with status 500 |
| 109 | +- Never leaks stack traces or internal file paths |
| 110 | +- Logs full error details internally |
| 111 | + |
| 112 | +### Blocked Patterns (config.ts) |
| 113 | + |
| 114 | +```typescript |
| 115 | +blockedPatterns: [/\.\./, /%2e%2e/i, /%2f/i, /%5c/i, /%00/, /\0/, /%25%32%[fF]/i] |
| 116 | +``` |
| 117 | + |
| 118 | +Covers: raw `..`, encoded `../`, encoded `/`, encoded `\`, null byte, double-encoded `/`. |
| 119 | + |
| 120 | +## Testing Conventions |
| 121 | + |
| 122 | +- Use `bun:test` (`describe`, `test`, `expect`, `beforeAll`, `afterAll`) |
| 123 | +- Private method access: `(instance as any).privateMethod()` |
| 124 | +- Load balancer tests: use `LoadBalancerConfig` + `createLoadBalancer()` |
| 125 | +- Security tests: import from `../../src/security/<module>` |
| 126 | +- Session tests: use real TTLs (`await new Promise(r => setTimeout(r, N))`), not fake timers |
| 127 | +- Gateway E2E tests: start `Bun.serve()` echo servers, create `BunGateway`, call `listen()` + `close()` |
| 128 | + |
| 129 | +## Common Pitfalls |
| 130 | + |
| 131 | +1. **Don't validate before decoding.** Path validation must decode first, then validate. |
| 132 | + One-pass validation misses `%252f` (double-encoded) and `....//` (quad-dot). |
| 133 | + |
| 134 | +2. **JS bit-shift at 32 bits.** `1 << 32` equals `1` in JavaScript (only lower 5 bits used). |
| 135 | + The `isIPInCIDR` function special-cases prefix `0` for this reason. |
| 136 | + |
| 137 | +3. **Truthiness vs. null checks.** `config.sessions.ttl && config.sessions.ttl <= 0` short-circuits |
| 138 | + when `ttl` is `0` (falsy). Use `!= null` for numeric validation. |
| 139 | + |
| 140 | +4. **Always clean up.** Gateway tests must call `await gateway.close()` in `finally` blocks. |
| 141 | + Load balancer tests must call `manager.destroy()` / `loadBalancer.destroy()`. |
| 142 | + |
| 143 | +5. **Port conflicts.** E2E tests use specific ports (8100-8102 for echo servers, 3002+ for gateways). |
| 144 | + If a test hangs, check for stale Bun processes. |
| 145 | + |
| 146 | +6. **Don't modify node_modules.** Rate limiter and CORS live in `node_modules/0http-bun/lib/middleware/`. |
| 147 | + Fixes go in bungate source (e.g., custom `keyGenerator`), not in deps. |
| 148 | + |
| 149 | +7. **TypeScript strict mode.** Properties like `noUncheckedIndexedAccess` are on. Array accesses |
| 150 | + like `targets[0]` need explicit `!` assertions or length checks. |
| 151 | + |
| 152 | +## CI/CD |
| 153 | + |
| 154 | +- Pushes to `main` trigger GitHub Actions (see `.github/workflows/`) |
| 155 | +- `act` can run workflows locally: `bun run actions` |
| 156 | +- Release tags follow format `vYYYY.M.D` (e.g., `v1.0.1`) |
| 157 | +- Releases created via `gh release create` |
| 158 | + |
| 159 | +## Landing Page |
| 160 | + |
| 161 | +- Source: `docs/index.html` |
| 162 | +- Deployed to: `bungate.21no.de` (GitHub Pages) |
| 163 | +- Design system: `assets.21no.de` (CSS tokens, fonts, nav, hero, cards) |
| 164 | +- Colors: `#0a0a0b` background, `#38bdf8` accent |
| 165 | +- Fonts: `Outfit` (headings), `JetBrains Mono` (code) |
0 commit comments