Changelog
- f801c19 Merge branch 'fix/audit-p0'
- 72a09ee Merge fix/audit-p1-node-om (audit P1-15: renew a due certificate while the console refuses heartbeats)
- 42d49fb Merge master (rules-v2) into the audit fixes
- f2c692c build(docker): node image on Debian with edgeweir-openresty
- d142f1f build(openresty): fail when libmodsecurity needs a newer libstdc++ than EL9's
- 9f09a0e build(openresty): one release number for both packages
- 397ec43 build(openresty): reproducible edgeweir-openresty packages
- fd19058 build(proto): consume proto/v0.2.0
- 9cfd1ec build(proto): consume proto/v0.2.1
- 9198cbd build(proto): consume proto/v0.2.2
- a89bfea build(proto): regenerate from proto/v0.13.0
- eb884d5 build(proto): regenerate from proto/v0.15.0
- 82c26e8 build(proto): regenerate from proto/v0.15.1 (comments only)
- 60ad3c5 build(proto): regenerate from proto/v0.16.0
- 083d8aa build(proto): regenerate from proto/v0.17.0
- a7f2c8d build(proto): regenerate from proto/v0.18.0
- f54d54a build(proto): regenerate from proto/v0.19.0
- 39a7fd5 build(release): release edgeweir-openresty next to edgeweir-node
- c72e281 build(release): systemd unit and image directory for probe mode
- a19f922 build: add goreleaser config
- b903c6e build: add make adr-check for the ADR mirror
- ed30e7e build: add node container image
- b649683 build: add systemd unit and deb/rpm maintainer scripts
- 0157a1f build: pin the Go toolchain patch release (go 1.27.1)
- 94df55f build: pin third-party images by digest and actions by commit SHA
- bd2a2b3 build: pin-check accepts the e2e node image variable
- df49792 build: ship nftables for kernel bans
- 59599f7 catchup
- 383fd22 chore(proto): regenerate from proto/v0.10.0
- 6da3403 chore(proto): regenerate from proto/v0.10.1
- 7c7471c chore(proto): regenerate from proto/v0.11.0
- 74c601a chore(proto): regenerate from proto/v0.12.0
- b1ddc6c chore(proto): regenerate from proto/v0.8.0
- c09e645 chore(proto): regenerate from proto/v0.9.0
- 9a62e16 ci(release): build edgeweir-openresty and the image natively per architecture
- 209a12d docs(adr): mirror the eighteen architecture decisions from edgeweir
- fb6f81b docs(adr): sync ADRs 0002, 0003, 0005, 0007, 0008 and 0011 from edgeweir
- 440473c docs(architecture): real apply order and the missing packages
- 341908e docs(architecture): record the P1-57 to P1-62 fixes
- 10a4d4b docs(claude): docs/adr is a generated mirror of the console's ADRs
- 557e3c7 docs(roadmap): prefix/full prefetch is v1, node self-check is done
- 1ec181b docs(security): no SSH install, purge.json loss, config/ modes, --allow-unsigned
- cd73dd1 feat(agent): accept domains the certificate does not cover yet
- 0469500 feat(agent): challenge keys, captcha pools and CC events
- a34b01b feat(agent): follow the console's ban channel
- 1887df3 feat(agent): host metrics in every heartbeat (metrics-v1)
- 8fdf6c2 feat(agent): layer-4 tables and statistics (l4-v1)
- bc46270 feat(agent): origin credentials, typed purge and prefetch tasks, origin health
- 9a8f089 feat(agent): prefetch device variants and https URLs
- 7750d10 feat(agent): probe the other nodes when the console asks
- dd94051 feat(agent): purge by Host and Cache-Tag
- 201e263 feat(agent): report brotli-v1, zstd-v1 and modsecurity-v1, CRS rule hits
- a14037e feat(agent): report log rule matches and announce rule-log-v1
- cf2212a feat(agent): report the statistics watermark after every acknowledged drain
- 6ff3c92 feat(agent): run active health checks, push their marks and report them
- f2d8ce6 feat(agent): run loop with watch, poll, apply, report and renewal
- 7b7673a feat(agent): send ban deltas against what the data plane holds
- bcd574d feat(agent): sitemap prefetch tasks
- ef496c7 feat(bans): group bans with the same key into one data plane entry
- a833cef feat(bans): keep the console's dynamic bans with their sequence
- e65b8c8 feat(captcha): draw image captchas with the standard library
- d89986d feat(cli): add enroll, run, healthcheck and version commands
- e30d8fd feat(cli): report the OpenResty version with the enrollment
- 58fcc61 feat(cli): take the enrollment token from EDGEWEIR_TOKEN or --token-file
- 6370c53 feat(cmd): --modsecurity-module and --crs-dir
- d07c2f4 feat(cmd): --purge-tags-per-site bounds a site's tag markers
- 71f8624 feat(cmd): --sites-dict-mb sizes the site table store
- 9137bfb feat(cmd): --tag-dict-mb sizes the Cache-Tag index
- f3484c0 feat(cmd): default --nginx-bin to edgeweir-openresty when it is installed
- 2ab65af feat(cmd): flags for the ban store and kernel bans
- 4265710 feat(cmd): flags for the challenge and CC stores
- 0c43444 feat(cmd): print the data plane's ban status
- 86e2ed5 feat(cmd): print the data plane's challenge and CC state
- 14fd0e1 feat(configir): announce purge-tag-v1 and prefetch-v2
- 1f23dce feat(configir): announce rules-v2
- 385a59c feat(configir): canonical order and diffs of the v0.12.0 fields
- ba87de9 feat(configir): canonical ordering, content hash, diff apply and validation
- 94cc131 feat(configir): canonical origin allow list and the v0.2.1 hash vector
- 3880b64 feat(configir): layer-4 applications (l4-v1)
- 2826d53 feat(configir): plan error pages, offline hosts, active health checks and session affinity
- 5678b63 feat(configir): plan origin pool settings, S3 auth, cache keys and rule conditions
- 89d402d feat(configir): validate Brotli, Zstandard and OWASP CRS settings
- 34bb2df feat(configir): validate challenges, CC policies, challenge keys and JA4 rules
- 53238a6 feat(configir): validate rules-v2 expressions, actions and site fields
- c696a20 feat(configstore): persist last-known-good config with backup
- c475ea1 feat(dataplane): G4 site table fields, tag markers, active health and request ids
- e49057f feat(dataplane): add unix-socket client for the Lua control API
- afb9500 feat(dataplane): client for the ban control endpoints
- 7efaf34 feat(dataplane): client for the challenge and security endpoints
- 3ddc218 feat(engine): detect Brotli and Zstandard, summarize CRS denials
- 281f55a feat(engine): test, reload and supervise OpenResty
- 93b42e8 feat(enroll): enroll nodes with a single-use token over a pinned channel
- b3cac27 feat(enroll): enroll probes through ProbeService
- 0747c92 feat(geoip): bundle IPinfo Lite at image build time
- 36aca2c feat(geoip): merge IPinfo Lite bundling
- 954d928 feat(healthcheck): active origin health checks
- 5393fd2 feat(lua): a statistics drain can take the current minute
- 450debf feat(lua): balancer-based origin layer, cache keys, purge markers and passive health
- a138425 feat(lua): challenge, CC and JA4 at the edge layer
- 8b24dc6 feat(lua): challenges and passes
- afbf8e5 feat(lua): compression negotiation and OWASP CRS at the edge layer
- 2c7aaa1 feat(lua): compute JA4 TLS client fingerprints
- aed215c feat(lua): count the matches of log rules per rule and minute
- ca76985 feat(lua): domains waiting for the certificate get no TLS or HTTPS redirect
- 263c89e feat(lua): error page templates and built-in pages
- ae0fa83 feat(lua): expression functions and value expressions
- 72b8dc4 feat(lua): health endpoint for regional probes (probe-health-v1)
- 815233c feat(lua): hold dynamic bans and enforce them at the edge layer
- 6d88eb8 feat(lua): layer-4 forwarding in the stream subsystem
- 524525e feat(lua): rules-v2 actions, bulk redirects, origin groups and rule-driven compression
- 5397173 feat(lua): session affinity cookies and active health marks
- ce8ccb5 feat(lua): sign S3 origin requests with AWS Signature V4
- c242933 feat(lua): signal-trace built-in pages, also for nginx's own errors
- 478e4dd feat(lua): tag purge markers and the Cache-Tag key-epoch index
- d1b95fb feat(lua): tiered CC mitigation decided on the node
- 3c98e6c feat(lua): two-layer OpenResty data plane with hot-updatable site table
- 21fc5ac feat(lua): wire Cache-Tag, error pages, offline hosts and affinity into both layers
- 8ff0a0a feat(nft): enforce platform bans in an nftables table of the agent
- fdc70bc feat(node): execute typed rules and serve local GeoIP data
- c0d02f8 feat(node): persist statistics batches and report bounded heavy hitters
- d7c91c5 feat(node): report bounded sampled access logs with durable retries
- 28c5535 feat(node): serve SNI TLS and recover configuration activation
- 15b83ef feat(node): verify signed upgrades and recover failed activations
- d64e801 feat(pki): add key/CSR generation, CA pinning and atomic file writes
- 5ff262d feat(probe): edgeweir-node probe
- 102f45e feat(probe): probe targets over TCP, HTTP and HTTPS
- 1d2d811 feat(proto): generate go code from edgeweir proto/v0.1.0
- 47f18b2 feat(proto): regenerate from proto/v0.14.0
- 6ac625e feat(proto): regenerate the node channel from edgeweir proto v0.2.0
- 586859c feat(render): Brotli, Zstandard and CRS locations in nginx.conf
- 492b4c5 feat(render): Cache-Tag index store, request ids and hidden internal headers
- 287264d feat(render): declare the ban store and its capacity
- ad4c31e feat(render): declare the challenge and CC stores
- 3721656 feat(render): origin layers with and without TLS verification, balancer upstream and slice maps
- 75646ec feat(render): raise nginx worker open-file limit to the hard limit
- 3254a18 feat(render): render nginx.conf from a Go template with golden tests
- 341fa6f feat(render): stream {} for layer-4 applications
- b666588 feat(retry): one retry schedule with a give-up condition
- 63a4ac7 feat: refuse special-purpose origin addresses and detect loops (CDN-Loop)
- 18879b3 feat: report error codes for origin health and task results
- 22b524d fix(agent): a purge of a host pattern fails instead of doing nothing
- ab87ffb fix(agent): a running agent never keeps or mixes a replaced identity
- 19d5ffa fix(agent): a table that does not fit is not pushed again and again
- f48dd15 fix(agent): an apply has its own time budget and never waits for OCSP
- 65f8f03 fix(agent): an expired client certificate is named in the logs
- e10f2b0 fix(agent): bounded purge markers that never take the sites down
- 60cd5c6 fix(agent): delete own bans the console lifted
- f05739d fix(agent): include node_id in the mTLS switch log message
- 1237f57 fix(agent): jitter the GetConfig and task poll intervals
- 606a21f fix(agent): leave bans alone when a snapshot changes nothing
- a6537d4 fix(agent): never replace an apply's challenge keys with an older set
- 0fe0f6d fix(agent): nginx workers of another user can reach sockets and temp files
- f70a33e fix(agent): prefetches go through local listeners that skip protection
- 7415d2c fix(agent): purges have a lane of their own
- 8049edc fix(agent): read the mTLS channel safely from loops that start before enrollment
- a7b3a07 fix(agent): receipts.json is written only when it changes
- 52c861e fix(agent): renew a due certificate while the console refuses heartbeats
- df26fef fix(agent): replace a stale site-level purge fallback at once
- 0a32d02 fix(agent): report sites at normal whose paths are escalated
- f95312b fix(agent): run purges before prefetches and bound prefetch time
- 39d7e44 fix(agent): statistics survive console outages and restarts
- 9dda5c3 fix(agent): the supervisor hears the node's health between heartbeats
- ec1c91e fix(agent): verify that a reload actually loaded the new nginx.conf
- ed8c0bb fix(build): pass signature paths to cosign without shell positionals
- 492b183 fix(captcha): keep characters legible with less rotation and shear
- fd4eff2 fix(cc): clear a site's CC state when its policy goes away
- 3b363a1 fix(ci): pin an available cosign installer revision
- 907b3d8 fix(config): reject unknown enum semantics before activation
- 1827ec9 fix(configir): reject site, origin and rule ids outside [A-Za-z0-9_-]
- dcf9bce fix(configir): reserve every shared dict name for cache zones
- 6c3a4b8 fix(configir): validate regex patterns with the console's allow-list
- 747d4bf fix(geoip): keep capability names compatible and harden the IPinfo build
- 26e0f8a fix(lua): CC counts and bans IPv6 clients by their /64
- e634811 fix(lua): URL purges match their query in any percent-encoding
- 05fb616 fix(lua): WebSocket connections are not closed after a minute idle
- 3a94136 fix(lua): answer the health endpoint with a fixed length
- 63b7583 fix(lua): cache keys read cookies as origins do
- 2485aaf fix(lua): challenge pages show the response's request id
- 1bde1d8 fix(lua): keep an origin unhealthy until a request succeeds
- e2f8fa9 fix(lua): keep unknown hosts in a separate small cache
- 48f089d fix(lua): layer-4 balancer errors and relay shutdown order
- 55c1b44 fix(lua): leave Accept-Encoding of slice subrequests alone
- 5eaf186 fix(lua): let requests pass when a rate-limit partition is full
- 01d0f77 fix(lua): never forward the client's x-amz-* headers to S3 origins
- 731f950 fix(lua): plain-text 403 for requests without a pass that cannot be challenged
- 71f32c7 fix(lua): requests with Authorization bypass the cache (RFC 9111 3.5)
- 58ce54f fix(lua): serve stale copies when the origin layer itself fails
- db7b1d2 fix(lua): the origin's own HTTP-01 challenges reach the origin
- f317dbd fix(lua): unambiguous cache keys over all headers and the normalized path
- df72e99 fix(lua): use backup origins only when every primary is down
- 93cef01 fix(node): avoid TLS prefetch listeners and correct release target
- 2ffac08 fix(node): back off after configuration persistence failures
- 672595a fix(node): invalid local settings stop the node instead of a restart loop
- ed33366 fix(node): isolate rate counters and respect public HTTP3 ports
- de37bed fix(openresty): run the CRS phase 2 rules when the request body is not inspected
- d7b3abd fix(openresty): run workers as nobody:nogroup on Debian and Ubuntu
- a404173 fix(packaging): keep the enrollment token off command lines in the hints
- c22aa71 fix(render): the edge never retries the origin layer on a reused connection
- bdc7888 fix(render): verify origin certificates against the origin's own name
- 5059527 fix(upgrade): OpenResty outlives agent upgrades, and downgrades are refused
- 6253133 fix: use the PROXY protocol client address and keep prefetches off such listeners
- e92f21d perf(lua): read offline hosts from the version the host lookup used
- 9cf88d7 perf(lua): read the client address only when a ban could apply
- a8ce3a4 perf(lua): skip rules-v2 work for sites that do not use it
- 0104a76 refactor(agent): data plane writes share one retry helper
- 055dc05 refactor(agent): statistics and access logs share one disk spool
- a64eb0b refactor: offline hosts are disabled sites only (proto v0.20.0)
- 2333e69 style(configir): gofmt the shared vector test
- c0c4b02 test(agent): older revisions, rejected revisions and unknown task types
- 22f7141 test(agent): queue the watermark test's bucket before the agent starts
- 6813f75 test(agent): wait for both active probes before advancing the clock
- afd9cbb test(configir): content hash vector for proto v0.11.0
- 4e5d318 test(configir): proto v0.13.0 content hash vector
- 45138da test(configir): proto v0.15.0 content hash vector
- c190fb9 test(e2e): Brotli, Zstandard and OWASP CRS in the smoke test
- 5551915 test(e2e): Cache-Tag, tag purges, request ids, error pages and affinity
- b021d04 test(e2e): Under Attack, js and pow challenges and CC in the smoke test
- 667ae58 test(e2e): add container smoke test with a fake console
- 4583da5 test(e2e): allow longer wait for per-minute stats upload
- de97ded test(e2e): ban and unban clients in the container smoke test
- 99735e0 test(e2e): captcha page and its accessible proof of work
- 4e947e8 test(e2e): check header stripping behind 150 headers, avoid port clashes
- 509488e test(e2e): health endpoint, health certificate, probes and host metrics
- 1bcc2e8 test(e2e): layer-4 applications
- 44868be test(e2e): rules-v2 redirects, origin rules, config overrides and compression rules
- ad215e0 test(e2e): smoke checks for the P1-58, P1-62 and supervisor fixes
- b49a33b test(e2e): tag and host purge tasks, sitemap prefetch and active health checks
- 174e8b8 test(fakeconsole): serve GetBans and ReportBans
- 0cfd161 test(fakeconsole): serve GetChallengeKeys and ReportSecurityEvents
- c1405e6 test(healthcheck): state the threshold steps directly
- 67e36bc test(node): distinguish site admission from hot updates
Verify
cosign verify-blob \
--bundle checksums.txt.sigstore.json \
--certificate-identity-regexp '^https://github\.com/marvinli001/edgeweir-node/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
sha256sum --ignore-missing -c checksums.txt
gh attestation verify <artifact> --repo marvinli001/edgeweir-node