Skip to content

Commit 0828be2

Browse files
author
molty3000
committed
docs: add AGENTS.md — build, test, security conventions, and pitfalls
1 parent ea343ba commit 0828be2

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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

Comments
 (0)