Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
ROSA Hyperfleet API — ROSA HCP regional cluster management.

Three components:

- **platform-api/** — Stateless REST gateway (SigV4 auth, Cedar/AVP authz, ZOA)
- **hyperfleet-operator/** — Kubernetes operator (Cluster, NodePool, Placement, ManagementCluster, Manifest CRDs)
- **hyperfleet-db/** — PostgreSQL-backed controller-runtime library
Expand All @@ -29,15 +30,32 @@ make test-operator-int # Operator integration tests (Postgres + DynamoDB)

make manifests # Generate CRDs (controller-gen)
make generate # Generate deepcopy

make codegen # Full codegen pipeline (openapi, passthrough, conversion)
make generate-clientset # Regenerate typed clientset from CRD types
make generate-openapi # Regenerate OpenAPI spec from CRD types

make verify-codegen # Verify codegen output is up to date
make verify-clientset # Verify clientset matches committed files
make verify-openapi # Verify OpenAPI spec is up to date

make test-unit # All unit tests (api, operator, codegen, clientset)
make test-integration # Integration tests (fleetdb, operator)
make test-api-codegen # Codegen tool tests
make test-clientset # Clientset tests
```

## Module Layout

```
hyperfleet-db/go.mod ← standalone
api/go.mod ← standalone (CRD types sub-module)
hyperfleet-operator/go.mod ← requires: fleetdb, api
platform-api/go.mod ← requires: fleetdb, api
hyperfleet-db/go.mod ← standalone
api/go.mod ← standalone (CRD types, v1alpha1)
clientset/go.mod ← generated typed K8s client for HyperFleet CRDs
hyperfleet-operator/go.mod ← requires: fleetdb, api
platform-api/go.mod ← requires: fleetdb, api
hack/api-codegen/go.mod ← codegen tools (openapi-gen, crd-variants, conversion-gen)
hack/clientset/cmd/wire-gen/go.mod ← wire generation for clientset
hack/tools/go.mod ← dev tooling dependencies
```

Cross-module refs use permanent `replace` directives to sibling dirs.
Expand All @@ -47,5 +65,5 @@ Cross-module refs use permanent `replace` directives to sibling dirs.
- Multi-module monorepo: separate go.mod per component
- Ginkgo/Gomega for testing
- OpenAPI-first API design
- CRD types owned by hyperfleet-operator, imported by platform-api
- CRD types in standalone `api/` module, imported by hyperfleet-operator and platform-api
- golangci-lint v2 with custom logcheck plugin
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

ROSA HCP regional cluster management — platform API, operator, and backing database library.

| Directory | Description |
| --- | --- |
| `platform-api/` | REST gateway (SigV4 auth, Cedar/AVP authz, ZOA) |
| Directory | Description |
| ---------------------- | ------------------------------------------------------- |
| `api/` | CRD types and API definitions (v1alpha1) |
| `platform-api/` | REST gateway (SigV4 auth, Cedar/AVP authz, ZOA) |
| `hyperfleet-operator/` | Kubernetes operator (Cluster, NodePool, Placement CRDs) |
| `hyperfleet-db/` | PostgreSQL-backed controller-runtime library |
| `test/` | E2E tests (API, CLI, monitoring, ZOA) |
| `hyperfleet-db/` | PostgreSQL-backed controller-runtime library |
| `clientset/` | Generated typed Kubernetes client for HyperFleet CRDs |
| `hack/` | Code generation tools and dev tooling |
| `test/` | E2E tests (API, CLI, monitoring, ZOA) |
Comment on lines +5 to +13

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the module layout consistent with the directory table.

The table lists clientset/ and hack/, but the ## Module Layout section still omits clientset/go.mod and the three hack modules documented in CLAUDE.md, Lines 51 through 58. Add those entries or state that the section intentionally excludes tooling modules.

Suggested module-layout update
 hyperfleet-db/go.mod             ← standalone
 api/go.mod                       ← standalone (CRD types)
+clientset/go.mod                 ← generated typed Kubernetes client
 hyperfleet-operator/go.mod       ← requires: hyperfleet-db, api
 platform-api/go.mod              ← requires: hyperfleet-db, api
+hack/api-codegen/go.mod          ← code-generation tools
+hack/clientset/cmd/wire-gen/go.mod ← clientset wire generation
+hack/tools/go.mod                ← development tooling
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 5 - 13, Update the README’s “Module Layout” section
to match the directory table by adding clientset/go.mod and all three hack
module entries documented in CLAUDE.md, or explicitly state that tooling modules
are intentionally excluded.


## Quick Start

Expand Down
62 changes: 32 additions & 30 deletions docs/api/rate-limit.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ Rate limits are configured via a YAML file mounted as a ConfigMap at `/etc/ratel
```yaml
enabled: true

redisTimeout: 20 # ms before fail-open on backend error
redisTimeout: 20 # ms before fail-open on backend error

exemptAccounts:
- "111111111111"
- "222222222222"

default:
rate: 100 # requests per window
burst: 200 # max burst (spike allowance)
window: 1 # window duration in seconds
rate: 100 # requests per window
burst: 200 # max burst (spike allowance)
window: 1 # window duration in seconds

routes:
- path: "/api/v0/clusters"
Expand All @@ -49,27 +49,27 @@ routes:

### Defaults (when omitted)

| Field | Default |
|----------------|----------------|
| `rate` | 100 |
| `burst` | `rate * 2` |
| `window` | 1 (second) |
| `redisTimeout` | 20 (ms) |
| Field | Default |
| -------------- | ---------- |
| `rate` | 100 |
| `burst` | `rate * 2` |
| `window` | 1 (second) |
| `redisTimeout` | 20 (ms) |

Route-level `burst` defaults to `rate * 2` and `window` inherits from `default.window` if not set.

### Environment variables

| Variable | Description |
|----------------------------|--------------------------------------------------|
| `RATE_LIMIT_ENABLED` | Set to `true` to enable rate limiting |
| `RATE_LIMIT_TEST_MODE` | Set to `true` for test mode (rate=3, burst=6, window=1s, in-memory) |
| `RATE_LIMIT_CONFIG_FILE` | Path to limits YAML (default `/etc/ratelimit/limits.yaml`) |
| `RATE_LIMIT_IN_MEMORY` | Set to `true` to use in-memory GCRA instead of Redis |
| `REDIS_ENDPOINT` | Valkey/Redis address (required when not in-memory) |
| `RATE_LIMIT_DEFAULT_RATE` | Override default rate |
| `RATE_LIMIT_DEFAULT_BURST` | Override default burst |
| `RATE_LIMIT_DEFAULT_WINDOW`| Override default window |
| Variable | Description |
| --------------------------- | ------------------------------------------------------------------- |
| `RATE_LIMIT_ENABLED` | Set to `true` to enable rate limiting |
| `RATE_LIMIT_TEST_MODE` | Set to `true` for test mode (rate=3, burst=6, window=1s, in-memory) |
| `RATE_LIMIT_CONFIG_FILE` | Path to limits YAML (default `/etc/ratelimit/limits.yaml`) |
| `RATE_LIMIT_IN_MEMORY` | Set to `true` to use in-memory GCRA instead of Redis |
| `REDIS_ENDPOINT` | Valkey/Redis address (required when not in-memory) |
| `RATE_LIMIT_DEFAULT_RATE` | Override default rate |
| `RATE_LIMIT_DEFAULT_BURST` | Override default burst |
| `RATE_LIMIT_DEFAULT_WINDOW` | Override default window |

When `RATE_LIMIT_CONFIG_FILE` is set, the YAML file is loaded and `RATE_LIMIT_DEFAULT_*` env vars are ignored. When no config file is set, `NewDefaultConfig()` is used with `RATE_LIMIT_DEFAULT_*` overrides applied.

Expand All @@ -78,7 +78,8 @@ When `RATE_LIMIT_CONFIG_FILE` is set, the YAML file is loaded and `RATE_LIMIT_DE
Run rate limiting locally without Redis/Valkey:

```bash
RATE_LIMIT_TEST_MODE=true go run ./cmd/rosa-regional-platform-api serve
cd platform-api
RATE_LIMIT_TEST_MODE=true go run ./cmd/... serve
```

Test mode uses an in-memory GCRA implementation. It explicitly sets `rate=3`, `burst=6`, `window=1s` — all three values are hardcoded, not derived from production defaults.
Expand All @@ -88,15 +89,15 @@ Test mode uses an in-memory GCRA implementation. It explicitly sets `rate=3`, `b
All rate-limited requests include:

| Header | Description |
|-------------------------|------------------------------------------|
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit` | Configured rate for the matched route |
| `X-RateLimit-Remaining` | Remaining requests in the current window |
| `X-RateLimit-Reset` | Seconds until the limit resets |

Denied requests (429) additionally include:

| Header | Description |
|---------------|--------------------------------------|
| Header | Description |
| ------------- | ---------------------------------------------- |
| `Retry-After` | Seconds until the next request will be allowed |

### 429 Response Body
Expand All @@ -117,11 +118,11 @@ Denied requests (429) additionally include:
ratelimit_requests_total{method, path, result}
```

| `result` label | Meaning |
|------------------------|-------------------------------------------------|
| `ok` | Request allowed |
| `over_limit` | Request denied (429) |
| `failure_mode_allowed` | Backend error, request allowed (fail-open) |
| `result` label | Meaning |
| ---------------------- | ------------------------------------------ |
| `ok` | Request allowed |
| `over_limit` | Request denied (429) |
| `failure_mode_allowed` | Backend error, request allowed (fail-open) |

The `path` label is the matched route pattern (e.g. `/api/v0/clusters`) or `"default"` for unmatched routes.

Expand All @@ -143,7 +144,7 @@ Every denied request logs at WARN level:
## Architecture

```
pkg/ratelimit/
platform-api/pkg/ratelimit/
config.go # Config struct, YAML loader, defaults
middleware.go # HTTP middleware, metrics, response writer
local.go # RateLimiter interface, Redis adapter, in-memory GCRA
Expand All @@ -158,6 +159,7 @@ The `RateLimiter` interface abstracts the backend:
## Running Tests

```bash
cd platform-api
go test -race -count=1 ./pkg/ratelimit/...
```

Expand Down
Loading