Repository navigation
Expand file tree
/
Copy pathCargo.toml
More file actions
230 lines (191 loc) · 8.64 KB
/
Copy pathCargo.toml
File metadata and controls
230 lines (191 loc) · 8.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
[workspace]
resolver = "2"
members = [
"crates/db",
"crates/storage",
"crates/cache",
"crates/core",
"crates/crypto",
"crates/telemetry",
"crates/traffic",
"crates/format-api",
"crates/server",
"crates/e2e",
"crates/formats/apt",
"crates/formats/docker",
"crates/formats/nuget",
"crates/formats/npm",
"crates/formats/raw",
"xtask",
]
# One version for the whole product: every crate inherits it, so a release
# bumps it here once (and `web/package.json` to match).
[workspace.package]
version = "2.1.0"
edition = "2021"
rust-version = "1.99"
# MIT (see LICENSE and README → License).
license = "MIT"
publish = false
[workspace.dependencies]
# Async runtime
tokio = { version = "1.45", features = ["rt-multi-thread", "macros", "fs", "io-util"] }
# Stream <-> AsyncRead bridge (multipart upload field -> CAS)
tokio-util = { version = "0.7", features = ["io"] }
# HTTP framework
axum = { version = "0.8" }
# Static file serving (SPA assets + index.html fallback)
tower-http = { version = "0.7", features = ["fs", "trace", "set-header", "timeout"] }
# Database
sqlx = { version = "0.9", features = [
"runtime-tokio",
"postgres",
"macros",
"chrono",
"uuid",
] }
# UUIDs (retention run grouping)
uuid = { version = "1", features = ["v4", "serde"] }
# S3. `default-features = false` drops the SDK's `rustls` feature, which only
# compiles in the legacy hyper 0.14 / rustls 0.21 / h2 0.3 connector (never
# used: the default HTTPS client is hyper 1 / rustls 0.23) and with it
# RUSTSEC-2026-0258 (h2 0.3) and RUSTSEC-2026-0098/0099/0104 (rustls-webpki
# 0.101). The list below is the SDK's default set minus `rustls` and
# `sigv4a`: SigV4a signs only requests to AWS Multi-Region Access Points,
# which Forge neither documents nor tests, and compiles in crypto-bigint 0.5
# (RUSTSEC-2026-0387, no fixed 0.5 release, and aws-sigv4 1.6 needs 0.5).
aws-sdk-s3 = { version = "1.85", default-features = false, features = [
"http-1x",
"default-https-client",
"rt-tokio",
] }
aws-config = { version = "1.8" }
# Short-lived S3 credentials (`s3.credentials = "web_identity"`): STS
# AssumeRoleWithWebIdentity against AWS or an S3-compatible STS endpoint.
# `default-features = false` for the same reason as `aws-sdk-s3` above (the
# SDK's `rustls` feature is the legacy connector); the call is unsigned, so
# no `sigv4a` either.
aws-sdk-sts = { version = "1.114", default-features = false, features = [
"default-https-client",
"rt-tokio",
] }
aws-credential-types = { version = "1.2" }
# HTTP client
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json", "stream", "form", "system-proxy"] }
# Outgoing email (Admin → Settings → Email): SMTP submission over rustls,
# verified against the system roots like reqwest (the platform verifier),
# with the workspace's aws-lc-rs provider.
lettre = { version = "0.11", default-features = false, features = [
"smtp-transport",
"builder",
"hostname",
"tokio1-rustls",
"rustls-platform-verifier",
"aws-lc-rs",
] }
# In-memory cache
moka = { version = "0.12", features = ["future"] }
# Glob matching for RBAC content selectors: compile a GlobSet once per
# selector and match lowercased package names. Audited, standard choice.
globset = { version = "0.4" }
# Redis (optional)
# `tokio-rustls-comp`: `rediss://` URLs (TLS, verified against the system
# trust store).
redis = { version = "1", features = ["tokio-comp", "tokio-rustls-comp", "connection-manager"] }
# Futures combinators (Stream adapters for redis pub/sub)
futures-util = { version = "0.3", default-features = false, features = ["std"] }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
# Error handling
anyhow = { version = "1" }
thiserror = { version = "2" }
# Tracing / logging
tracing = { version = "0.1" }
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
# OpenTelemetry: metrics, traces and logs, exported over OTLP. Every crate
# records through the API (forge-telemetry); only forge-server sets up the
# SDK, the OTLP/HTTP exporter and the bridges from `tracing`. The SDK's
# `internal-logs` reports export failures in Forge's log.
opentelemetry = { version = "0.33", default-features = false, features = ["metrics", "trace", "logs", "internal-logs"] }
opentelemetry_sdk = { version = "0.33", default-features = false, features = ["metrics", "trace", "logs", "internal-logs"] }
opentelemetry-otlp = { version = "0.33", default-features = false, features = ["http-proto", "reqwest-blocking-client", "metrics", "trace", "logs", "internal-logs", "gzip-http"] }
tracing-opentelemetry = { version = "0.34", default-features = false }
opentelemetry-appender-tracing = { version = "0.33", default-features = false }
# Hashing
sha2 = { version = "0.11" }
# Keyed hashing (validated-credential cache key: HMAC-SHA256 with a server pepper)
hmac = { version = "0.13" }
# Hex encoding (token hashes)
hex = { version = "0.4" }
# Password hashing (PHC argon2 verification)
argon2 = { version = "0.6" }
# Constant-time comparison
subtle = { version = "2.6" }
# AEAD ciphers for secret encryption at rest. AES-256-GCM is the default
# (hardware-accelerated, KMS-friendly); XChaCha20-Poly1305 is the opt-in
# alternative whose 192-bit extended nonce makes pure-random nonces
# collision-safe without any per-key counter state. `zeroize` scrubs the
# expanded key schedule (AES round keys, GHASH/ChaCha state) when a cipher
# instance is dropped; without it only our own key buffers would be wiped.
aes-gcm = { version = "0.11", features = ["zeroize"] }
chacha20poly1305 = { version = "0.11", features = ["zeroize"] }
# Scrub unwrapped key bytes / transient plaintext from memory on drop.
zeroize = { version = "1.8" }
# Secret wrappers that redact Debug/Display and zeroize on drop: the
# plaintext-secret type handed to callers so it can never leak into logs.
secrecy = { version = "0.10" }
# CSPRNG for token secrets
rand = { version = "0.10" }
# CIDR / IP network parsing (trusted proxies, SSRF guard)
ipnet = { version = "2.10" }
# URL parsing (SSRF guard)
url = { version = "2.5" }
# HTTP types (HeaderMap for principal sources)
http = { version = "1" }
# async fn in dyn traits (PrincipalSource, SSRF resolver)
async-trait = { version = "0.1" }
# Base64 (RFC 4648 standard alphabet)
base64 = { version = "0.23" }
# JWT decode/verify (OIDC ID-token signature + claim validation).
# We use `jsonwebtoken` (not the heavier `openidconnect`): it gives explicit
# control over the signing-key (RSA n/e from JWKS), the algorithm allowlist
# (reject `alg: none`/HMAC), and the iss/aud/exp leeway — and it slots cleanly
# behind our own outbound metadata client (`outbound_metadata_client`) +
# `forge-cache` rather than bringing its own HTTP-client abstraction.
jsonwebtoken = { version = "11", default-features = false, features = ["use_pem", "aws_lc_rs"] }
# RSA key generation and signing for the client assertions forge issues
# itself (forge_core::oidc::assertion): the crypto backend `jsonwebtoken`
# already links, used directly where `jsonwebtoken` has no key generation.
aws-lc-rs = { version = "1.18" }
# Traffic statistics (crates/traffic): Parquet files in the object store.
# Without the Arrow layer (its record API suffices) and with Snappy alone, a
# pure-Rust codec.
parquet = { version = "60", default-features = false, features = ["snap"] }
parquet_derive = { version = "60" }
# Country and ASN lookups in MaxMind databases (crates/traffic).
maxminddb = { version = "0.32" }
# Temp files
tempfile = { version = "3" }
# Date/time (shared with forge-db's model types)
chrono = { version = "0.4", default-features = false, features = ["clock"] }
# Retention schedules (`schedule` + `schedule_timezone` in a retention
# policy): croner parses 5-field cron patterns and finds their next time in a
# chrono time zone, with Vixie-cron/OCPS rules across daylight-saving
# changes (a time in a skipped hour runs right after it, a time in a repeated
# hour once); chrono-tz is the IANA time-zone database compiled in, so a zone
# resolves the same in a container image without /usr/share/zoneinfo.
croner = { version = "4.0.1", default-features = false, features = ["chrono"] }
chrono-tz = { version = "0.10" }
# Tests build unoptimized, yet the mock IdPs generate RSA keys and every test
# server hashes its bootstrap admin password: ~30x (RSA-2048 keygen, ~3 s) and
# ~15x (Argon2 default, ~0.3 s) slower than optimized. Optimize just those
# dependencies; the workspace crates stay fast to build and debug.
[profile.dev.package.rsa]
opt-level = 3
[profile.dev.package.num-bigint-dig]
opt-level = 3
[profile.dev.package.argon2]
opt-level = 3
[profile.dev.package.blake2]
opt-level = 3