How nshekhawat/portcullis works
Portcullis is a rate-limiting service with a fast enforcement plane and a separate, asynchronous judgment plane that assigns policy tiers to suspected L7 abuse. Requests enter through its HTTP/gRPC API or reverse-proxy gateway, consume tokens against configured rules and state, and receive an allow/deny result. In parallel, observations feed periodic aggregation and detection; bounded judge calls inform guardrails, which control tier changes and audit decisions. The README documents admin controls, metrics, and multiple judge backends; unsampled implementation details are represented only where the tree supports a path.
Main entry points: controller.go Cycle controller · limiter.go Rate limiter · gateway.go Proxy gateway · judge.go Judge interface
Components 24
Request entry
- Proxy gateway
internal/gateway/gateway.go - HTTP API
internal/server/http.go - gRPC API
internal/server/grpc.go
Rate enforcement
- Rate limiter
internal/ratelimiter/limiter.go - Token bucket
internal/ratelimiter/tokenbucket.go - Rate rules
internal/config/config.go - Bucket storage
internal/storage/storage.go - Memory backend
internal/storage/memory.go - Redis backend
internal/storage/redis.go
Judgment plane
- Signal aggregation
internal/signals/aggregator.go - Suspect detection
internal/detect/detector.go - Cycle controller
internal/controller/controller.go - Judge interface
internal/judge/judge.go - Rules judge
internal/judge/rules/rules.go - TypeSafe judge
internal/judge/typesafe/client.go - OpenAI-compatible judge
internal/judge/openai/client.go - Tier guardrails
internal/policy/policy.go - Tier policy store
internal/policy/policy.go
Operations
- Admin API
internal/server/admin.go - Decision audit
internal/controller/audit.go - Metrics
internal/metrics/metrics.go
Other components
- API caller
- Protected upstream
- Judge endpoint
Connections 29
- API caller → HTTP API: checks via
- API caller → gRPC API: checks via
- API caller → Proxy gateway: sends traffic
- HTTP API → Rate limiter: checks limits
- gRPC API → Rate limiter: checks limits
- Proxy gateway → Rate limiter: checks limits
- Proxy gateway → Protected upstream: proxies allowed
- Rate limiter → Rate rules: uses rules
- Rate limiter → Token bucket: consumes tokens
- Token bucket → Bucket storage: reads/writes state
- Bucket storage → Memory backend: implemented by
- Bucket storage → Redis backend: implemented by
- Proxy gateway → Signal aggregation: observes traffic
- Signal aggregation → Cycle controller: provides signals
- Cycle controller → Suspect detection: selects suspects
- Cycle controller → Judge interface: requests verdicts
- Judge interface → Rules judge: can dispatch
- Judge interface → TypeSafe judge: can dispatch
- Judge interface → OpenAI-compatible judge: can dispatch
- TypeSafe judge → Judge endpoint: posts judgments
- OpenAI-compatible judge → Judge endpoint: posts judgments
- Cycle controller → Tier guardrails: constrains verdicts
- Cycle controller → Tier policy store: applies tier changes
- Cycle controller → Decision audit: records decisions
- Admin API → Tier policy store: manages tiers
- Admin API → Decision audit: reads decisions
- HTTP API → Metrics: records metrics
- gRPC API → Metrics: records metrics
- Cycle controller → Metrics: reports cycles