Skip to content

Commit cc5acd6

Browse files
committed
Whole-repo hardening round: streaming, content policy, realtime billing, modernization
Fixes from a full-source review: - streaming responses outlived the per-account timeout: reqwest's request timeout is a total deadline, so any generation longer than timeout_seconds (default 60s) was cut mid-stream and billed as aborted; streams now get the bound on response headers and then per gap between chunks - REST responses never masked secrets (detect_secrets applied inbound and on the realtime relay only), and a secrets-only tenant streamed raw deltas; outbound masking and the stream-buffering boundary now share one predicate - the blocklist scanned base64 image parts, randomly blocking multimodal requests; the scan now visits the same text fields DLP does - a second realtime response.create during an active turn desynced the admitted-turn queue for the rest of the session (misattributed billing plus a stuck reservation); the bridge holds at most one admitted turn - content-blocked requests on the responses/embeddings/images/audio surfaces answered 500 instead of a graceful 400 - vendor error bodies without an error envelope (Bedrock, DashScope native) parsed as empty successes on 4xx/5xx statuses - claude engine joined system texts without a separator - MemoryStore's ledger prune wedged behind an out-of-order young row - config generation hashed with DefaultHasher (not stable across rustc), so a mixed-build fleet would miss the shared cache; sha256 now, builder pinned - Redis QPS used ceil() where the in-process limiter rounds; negative quotas/qps/qpm are rejected at config load; the in-process failure streak decays after an hour idle like the Redis backend's TTL Modernization and hygiene: rust-version 1.88 (let-chains were already in use), resolver 3, unmaintained serde_yaml replaced by serde-saphyr, yanked spin bumped, account slots shared via Arc instead of cloned per request, the one-caller response-transform DSL replaced by a direct conversion, SSE decoder and buffered drains bounded against unbounded peers, OpenAI/Anthropic usage now carry cache/reasoning detail on the wire, docs re-synced to the code, and regression tests pin every fix above plus an e2e erasure round trip. Verified: 329 tests green on macOS and on Linux (rust:1.94, live PG/Redis); bench A/B on bare metal: small-chat p50 and request-clone unchanged, concurrent throughput up ~3%, big-payload p50 +14% traced to x86 codegen drift (bisect halves it with no per-byte change present; arm64 shows parity).
1 parent dd0b04d commit cc5acd6

57 files changed

Lines changed: 1617 additions & 1018 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 99 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Gateway — LLM access point. Workspace manifest.
22
[workspace]
3-
resolver = "2"
3+
resolver = "3"
44
members = [
55
"crates/consts",
66
"crates/models",
@@ -20,7 +20,7 @@ version = "0.1.0"
2020
edition = "2024"
2121
license = "AGPL-3.0-only"
2222
repository = "https://github.com/cocoonstack/gateway"
23-
rust-version = "1.85"
23+
rust-version = "1.88"
2424
publish = false
2525

2626
[workspace.lints.clippy]
@@ -43,7 +43,7 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"
4343
# --- serde ---
4444
serde = { version = "1", features = ["derive"] }
4545
serde_json = "1"
46-
serde_yaml = "0.9"
46+
serde-saphyr = "0.0.29" # serde_yaml is unmaintained (archived 2024)
4747
# --- errors ---
4848
thiserror = "2"
4949
anyhow = "1"

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
FROM rust:1 AS builder
1+
# Pinned: successive image builds must embed the same toolchain, not whatever
2+
# `rust:1` floats to on the day of the build.
3+
FROM rust:1.94 AS builder
24
WORKDIR /app
35
COPY . .
46
RUN cargo build --release -p gw-server --locked

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ docker run -p 8080:8080 -v $PWD/conf/gateway.yaml:/etc/gateway.yaml \
5454
```
5555

5656
The image binds `0.0.0.0` (`GW_HOST`) and ships a `/health` HEALTHCHECK.
57-
Published multi-arch to `ghcr.io/cocoonstack/gateway` on push.
57+
Published multi-arch to `ghcr.io/cocoonstack/gateway` on `v*` tags.
5858

5959
## Development
6060

@@ -64,12 +64,13 @@ make test # cargo test --workspace
6464
make lint # clippy -D warnings
6565
make fmt # cargo fmt --all
6666
make deny # cargo deny check (advisories + licenses)
67-
make release # optimized gw-server binary (--locked)
67+
make release # optimized `gw` binary (--locked)
6868
make docker # build the container image
6969
```
7070

71-
CI runs fmt/clippy/test + `cargo deny` on every push; tagged `v*` pushes
72-
build multi-arch binaries (release) and a multi-arch image (docker).
71+
CI runs fmt/clippy/test + `cargo deny` on every push to `main` and every PR;
72+
tagged `v*` pushes build multi-arch binaries (release) and a multi-arch image
73+
(docker).
7374

7475
## License
7576

crates/config/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ description = "Local file configuration — no config center."
99
[dependencies]
1010
gw-consts = { workspace = true }
1111
serde = { workspace = true }
12-
serde_yaml = { workspace = true }
12+
serde-saphyr = { workspace = true }
13+
sha2 = { workspace = true }
1314
thiserror = { workspace = true }
1415
regex = { workspace = true }
1516
tracing = { workspace = true }

0 commit comments

Comments
 (0)