2026-07-21 - 2026-10-21
Overview
3 Releases published by 1 user
Published
v1.0.0-rc3
Published
v1.0.0-rc2
Published
v1.0.0-rc1
243 Pull requests merged by 2 users
Merged
#557 Run the tests with cgo off and without the race detector (closes #538)
Merged
#555 Store events and create deliveries in the delivery engine (closes #544)
Merged
#554 Store a target's settings as columns (closes #543)
Merged
#553 Use one recovery routine at start and on every sweep tick (closes #542)
Merged
#552 Move the archive files into their own package (closes #541)
Merged
#546 Store a webhook's retention as a plain day count, 0 meaning forever (closes #539)
Merged
#547 Store a target's number of delivery attempts, at least one
Merged
#551 Say the query logger drops bound values
Merged
#549 Send only the Referer's scheme and host to Sentry
Merged
#550 Build the binary without cgo
Merged
#537 Drop unsafe-inline from the Content-Security-Policy
Merged
#536 Bind 0.0.0.0 to IPv4 only
Merged
#534 Keep the entrypoint UUID out of webhooker's own logs
Merged
#532 Leave a delivery cut off by a stop for the next start
Merged
#380 Milestone: next into main
Merged
#533 Store delivery and archive times without the monotonic clock reading
Merged
#526 Build the image's static binary with netgo, osusergo and sqlite_omit_load_extension (closes #525)
Merged
#524 Describe code in its own terms, not by an earlier build's data (closes #522)
Merged
#523 Escape the database path in the SQLite connection string (closes #518)
Merged
#521 Remove upgrade and older-build text from the README (closes #520)
Merged
#517 Drop Completed Steps from TODO.md; the tracker is the record (closes #112)
Merged
#519 Build every database's schema from embedded SQL files (closes #56)
Merged
#516 Name Sentry transactions after the route they matched (closes #185)
Merged
#515 Make the HSTS max-age configurable with HSTS_MAX_AGE (closes #271)
Merged
#514 Document that DATA_DIR must be on a local filesystem (closes #295)
Merged
#512 Keep test helpers out of the shipped binary (closes #506)
Merged
#513 Read the export test's heap only after pools drop their caches (closes #511)
Merged
#510 Make the load-sensitive tests wait for what they check (closes #507)
Merged
#509 Refresh the package lists before installing in script/bootstrap (closes #508)
Merged
#505 Re-vendor the shared files from sneak/prompts at dd4027b (closes #504)
Merged
#502 Mask a target URL's query string when the URL has no path (closes #500)
Merged
#501 Store and show an event's query string, and pass it on to an HTTP target when set (closes #312)
Merged
#498 Merge main into next after 416 (closes #497)
Merged
#416 main side of 414: cheaper test hashing, and failing tests visible in the build log (closes #414)
Merged
#496 Install ESLint and prettier with yarn 4 through corepack (closes #493)
Merged
#495 Break long values on the webhook page and event log at phone width (closes #391)
Merged
#492 Format the Markdown with prettier in make fmt and make fmt-check (closes #215)
Merged
#494 Split source_management.go along its CRUD seams (closes #274)
Merged
#490 Event log: show only the events with a failed or a pending delivery (closes #390)
Merged
#489 Show an event's entrypoint and request headers in the event log and on its page (closes #389)
Merged
#491 Use one name for each thing the UI shows (closes #399)
Merged
#486 Lint static/js/ with ESLint in Docker (closes #120)
Merged
#482 Rotate a database target's archive monthly, daily or hourly (closes #379)
Merged
#487 Event log: show attempt and delivery times, label replays, zone event times (closes #386)
Merged
#488 Event log: only the newest event expanded, and only the 50 most recent (closes #349)
Merged
#485 Name the item and what is lost in each delete prompt (closes #400)
Merged
#484 Say what a database or log target's attempt did, without a status (closes #388)
Merged
#471 Event log: an event's ID can be selected without toggling it (closes #348)
Merged
#483 Offer no Replay for a delivery to a deleted target (closes #387)
Merged
#478 Show a target paused by its circuit breaker (closes #385)
Merged
#481 Remove an http target's max_queue_size (closes #477)
Merged
#480 Show each page's own title in the browser tab (closes #117)
Merged
#479 Offer archive expiry choices on the target forms, show plain units (closes #396)
Merged
#474 Keep what was typed when a target or webhook edit is refused (closes #381)
Merged
#473 Pin tailwindcss and check the committed stylesheet against it (closes #231)
Merged
#476 New-webhook page: optional HTTP target URL and archive with pruning (closes #373)
Merged
#475 Show a slack target's retry setting in the target list (closes #395)
Merged
#472 Show each target's delivered and failed deliveries in the target list (closes #372)
Merged
#470 Show each entrypoint's last event and event count on the webhook page (closes #393)
Merged
#463 Targets section: one Add, then a target type and Next, then that type's fields (closes #370)
Merged
#465 Give each event its own page and show bodies the same everywhere (closes #369)
Merged
#460 Report or refuse each unusable file webhooker reads (closes #290)
Merged
#464 Let an entrypoint's description be edited in place (closes #392)
Merged
#468 Index the event log's resubmit count with deleted_at (closes #325)
Merged
#469 Show a database target's archive file, size and last write in the target list (closes #397)
Merged
#467 Name each embedded static file so a missing Alpine.js fails the build (closes #166)
Merged
#439 Add a Download button that exports a database target's archive as gzipped JSON (closes #374)
Merged
#466 Route the delivery tests' gorm.Open through gormlog (closes #462)
Merged
#454 Clamp the HTTP drain by the tail-hook reserve (closes #170)
Merged
#458 Pin the HTTP target's unpinned error checks (closes #285)
Merged
#461 Name the reaper's hard delete in the event body comments (closes #455)
Merged
#457 Fix two resubmit comments and test the resubmit route's middleware (closes #252)
Merged
#456 Harden the (*gorm.DB).Scan guard test (closes #232)
Merged
#451 Try every event database file on delete and say which was left (closes #275)
Merged
#447 Make every clickable control look clickable, in two shared styles (closes #375)
Merged
#445 Pin the close before the reopen in the archive sweep (closes #103)
Merged
#453 Clear the environment in the cmd/webhooker tests that build a Config (closes #452)
Merged
#450 Assert the body a retry delivers, not only its status (closes #294)
Merged
#449 Pin the body cap's order in every page route group (closes #93)
Merged
#442 Check the log charge against every code point (closes #172)
Merged
#444 Isolate config tests from the shell; any out-of-range PORT is ErrInvalidPort (closes #94)
Merged
#443 Send fx's own events through the service's logger (closes #183)
Merged
#448 Pin the rate-limit key for an empty RemoteAddr (closes #168)
Merged
#446 Close the retention follow-ups from the August review (closes #99)
Merged
#440 Log the client address next to the peer address (closes #270)
Merged
#441 Seed the retention tests 50 rows per insert, not 500 (closes #198)
Merged
#411 Load Alpine's CSP build so the UI's directives run (closes #371)
Merged
#438 Drive the archive reopen debounce test from a clock (closes #190)
Merged
#433 Keep each model's parent out of its JSON (closes #177)
Merged
#436 Write a form-error page's status only after it renders (closes #128)
Merged
#435 Name the CI build step after what the image runs (closes #175)
Merged
#437 Toggle only a target's active state, so it cannot undo an edit (closes #431)
Merged
#434 Build the middleware test cookie stores with the production constructor (closes #154)
Merged
#432 Justify the handlers tests' start limit with a measurement (closes #225)
Merged
#417 Show each webhook's activity in the webhook list (closes #394)
Merged
#429 Say at the receiver route where its 1 MB body cap lives (closes #173)
Merged
#418 Name each database target's archive for its webhook and target (closes #376)
Merged
#430 Remove the no-op MAINTENANCE_MODE setting (closes #317)
Merged
#428 Let a handler flush or set a write deadline through the access log and metrics (closes #191)
Merged
#427 Serve the delivery duration histogram from boot (closes #267)
Merged
#409 Add a read-only Settings page for the loaded configuration (closes #402)
Merged
#425 Run script/test quietly with coverage, rerun failed tests verbosely (closes #315)
Merged
#422 Refuse [::], 0.0.0.0, IPv6 multicast and documentation space (closes #341)
Merged
#426 Discard fx's own log in tests that build an fx app (closes #230)
Merged
#420 Say what each action did in a one-line notice (closes #383)
Merged
#424 Drop TODO.md's stale docs-only cache caveat (closes #421)
Merged
#419 Widen the webhook page by half so an entrypoint URL fits on one line (closes #350)
Merged
#423 Send the build version in the outbound User-Agent (closes #313)
Merged
#346 Serve /metrics from a registry of its own (closes #227)
Merged
#410 Derive the image's version from the .git in the build context (closes #366)
Merged
#408 Render admin page errors in the normal layout (closes #382)
Merged
#407 Say how to allow a refused private target address (closes #398)
Merged
#406 Logging in returns to the page that was asked for (closes #384)
Merged
#403 Add a statistics pane to the webhook page (closes #368)
Merged
#378 Move webhook pages to /hook/ID and inbound URLs to /h/UUID (closes #367)
Merged
#415 Run the test suite without -v so a failure shows in the build log (closes #414)
Merged
#404 Keep make test under 2 GB of memory (closes #344)
Merged
#413 Reword the build-architecture history line in TODO.md (closes #412)
Merged
#336 Trust the RFC 1918 ranges as proxies when TRUSTED_PROXIES is unset (closes #333)
Merged
#339 State what the default blocklist covers (closes #244)
Merged
#361 Show 50 recent events with size, processing time and status (closes #347)
Merged
#405 Remove the fixed Account Type row from the profile page (closes #401)
Merged
#351 Commit the Alpine.js tarball in 3p/ and extract it at build time (closes #345)
Merged
#338 Bound username length at creation (closes #184)
Merged
#365 deploy
Merged
#364 Next
Merged
#353 Container sets its data directory's owner and mode itself
Merged
#362 Let a browser with cookies from an earlier database log in (closes #359)
Merged
#360 Fast-forward next to main
Merged
#357 deployment to prod
Merged
#356 Sneak/testdeploy
Merged
#355 deployment
Merged
#342 Milestone: next into main
Merged
#343 Deploy: main into prod
Merged
#335 Restrict /s/* to GET and HEAD (closes #169)
Merged
#321 1.0.0 milestone: next into main
Merged
#337 Drop Set-Cookie from the recovered 500 (closes #193)
Merged
#334 Default-block Azure WireServer's public address (closes #245)
Merged
#332 Close archive writers when the delivery engine stops (closes #280)
Merged
#331 Send Content-Type once on a delivery
Merged
#329 Fail a pending delivery whose target was deleted (closes #293)
Merged
#330 Make deliveries refused while half-open wait a cooldown (closes #306)
Merged
#327 Open each event database once when callers race
Merged
#326 Say make check needs make bootstrap on a fresh clone
Merged
#328 Do not resend a delivery that restart recovery already sent
Merged
#319 Index the event-tier columns the sweeps, event log and retention scan
Merged
#322 Default WEBHOOKER_ENVIRONMENT to prod (closes #307)
Merged
#324 Document running webhooker under upaas (closes #323)
Merged
#320 Say max_retries is the total attempt count, not a retry count
Merged
#318 Consolidate the data directory mode into one owner
Merged
#302 State the UUID-is-the-credential rule as a rule (closes #301)
Merged
#111 Milestone 1.0.0: internet-facing readiness
Merged
#300 Render unknown for a zero CreatedAt in Slack/Mattermost messages (closes #298)
Merged
#297 Carry the event's receipt time into every delivery (closes #257)
Merged
#296 Correct four documentation claims ahead of the 1.0.0 tag
Merged
#292 Close the two remaining delivery terminal-state gaps (closes #107)
Merged
#287 Create every SQLite file 0600 (closes #255)
Merged
#289 Fail loudly on an unparseable SENTRY_DSN and a malformed .env (closes #283)
Merged
#286 Derive the source detail BaseURL scheme from reqtls (closes #272)
Merged
#263 Make SQLite durable under concurrent readers and stop re-delivering stranded webhooks (closes #256)
Merged
#284 Record landed 1.0.0 work and drop the removed signing roadmap in TODO.md
Merged
#277 Bind the app port deliberately and document the proxy deployment (closes #268)
Merged
#281 Remove inbound request signature verification (closes #279)
Merged
#260 Stamp the build version into the binary (closes #253)
Merged
#276 Decide request TLS in one place, per request (closes #269)
Merged
#273 Check every statement in the webhook deletion transaction (closes #262)
Merged
#266 Name a deleted target on its historical deliveries (closes #211)
Merged
#264 Bound the /metrics method label (closes #261)
Merged
#259 Validate max_retries on both target forms (closes #221)
Merged
#258 Label HTTP metrics with the chi route pattern (closes #254)
Merged
#251 Resubmit a stored event as a new undelivered event (closes #250)
Merged
#249 Record the completed 1.0.0 milestone in TODO.md
Merged
#242 Harden operator-set target headers (closes #233)
Merged
#217 Add an egress CIDR allowlist to the SSRF guard (closes #204)
Merged
#219 Render delivery attempt detail in the event log (closes #202)
Merged
#240 Add per-delivery replay to the event log (closes #203)
Merged
#239 Add a webhooker resetpw subcommand and a bootstrap banner (closes #208)
Merged
#228 Add optional inbound webhook signature verification (closes #67)
Merged
#223 Stop target credentials leaking into event databases (closes #206)
Merged
#237 Read queue depths with Find, not Scan (closes #234)
Merged
#229 Add a target edit form and reachable header/timeout fields (closes #127)
Merged
#220 Lock DATA_DIR against a second instance (closes #201)
Merged
#222 Log SQL with placeholders, never bound values (closes #207)
Merged
#224 Expose delivery metrics on /metrics (closes #209)
Merged
#218 Exit non-zero when the HTTP listener fails (closes #200)
Merged
#216 Fail startup on half-set metrics credentials (closes #205)
Merged
#214 Document backup, restore and upgrade procedures (closes #210)
Merged
#213 Record the reopened 1.0.0 milestone in TODO.md
Merged
#199 Record the 1.0.0 milestone as complete in TODO.md
Merged
#195 Raise script/test's per-package timeout to 90s (closes #194)
Merged
#197 Re-sync REPO_POLICIES.md from prompts (closes #196)
Merged
#189 Report handler panics through the logger and answer 500 (closes #187)
Merged
#182 Route GORM's logger through slog and bound it (closes #178)
Merged
#180 Bound every slog line against client-chosen text (closes #176)
Merged
#188 Stop a slow host turning a login-guard test into a segfault (closes #186)
Merged
#192 Correct TODO.md milestone state and record seventeen landed units
Merged
#181 Send the chi route pattern to Sentry, not the concrete path (closes #179)
Merged
#174 Read form fields from the POST body only (closes #160)
Merged
#171 Verify login credentials before spending rate-limit budget (closes #150)
Merged
#165 Run all linting in Docker via Dockerfile.lint (closes #109)
Merged
#167 Serve an event's full stored body over HTTP (closes #157)
Merged
#155 Bound the access log line against client-chosen text (closes #146)
Merged
#161 Mark superseded commits honestly instead of skipped (closes #152)
Merged
#159 Set fx.StopTimeout inside the container stop grace (closes #134)
Merged
#162 Bucket IPv6 rate-limit keys by /64 (closes #125)
Merged
#156 Correct release-blocking README and startup-warning inaccuracies (closes #151)
Merged
#164 Fetch Alpine.js at build time under a verified hash (closes #145)
Merged
#158 Bound the event log's rendered bodies in the query (closes #135)
Merged
#126 Mask the http target's destination URL in the UI (closes #115)
Merged
#130 Bound shutdown hooks by their stop context (closes #102)
Merged
#131 Render templates via a buffer, not the ResponseWriter (closes #123)
Merged
#132 Align session codec max-age with the 7-day cap (closes #108)
Merged
#153 Warn when production shares one rate-limit bucket (closes #149)
Merged
#148 Record the last four milestone units in TODO.md
Merged
#143 Bound the receiver rate limit per client IP across /webhook/* (closes #139)
Merged
#144 Correct release-blocking documentation inaccuracies (closes #141)
Merged
#138 Make the CI gate execute the checks it reports on (closes #119)
Merged
#142 Require a positive RETENTION_SWEEP_INTERVAL (closes #140)
Merged
#137 Update TODO.md for the completed 1.0.0 milestone
Merged
#136 Scan the X-Forwarded-For chain without splitting it (closes #133)
Merged
#129 Cap the X-Forwarded-For hop walk at 64 entries (closes #124)
Merged
#122 Gate forwarded-header trust behind trusted-proxy config (closes #88)
Merged
#116 Clarify web UI terminology, copy, and the entrypoint URL (closes #57)
Merged
#121 Mask the target URL in delivery errors, SSRF logs and log page data (closes #118)
Merged
#87 Rate-limit the public webhook receiver endpoint (closes #64)
Merged
#91 Enforce the body size limit before CSRF parses the form (closes #90)
Merged
#114 Mask target config on the source detail page (closes #113)
Merged
#96 Allow retention_days of 0 to mean retain forever (closes #79)
Merged
#105 Add inactivity-based session timeout (closes #66)
Merged
#92 Fail loudly on set-but-unparseable env config values (closes #80)
Merged
#104 Terminally fail retrying deliveries with a non-retry target type (closes #82)
Merged
#95 Evict archive writers on deletion and sweep idle archives (closes #89)
Merged
#100 Root background loops at context.Background() (closes #97)
Merged
#83 Add admin password change flow (closes #65)
Merged
#86 Update golangci-lint to v2.12.2 with canonical config
Merged
#84 Implement the database archiving target (closes #43)
Merged
#81 Refactor delivery targets to a Target interface (closes #77)
Merged
#78 Add per-webhook event retention reaper (closes #63)
Merged
#75 Add NoCache middleware for authenticated pages (closes #61)
Merged
#73 Validate Slack target URLs at creation time (closes #68)
Merged
#74 Keep the SSRF-safe transport in clientForConfig (closes #69)
Merged
#71 Wrap /user/{username} in RequireAuth middleware (closes #60)
Merged
#72 Raise HTTP WriteTimeout above the request middleware timeout (closes #62)
1 Pull request proposed by 1 user
Proposed
#556 next into main
249 Issues closed from 2 users
Closed
#538 why is CGO being used?
Closed
#544 Move storing an event and creating its deliveries from the handlers into the delivery engine
Closed
#543 Store a target's settings as columns instead of a per-type JSON string
Closed
#542 Use one recovery routine at start and on every sweep tick
Closed
#541 Move the archive files into their own package
Closed
#539 Store a webhook's retention as a plain day count, 0 meaning forever
Closed
#540 Store a target's number of delivery attempts, at least one, instead of its retries
Closed
#535 A comment in the middleware says the query logger writes client values into statements; it drops them
Closed
#548 Sentry events can carry the entrypoint URL in the Referer header
Closed
#545 Build the binary without cgo
Closed
#530 CSP allows unsafe-inline scripts and styles and the README never says why
Closed
#528 BIND_ADDRESS=0.0.0.0 binds IPv6 too; the README describes it as IPv4-only and distinct from ::
Closed
#531 webhooker logs the entrypoint UUID at INFO although the README says to keep it out of logs
Closed
#527 A clean stop cancels in-flight delivery attempts and records them as failed; fire-and-forget deliveries are lost to a restart
Closed
#529 finished_at and archived_at are stored with Go's monotonic clock reading appended (m=+365.03)
Closed
#311 Review toward 1.0: identify and file all next steps
Closed
#525 The static image build links glibc's getaddrinfo and dlopen, which the Alpine runtime cannot satisfy
Closed
#522 Two code comments explain behaviour by what an earlier build left behind
Closed
#518 A # or ? in DATA_DIR makes every database open the same, shorter path
Closed
#520 The README describes an upgrade path that does not exist before 1.0
Closed
#112 Decision: TODO.md Completed Steps guarantees a merge conflict on every unit landing on next
Closed
#56 Move schema_migrations table creation into 000.sql with INTEGER version column
Closed
#185 If tracing is ever enabled, every Sentry transaction will collapse into one bucket named POST /(redacted)
Closed
#271 HSTS is a hardcoded 2-year includeSubDomains preload commitment with no opt-out and no documentation of its value
Closed
#85 Design: should delivery targets own their recovery/sweep loop, not just backoff?
Closed
#295 Observation, not a defect: one unreproducible SQLITE_IOERR_SHORT_READ storm under load on ZFS-backed storage
Closed
#506 Test helpers are compiled into the shipped binary
Closed
#511 Make next green: TestArchiveExport_Streams measures the shared heap and fails go test on noise
Closed
#507 Tests that fail at random under load
Closed
#508 CI fails at bootstrap: the runner cannot install Go
Closed
#504 Re-vendor the canonical files from sneak/prompts at dd4027b
Closed
#98 Deprecated gomodguard linter in the org-standard .golangci.yml (needs an upstream decision)
Closed
#265 script/docker is no longer byte-identical to the model script, and CI-built images stamp version "unknown"
Closed
#248 Migrate .golangci.yml from the deprecated gomodguard to gomodguard_v2
Closed
#500 The Redactor misses an echoed request line when the target URL has a query string but no path
Closed
#312 The inbound query string is discarded: a sender's URL parameters never reach storage, the UI or a target
Closed
#497 Merge main into next so the milestone PR merges again after 416
Closed
#414 Make main and next green: make test fails in the Docker build, and its output is cut off before the failure
Closed
#493 yarn 1 prints a url.parse() deprecation warning in the js-deps stage
Closed
#377 Audit: missing basic functionality and information across the whole UI
Closed
#391 At phone width the event log and the target list cut off statuses and controls
Closed
#215 make fmt does not format Markdown, so the org prettier settings are unenforced here
Closed
#274 Split internal/handlers/source_management.go along its three CRUD seams
Closed
#390 Event log cannot show only the events whose delivery failed
Closed
#389 The event log never shows an event's request headers or the entrypoint it arrived at
Closed
#399 The UI names the same things in different ways
Closed
#120 No JS linting, so the styleguide REPO_POLICIES binds us to is unenforced
Closed
#379 Archive database target: rotation setting puts year-month, day or hour in the filename
Closed
#386 Event log: attempts and deliveries show no time, event times have no zone, replays look like originals
Closed
#349 Event log: only the newest event expanded on load, and only the 50 most recent events
Closed
#400 Delete confirmations do not name the item or say what is lost
Closed
#388 Database and log target deliveries read "Status: — (no response)"
Closed
#348 Log viewer: the caret does not collapse an event; clicking the row should toggle it
Closed
#387 Replay is offered for a deleted target, and its refusal gives advice that cannot work
Closed
#385 A target paused by its circuit breaker is not shown as paused
Closed
#477 An http target's max_queue_size is stored and shown but nothing enforces it
Closed
#117 Page {{define "title"}} blocks never render; every browser tab reads "Webhooker"
Closed
#396 Archive expiry is a raw duration typed by hand (720h)
Closed
#381 Target and webhook edit pages lose what was typed when a save is rejected
Closed
#231 tailwindcss is unpinned, so the committed static/css/tailwind.css is not reproducible from the repo's own tooling
Closed
#373 New-webhook page: optional HTTP target URL and archive checkbox with pruning choice, creating those targets
Closed
#395 The slack target's retry setting is not shown in the target list
Closed
#372 Target list: successful and failed deliveries per target, in total and in the last 24h
Closed
#393 Entrypoints do not show when they last received an event
Closed
#370 Targets on the webhook page: one + Add, then pick a target type, then that type's settings
Closed
#369 Event bodies: per-event page, expandable recent events, full bodies under 32k, JSON formatted, scroll well over 200 lines
Closed
#290 File-sourced configuration paths have never been audited for silent defaults
Closed
#459 The main database's open errors do not name the file
Closed
#392 An entrypoint's description cannot be changed
Closed
#325 The event log's resubmit count reads every live event instead of using the resubmitted_from_id index
Closed
#397 A database target does not show its archive file, size or last write
Closed
#166 static.go embeds the js directory, so a missing fetched asset silently produces a binary with no Alpine
Closed
#374 Database targets: a Download button that exports the SQLite contents as gzipped JSON
Closed
#462 Six test-only gorm.Open calls still pass a bare gorm.Config
Closed
#170 Clamp the HTTP drain by the tail-hook reserve, not just the Sentry flush
Closed
#285 The withRetry bookkeeping-failure branch is unpinned: removing its error check leaves the suite green
Closed
#455 The eventBodyQuery comment credits the soft-delete predicate for refusing a reaped event
Closed
#252 Follow-ups from the PR 251 review: two comments state the wrong mechanism, and the resubmit route's middleware is untested
Closed
#232 Harden the (*gorm.DB).Scan guard test: three evasions, an overstated doc comment, and a weak file-count floor
Closed
#275 DeleteDB returns on the first failing suffix, so it can report a leftover file when the history is already destroyed
Closed
#375 Clickable things must look clickable: the entrypoint URL "copy" control, "+ Add", and every other one
Closed
#103 Pin the pre-reopen close in archiveWriter.sweepExpired (unprotected connection-leak guard)
Closed
#452 Tests outside the config package still read the developer's shell when they build a Config
Closed
#294 TestProcessRetryTask_LargeBody_FetchFromDB stays green when the fetch it exists to exercise is deleted
Closed
#93 Follow-ups from the PR #91 review: body-limit docs and route-ordering test coverage
Closed
#172 Assert the access-log encoded-byte charge against every Unicode code point
Closed
#94 Follow-ups from the PR #92 review: config test hygiene and env docs
Closed
#183 Two writers bypass internal/logger: fx's console logger and the Go runtime
Closed
#238 The event-DB sweep marker is monotonic and trusts itself, so a downgrade re-leaks target rows permanently
Closed
#168 Rate-limit key collapses every peer with an empty RemoteAddr into one bucket
Closed
#99 Follow-ups from the PR #96 re-review: retention bound docs and untested normalisation
Closed
#270 The access log records the proxy's address, never the client's, so abuse cannot be traced from webhooker's own logs
Closed
#198 make test is past the org 20s target and arguably past the 60s hard cap, driven almost entirely by internal/handlers
Closed
#371 The UI's Alpine.js never runs: the Content-Security-Policy forbids the eval it needs
Closed
#190 Last wall-clock-dependent test: two writes must land inside a real 2s debounce window or correct code reds
Closed
#101 Archive sweep repeats open/prune/close once per database target instead of once per webhook
Closed
#177 Target.Webhook and Webhook.Targets form a reference cycle that will recurse once anything marshals a preloaded model
Closed
#128 Form-error paths commit a 4xx before rendering, so a failed render there cannot report 500
Closed
#175 The CI workflow step is named "runs make check", which the image has never done
Closed
#431 The target toggle saves the whole row, so it can undo an edit of the same target
Closed
#154 middleware tests construct cookie stores by hand, so they no longer match the production store
Closed
#225 internal/handlers tests are load-fragile: both the fx start budget and the 90s package timeout blow under host load, so the gate reports failures unrelated to the change
Closed
#394 Webhook list does not show which webhooks are receiving or failing
Closed
#173 The receiver's 1 MB body cap lives in the handler, not the middleware the other route groups use
Closed
#376 Archive database filename includes the webhook name and the target name
Closed
#317 MAINTENANCE_MODE is a documented no-op configuration variable
Closed
#191 loggingResponseWriter has no Unwrap, so http.ResponseController cannot reach the real writer through the shipped chain
Closed
#267 webhooker_delivery_duration_seconds is absent from a scrape until the first delivery occurs
Closed
#402 No page shows the server's settings
Closed
#315 script/test always runs verbose and never measures coverage, against the policy pattern
Closed
#341 The SSRF guard lets a delivery reach [::], which is the host itself on Linux
Closed
#230 Data race in internal/handlers/logbound_test.go: fx testutil.WriteSyncer calls t.Logf from a start hook after the test goroutine has finished
Closed
#383 No message after saving, deleting, activating or signing out
Closed
#421 TODO.md says a docs-only commit replays from the layer cache, which is no longer true
Closed
#350 Webhook page: widen the entrypoints container by 50-100% so the URL does not wrap
Closed
#313 Outbound User-Agent is the hardcoded webhooker/1.0, not the stamped build version
Closed
#227 go test -count=2 ./internal/server/... panics on duplicate metrics collector registration
Closed
#366 Image built by upaas stamps version "unknown" into the binary
Closed
#382 Error pages outside forms are bare text with no way back
Closed
#398 Refusing a private target address does not say how to allow it
Closed
#384 Signing in does not return to the page that was asked for
Closed
#368 Per-webhook page: statistics pane at the top (lifetime and per retention period)
Closed
#367 Routes: per-webhook page under /webhook/ (not /source/), its log at .../events, inbound URLs under /h/UUID or /ingest/UUID
Closed
#344 make test needs up to 6.7 GiB of RAM (handlers and database tests under -race)
Closed
#412 Remove buildarch mentions: the architecture is read at runtime
Closed
#333 Trust the RFC 1918 ranges as proxies when TRUSTED_PROXIES is unset
Closed
#244 blockedNetworks does not cover in-cloud provider service networks on public unicast, e.g. IBM Cloud 161.26.0.0/16 and 166.8.0.0/14
Closed
#347 Recent events on a webhook page: 50 rows, relative times, size, processing time, delivery status
Closed
#401 Profile page says "Account Type: Standard User" for the admin account
Closed
#345 Commit the Alpine.js tarball in 3p/ instead of downloading it at build time
Closed
#184 Nothing bounds username length, and an account with a multi-KB username cannot log in at all
Closed
#363 Run every build, test and lint step in the Dockerfiles at nice -n 19
Closed
#340 The container sets its data directory permissions itself before startup
Closed
#359 After a restart under upaas: new admin password, and logging in with it returns 500
Closed
#169 Restrict /s/* to GET and HEAD — it currently answers POST, PUT and DELETE with 200
Closed
#193 Headers set before an uncommitted panic survive onto the recovered 500, including Set-Cookie
Closed
#245 Default-block the public-unicast cloud metadata endpoints (Azure WireServer, Equinix Metal)
Closed
#280 Archive writers are never closed at shutdown, so their -wal survives a clean stop
Closed
#246 A delivery can carry Content-Type twice when the inbound event also supplied one
Closed
#293 A pending delivery whose target was deleted is stranded forever
Closed
#306 Circuit breaker half-open state busy-loops queued tasks with a DB write per spin
Closed
#291 GetDB can open the same event database twice, and closing the loser drops the winner's file locks
Closed
#282 make check fails on a fresh clone because script/check does not fetch the vendored assets
Closed
#299 Startup recovery races the receiver and can deliver a fresh event twice
Closed
#314 No index on the columns the sweeps, recovery and the event log filter by
Closed
#307 WEBHOOKER_ENVIRONMENT defaults to dev, silently shipping insecure prod (no Secure cookies, CORS *)
Closed
#323 Ready to run under upaas: prod branch, one data volume, env configuration, README section
Closed
#316 max_retries=N means N attempts in total, but the form label and the field name say retries
Closed
#288 Two constants define the data directory mode, in two packages that both create it
Closed
#303 Independent code audit
Closed
#278 Changing the password neither regenerates the current session nor invalidates any other one
Closed
#305 Notify drops tasks on full channel; pending deliveries only recover on process restart
Closed
#308 Listener bind failure leaves the process running with no listener instead of exiting non-zero
Closed
#309 SSRF blocking has no opt-out: cannot deliver to RFC1918/LAN targets — needs ALLOWED_TARGET_CIDRS
Closed
#310 Replay/redelivery does not exist and the UI shows no per-attempt results, despite README promises
Closed
#304 SQLite concurrency: cache=shared, no busy_timeout, no WAL, unbounded pool — concurrent writers get SQLITE_BUSY, deliveries stick pending
Closed
#301 Document that the entrypoint UUID is the authentication and shared secrets are never used
Closed
#147 CI gate follow-ups: script/cibuild has drifted from the model script, and the status-rewrite context string is hardcoded
Closed
#298 The reaped-row fallback renders the exact zero timestamp that #257 was filed against
Closed
#257 Every Slack message shows a zero timestamp of 0001-01-01T00:00:00Z
Closed
#107 Two remaining delivery terminal-state gaps: opaque failure and deletion-orphaned retries
Closed
#255 SQLite files are created 0644 with plaintext credentials, and the documented Docker deployment supplies the parent directory 0755
Closed
#283 Two config paths fail silently: an unparseable SENTRY_DSN starts anyway, and a malformed .env is discarded whole
Closed
#272 BaseURL on the source detail page uses the raw X-Forwarded-Proto value as the URL scheme
Closed
#256 A concurrent reader wedges the per-webhook database, stranding delivered webhooks at pending and re-delivering them on restart
Closed
#226 SIGTERM during startup panics on a nil httpServer, and cleanShutdown reads two fields with no happens-before edge
Closed
#268 The plaintext app port binds all interfaces and the README has no reverse-proxy deployment section
Closed
#241 README understates who can replay a signed request: forwarding X-Hub-Signature-256 hands every target a valid (body, signature) pair
Closed
#279 Remove inbound request signature verification: the entrypoint UUID is the authentication secret
Closed
#253 The shipped binary reports version "dev": no -X ldflags in the Makefile or Dockerfile
Closed
#269 The session cookie silently loses Secure in the default environment, and X-Forwarded-Proto parsing is exact-match
Closed
#262 Webhook deletion commits a partial delete and reports success when a delete statement fails
Closed
#211 Deleting a target blanks its name on every historical delivery in the event log
Closed
#261 The /metrics method label is still unbounded: 300 requests with random method tokens mint 7,525 permanent series
Closed
#221 max_retries is unbounded at target creation, and unparseable input silently becomes 0
Closed
#254 Enabling /metrics lets an unauthenticated client grow the process without bound, and publishes live entrypoint UUIDs
Closed
#247 Invalid target header name error no longer indicates which line was rejected
Closed
#250 Resubmit a stored event as a new undelivered event, so backends can be tested against real captured traffic
Closed
#243 Forwarded inbound event headers are not stripped on a cross-origin redirect, unlike operator-configured ones
Closed
#233 Operator-set target headers: credential headers survive a cross-host redirect, Trailer is not reserved, and an invalid header name error can quote a secret
Closed
#204 The SSRF blocklist has no escape hatch, so a self-hosted proxy cannot forward to your own network
Closed
#236 next ships a target edit form whose Tailwind classes are missing from the committed CSS
Closed
#202 Delivery failures are invisible in the UI: nothing renders status_code, response_body, error or attempt_num
Closed
#203 No replay: a delivery that exhausts max_retries is failed forever, and store-and-forward is the point
Closed
#208 No admin password recovery path: lose the one-time bootstrap line and the deployment is unreachable
Closed
#67 Optional inbound webhook HMAC signature verification
Closed
#206 Target credentials leak into the per-webhook event databases via GORM association upsert
Closed
#234 next is red: queue_depth.go calls (*gorm.DB).Scan, which interpolates bound values into logged SQL
Closed
#235 next is red: queue_depth.go calls (*gorm.DB).Scan, tripping the scan guard
Closed
#127 No target edit form: a target's destination URL, headers and timeout are write-once
Closed
#201 No lock on DATA_DIR: two instances both run delivery recovery and both deliver
Closed
#207 DEBUG=true prints the session encryption key and the admin password hash to the log
Closed
#209 No delivery metrics: /metrics cannot tell you whether the product is doing its job
Closed
#200 A failed listen leaves a live, non-serving process that fx still reports RUNNING
Closed
#205 METRICS_USERNAME set with an empty METRICS_PASSWORD publishes /metrics unauthenticated
Closed
#210 No backup, restore or upgrade guidance anywhere in the README
Closed
#194 internal/handlers runs at 22s against script/test's 30s per-package timeout, and has already reded a build under load
Closed
#196 REPO_POLICIES.md is a stale copy: it mandates a 30s test timeout the org policy replaced with 90s
Closed
#187 chi's Recoverer panics instead of handling a handler panic, so a panicking request drops the connection instead of answering 500
Closed
#178 GORM's default logger prints the full interpolated SQL, including the client-chosen path and username, on every record-not-found
Closed
#176 MaxBodySize logs the full client-chosen path ahead of RequireAuth, sidestepping the access-log line budget
Closed
#186 A timing-sensitive login-guard test panics on a nil release and reds the whole internal/middleware package
Closed
#179 The receiver's capability URL is sent to Sentry in full
Closed
#160 Target create reads the destination URL via r.FormValue, so a query-string credential lands in the access log and Sentry
Closed
#150 Decision: should login rate limiting survive a shared bucket, or should TRUSTED_PROXIES be mandatory in production?
Closed
#106 script/lint uses the host golangci-lint and a shared cache, so lint results can be wrong in either direction
Closed
#109 Run all linting in Docker via Dockerfile.lint + script/lint
Closed
#157 No in-app way to retrieve an event body larger than the event log's 8 KB render cap
Closed
#146 The access log writes one INFO line with the full attacker-controlled URL per request, including rejected ones
Closed
#152 Superseded-run status laundering: a never-tested commit reads green in the combined status
Closed
#134 fx.StopTimeout is never set, so the bounded-shutdown fix does not fire under a default docker stop
Closed
#125 Decision: should IPv6 rate-limit keys bucket by /64 rather than per-address?
Closed
#151 Release-blocking accuracy: README describes a build and an endpoint that do not exist, and the lockout warning misses the default environment
Closed
#145 A minified vendored bundle is committed to the repo, which REPO_POLICIES forbids
Closed
#135 The event-log page renders stored bodies untruncated, so buffered rendering can hold ~25 MB per request
Closed
#115 HTTP target destination URL is rendered in full and can itself be a bearer credential
Closed
#102 Shutdown hooks ignore their context and wg.Wait() unbounded
Closed
#123 renderTemplate streams to the ResponseWriter, so a mid-render template error ships a partial page
Closed
#108 Session codec max-age still 30 days: bring securecookie codecs in line with the 7-day cap
Closed
#149 Default config allows a remote stranger to lock the operator out of the admin UI, and nothing warns about it
Closed
#139 The receiver rate limit is per-URL-path, so an attacker gets unlimited aggregate rate against /webhook/*
Closed
#141 Release-readiness accuracy: docs contradict the code, TODO.md omits landed units, debug logging in the production asset
Closed
#119 CI can report success without running lint or tests, because script/cibuild replays a cached image
Closed
#140 RETENTION_SWEEP_INTERVAL is not range-checked, so a non-positive value panics two goroutines after startup reports success
Closed
#133 The hop cap bounds the walk but not the Split: a 1 MB X-Forwarded-For still allocates ~8 MB per request
Closed
#124 Cap the X-Forwarded-For hop walk: an unbounded chain burns CPU on every request
Closed
#88 Gate forwarded-header trust behind trusted-proxy config in rate limiters
Closed
#57 Clean up and clarify the web UI
Closed
#118 Slack webhook credential still leaks via delivery errors, SSRF logs, and the source_logs template data
Closed
#64 Rate-limit the public webhook receiver endpoint
Closed
#90 Enforce request body size limit before CSRF middleware parses the form
Closed
#113 Source detail page renders raw target config, exposing the Slack webhook URL credential
Closed
#79 RetentionDays cannot be set to 0 (retain forever) via the normal create path
Closed
#110 TOP PRIORITY: consolidate all open PRs onto one next branch, one PR
Closed
#66 Add inactivity-based session timeout
Closed
#80 Config parsing should fail loudly on set-but-unparseable env values (envInt, etc.)
Closed
#82 Recovery skips orphaned retrying deliveries whose target type changed to a non-retry type
Closed
#89 Archive writer lifecycle: evict writers on webhook deletion and sweep idle archives
Closed
#97 CRITICAL: delivery engine and retention reaper both die ~15s after startup (fx OnStart context)
Closed
#65 Add an admin password change flow in the web UI
Closed
#43 configure db target type for archiving
Closed
#77 Refactor delivery targets to a Target interface
Closed
#63 Enforce per-webhook event retention (RetentionDays reaper)
Closed
#61 Set Cache-Control: no-store on authenticated pages
Closed
#70 Implement the log delivery target
Closed
#68 Validate Slack target URLs at creation time (SSRF parity with HTTP targets)
Closed
#69 Keep the SSRF-safe Transport in clientForConfig when a per-target timeout is set
Closed
#60 Wrap the /user/{username} route in RequireAuth middleware
Closed
#62 Reconcile HTTP WriteTimeout with the request middleware timeout
249 Issues created by 1 user
Opened
#60 Wrap the /user/{username} route in RequireAuth middleware
Opened
#61 Set Cache-Control: no-store on authenticated pages
Opened
#62 Reconcile HTTP WriteTimeout with the request middleware timeout
Opened
#63 Enforce per-webhook event retention (RetentionDays reaper)
Opened
#64 Rate-limit the public webhook receiver endpoint
Opened
#65 Add an admin password change flow in the web UI
Opened
#66 Add inactivity-based session timeout
Opened
#67 Optional inbound webhook HMAC signature verification
Opened
#68 Validate Slack target URLs at creation time (SSRF parity with HTTP targets)
Opened
#69 Keep the SSRF-safe Transport in clientForConfig when a per-target timeout is set
Opened
#70 Implement the log delivery target
Opened
#77 Refactor delivery targets to a Target interface
Opened
#79 RetentionDays cannot be set to 0 (retain forever) via the normal create path
Opened
#80 Config parsing should fail loudly on set-but-unparseable env values (envInt, etc.)
Opened
#82 Recovery skips orphaned retrying deliveries whose target type changed to a non-retry type
Opened
#85 Design: should delivery targets own their recovery/sweep loop, not just backoff?
Opened
#88 Gate forwarded-header trust behind trusted-proxy config in rate limiters
Opened
#89 Archive writer lifecycle: evict writers on webhook deletion and sweep idle archives
Opened
#90 Enforce request body size limit before CSRF middleware parses the form
Opened
#93 Follow-ups from the PR #91 review: body-limit docs and route-ordering test coverage
Opened
#94 Follow-ups from the PR #92 review: config test hygiene and env docs
Opened
#97 CRITICAL: delivery engine and retention reaper both die ~15s after startup (fx OnStart context)
Opened
#98 Deprecated gomodguard linter in the org-standard .golangci.yml (needs an upstream decision)
Opened
#99 Follow-ups from the PR #96 re-review: retention bound docs and untested normalisation
Opened
#101 Archive sweep repeats open/prune/close once per database target instead of once per webhook
Opened
#102 Shutdown hooks ignore their context and wg.Wait() unbounded
Opened
#103 Pin the pre-reopen close in archiveWriter.sweepExpired (unprotected connection-leak guard)
Opened
#106 script/lint uses the host golangci-lint and a shared cache, so lint results can be wrong in either direction
Opened
#107 Two remaining delivery terminal-state gaps: opaque failure and deletion-orphaned retries
Opened
#108 Session codec max-age still 30 days: bring securecookie codecs in line with the 7-day cap
Opened
#109 Run all linting in Docker via Dockerfile.lint + script/lint
Opened
#110 TOP PRIORITY: consolidate all open PRs onto one next branch, one PR
Opened
#112 Decision: TODO.md Completed Steps guarantees a merge conflict on every unit landing on next
Opened
#113 Source detail page renders raw target config, exposing the Slack webhook URL credential
Opened
#115 HTTP target destination URL is rendered in full and can itself be a bearer credential
Opened
#117 Page {{define "title"}} blocks never render; every browser tab reads "Webhooker"
Opened
#118 Slack webhook credential still leaks via delivery errors, SSRF logs, and the source_logs template data
Opened
#119 CI can report success without running lint or tests, because script/cibuild replays a cached image
Opened
#120 No JS linting, so the styleguide REPO_POLICIES binds us to is unenforced
Opened
#123 renderTemplate streams to the ResponseWriter, so a mid-render template error ships a partial page
Opened
#124 Cap the X-Forwarded-For hop walk: an unbounded chain burns CPU on every request
Opened
#125 Decision: should IPv6 rate-limit keys bucket by /64 rather than per-address?
Opened
#127 No target edit form: a target's destination URL, headers and timeout are write-once
Opened
#128 Form-error paths commit a 4xx before rendering, so a failed render there cannot report 500
Opened
#133 The hop cap bounds the walk but not the Split: a 1 MB X-Forwarded-For still allocates ~8 MB per request
Opened
#134 fx.StopTimeout is never set, so the bounded-shutdown fix does not fire under a default docker stop
Opened
#135 The event-log page renders stored bodies untruncated, so buffered rendering can hold ~25 MB per request
Opened
#139 The receiver rate limit is per-URL-path, so an attacker gets unlimited aggregate rate against /webhook/*
Opened
#140 RETENTION_SWEEP_INTERVAL is not range-checked, so a non-positive value panics two goroutines after startup reports success
Opened
#141 Release-readiness accuracy: docs contradict the code, TODO.md omits landed units, debug logging in the production asset
Opened
#145 A minified vendored bundle is committed to the repo, which REPO_POLICIES forbids
Opened
#146 The access log writes one INFO line with the full attacker-controlled URL per request, including rejected ones
Opened
#147 CI gate follow-ups: script/cibuild has drifted from the model script, and the status-rewrite context string is hardcoded
Opened
#149 Default config allows a remote stranger to lock the operator out of the admin UI, and nothing warns about it
Opened
#150 Decision: should login rate limiting survive a shared bucket, or should TRUSTED_PROXIES be mandatory in production?
Opened
#151 Release-blocking accuracy: README describes a build and an endpoint that do not exist, and the lockout warning misses the default environment
Opened
#152 Superseded-run status laundering: a never-tested commit reads green in the combined status
Opened
#154 middleware tests construct cookie stores by hand, so they no longer match the production store
Opened
#157 No in-app way to retrieve an event body larger than the event log's 8 KB render cap
Opened
#160 Target create reads the destination URL via r.FormValue, so a query-string credential lands in the access log and Sentry
Opened
#163 Consider dropping Alpine.js and writing its 19 directive uses directly
Opened
#166 static.go embeds the js directory, so a missing fetched asset silently produces a binary with no Alpine
Opened
#168 Rate-limit key collapses every peer with an empty RemoteAddr into one bucket
Opened
#169 Restrict /s/* to GET and HEAD — it currently answers POST, PUT and DELETE with 200
Opened
#170 Clamp the HTTP drain by the tail-hook reserve, not just the Sentry flush
Opened
#172 Assert the access-log encoded-byte charge against every Unicode code point
Opened
#173 The receiver's 1 MB body cap lives in the handler, not the middleware the other route groups use
Opened
#175 The CI workflow step is named "runs make check", which the image has never done
Opened
#176 MaxBodySize logs the full client-chosen path ahead of RequireAuth, sidestepping the access-log line budget
Opened
#177 Target.Webhook and Webhook.Targets form a reference cycle that will recurse once anything marshals a preloaded model
Opened
#178 GORM's default logger prints the full interpolated SQL, including the client-chosen path and username, on every record-not-found
Opened
#179 The receiver's capability URL is sent to Sentry in full
Opened
#183 Two writers bypass internal/logger: fx's console logger and the Go runtime
Opened
#184 Nothing bounds username length, and an account with a multi-KB username cannot log in at all
Opened
#185 If tracing is ever enabled, every Sentry transaction will collapse into one bucket named POST /(redacted)
Opened
#186 A timing-sensitive login-guard test panics on a nil release and reds the whole internal/middleware package
Opened
#187 chi's Recoverer panics instead of handling a handler panic, so a panicking request drops the connection instead of answering 500
Opened
#190 Last wall-clock-dependent test: two writes must land inside a real 2s debounce window or correct code reds
Opened
#191 loggingResponseWriter has no Unwrap, so http.ResponseController cannot reach the real writer through the shipped chain
Opened
#193 Headers set before an uncommitted panic survive onto the recovered 500, including Set-Cookie
Opened
#194 internal/handlers runs at 22s against script/test's 30s per-package timeout, and has already reded a build under load
Opened
#196 REPO_POLICIES.md is a stale copy: it mandates a 30s test timeout the org policy replaced with 90s
Opened
#198 make test is past the org 20s target and arguably past the 60s hard cap, driven almost entirely by internal/handlers
Opened
#200 A failed listen leaves a live, non-serving process that fx still reports RUNNING
Opened
#201 No lock on DATA_DIR: two instances both run delivery recovery and both deliver
Opened
#202 Delivery failures are invisible in the UI: nothing renders status_code, response_body, error or attempt_num
Opened
#203 No replay: a delivery that exhausts max_retries is failed forever, and store-and-forward is the point
Opened
#204 The SSRF blocklist has no escape hatch, so a self-hosted proxy cannot forward to your own network
Opened
#205 METRICS_USERNAME set with an empty METRICS_PASSWORD publishes /metrics unauthenticated
Opened
#206 Target credentials leak into the per-webhook event databases via GORM association upsert
Opened
#207 DEBUG=true prints the session encryption key and the admin password hash to the log
Opened
#208 No admin password recovery path: lose the one-time bootstrap line and the deployment is unreachable
Opened
#209 No delivery metrics: /metrics cannot tell you whether the product is doing its job
Opened
#210 No backup, restore or upgrade guidance anywhere in the README
Opened
#211 Deleting a target blanks its name on every historical delivery in the event log
Opened
#212 Encrypt credential-bearing target config at rest in webhooker.db
Opened
#215 make fmt does not format Markdown, so the org prettier settings are unenforced here
Opened
#221 max_retries is unbounded at target creation, and unparseable input silently becomes 0
Opened
#225 internal/handlers tests are load-fragile: both the fx start budget and the 90s package timeout blow under host load, so the gate reports failures unrelated to the change
Opened
#226 SIGTERM during startup panics on a nil httpServer, and cleanShutdown reads two fields with no happens-before edge
Opened
#227 go test -count=2 ./internal/server/... panics on duplicate metrics collector registration
Opened
#230 Data race in internal/handlers/logbound_test.go: fx testutil.WriteSyncer calls t.Logf from a start hook after the test goroutine has finished
Opened
#231 tailwindcss is unpinned, so the committed static/css/tailwind.css is not reproducible from the repo's own tooling
Opened
#232 Harden the (*gorm.DB).Scan guard test: three evasions, an overstated doc comment, and a weak file-count floor
Opened
#233 Operator-set target headers: credential headers survive a cross-host redirect, Trailer is not reserved, and an invalid header name error can quote a secret
Opened
#234 next is red: queue_depth.go calls (*gorm.DB).Scan, which interpolates bound values into logged SQL
Opened
#235 next is red: queue_depth.go calls (*gorm.DB).Scan, tripping the scan guard
Opened
#236 next ships a target edit form whose Tailwind classes are missing from the committed CSS
Opened
#238 The event-DB sweep marker is monotonic and trusts itself, so a downgrade re-leaks target rows permanently
Opened
#241 README understates who can replay a signed request: forwarding X-Hub-Signature-256 hands every target a valid (body, signature) pair
Opened
#243 Forwarded inbound event headers are not stripped on a cross-origin redirect, unlike operator-configured ones
Opened
#244 blockedNetworks does not cover in-cloud provider service networks on public unicast, e.g. IBM Cloud 161.26.0.0/16 and 166.8.0.0/14
Opened
#245 Default-block the public-unicast cloud metadata endpoints (Azure WireServer, Equinix Metal)
Opened
#246 A delivery can carry Content-Type twice when the inbound event also supplied one
Opened
#247 Invalid target header name error no longer indicates which line was rejected
Opened
#248 Migrate .golangci.yml from the deprecated gomodguard to gomodguard_v2
Opened
#250 Resubmit a stored event as a new undelivered event, so backends can be tested against real captured traffic
Opened
#252 Follow-ups from the PR 251 review: two comments state the wrong mechanism, and the resubmit route's middleware is untested
Opened
#253 The shipped binary reports version "dev": no -X ldflags in the Makefile or Dockerfile
Opened
#254 Enabling /metrics lets an unauthenticated client grow the process without bound, and publishes live entrypoint UUIDs
Opened
#255 SQLite files are created 0644 with plaintext credentials, and the documented Docker deployment supplies the parent directory 0755
Opened
#256 A concurrent reader wedges the per-webhook database, stranding delivered webhooks at pending and re-delivering them on restart
Opened
#257 Every Slack message shows a zero timestamp of 0001-01-01T00:00:00Z
Opened
#261 The /metrics method label is still unbounded: 300 requests with random method tokens mint 7,525 permanent series
Opened
#262 Webhook deletion commits a partial delete and reports success when a delete statement fails
Opened
#265 script/docker is no longer byte-identical to the model script, and CI-built images stamp version "unknown"
Opened
#267 webhooker_delivery_duration_seconds is absent from a scrape until the first delivery occurs
Opened
#268 The plaintext app port binds all interfaces and the README has no reverse-proxy deployment section
Opened
#269 The session cookie silently loses Secure in the default environment, and X-Forwarded-Proto parsing is exact-match
Opened
#270 The access log records the proxy's address, never the client's, so abuse cannot be traced from webhooker's own logs
Opened
#271 HSTS is a hardcoded 2-year includeSubDomains preload commitment with no opt-out and no documentation of its value
Opened
#272 BaseURL on the source detail page uses the raw X-Forwarded-Proto value as the URL scheme
Opened
#274 Split internal/handlers/source_management.go along its three CRUD seams
Opened
#275 DeleteDB returns on the first failing suffix, so it can report a leftover file when the history is already destroyed
Opened
#278 Changing the password neither regenerates the current session nor invalidates any other one
Opened
#279 Remove inbound request signature verification: the entrypoint UUID is the authentication secret
Opened
#280 Archive writers are never closed at shutdown, so their -wal survives a clean stop
Opened
#282 make check fails on a fresh clone because script/check does not fetch the vendored assets
Opened
#283 Two config paths fail silently: an unparseable SENTRY_DSN starts anyway, and a malformed .env is discarded whole
Opened
#285 The withRetry bookkeeping-failure branch is unpinned: removing its error check leaves the suite green
Opened
#288 Two constants define the data directory mode, in two packages that both create it
Opened
#290 File-sourced configuration paths have never been audited for silent defaults
Opened
#291 GetDB can open the same event database twice, and closing the loser drops the winner's file locks
Opened
#293 A pending delivery whose target was deleted is stranded forever
Opened
#294 TestProcessRetryTask_LargeBody_FetchFromDB stays green when the fetch it exists to exercise is deleted
Opened
#295 Observation, not a defect: one unreproducible SQLITE_IOERR_SHORT_READ storm under load on ZFS-backed storage
Opened
#298 The reaped-row fallback renders the exact zero timestamp that #257 was filed against
Opened
#299 Startup recovery races the receiver and can deliver a fresh event twice
Opened
#301 Document that the entrypoint UUID is the authentication and shared secrets are never used
Opened
#303 Independent code audit
Opened
#304 SQLite concurrency: cache=shared, no busy_timeout, no WAL, unbounded pool — concurrent writers get SQLITE_BUSY, deliveries stick pending
Opened
#305 Notify drops tasks on full channel; pending deliveries only recover on process restart
Opened
#306 Circuit breaker half-open state busy-loops queued tasks with a DB write per spin
Opened
#307 WEBHOOKER_ENVIRONMENT defaults to dev, silently shipping insecure prod (no Secure cookies, CORS *)
Opened
#308 Listener bind failure leaves the process running with no listener instead of exiting non-zero
Opened
#309 SSRF blocking has no opt-out: cannot deliver to RFC1918/LAN targets — needs ALLOWED_TARGET_CIDRS
Opened
#310 Replay/redelivery does not exist and the UI shows no per-attempt results, despite README promises
Opened
#311 Review toward 1.0: identify and file all next steps
Opened
#312 The inbound query string is discarded: a sender's URL parameters never reach storage, the UI or a target
Opened
#313 Outbound User-Agent is the hardcoded webhooker/1.0, not the stamped build version
Opened
#314 No index on the columns the sweeps, recovery and the event log filter by
Opened
#315 script/test always runs verbose and never measures coverage, against the policy pattern
Opened
#316 max_retries=N means N attempts in total, but the form label and the field name say retries
Opened
#317 MAINTENANCE_MODE is a documented no-op configuration variable
Opened
#323 Ready to run under upaas: prod branch, one data volume, env configuration, README section
Opened
#325 The event log's resubmit count reads every live event instead of using the resubmitted_from_id index
Opened
#333 Trust the RFC 1918 ranges as proxies when TRUSTED_PROXIES is unset
Opened
#340 The container sets its data directory permissions itself before startup
Opened
#341 The SSRF guard lets a delivery reach [::], which is the host itself on Linux
Opened
#344 make test needs up to 6.7 GiB of RAM (handlers and database tests under -race)
Opened
#345 Commit the Alpine.js tarball in 3p/ instead of downloading it at build time
Opened
#347 Recent events on a webhook page: 50 rows, relative times, size, processing time, delivery status
Opened
#348 Log viewer: the caret does not collapse an event; clicking the row should toggle it
Opened
#349 Event log: only the newest event expanded on load, and only the 50 most recent events
Opened
#350 Webhook page: widen the entrypoints container by 50-100% so the URL does not wrap
Opened
#359 After a restart under upaas: new admin password, and logging in with it returns 500
Opened
#363 Run every build, test and lint step in the Dockerfiles at nice -n 19
Opened
#366 Image built by upaas stamps version "unknown" into the binary
Opened
#367 Routes: per-webhook page under /webhook/ (not /source/), its log at .../events, inbound URLs under /h/UUID or /ingest/UUID
Opened
#368 Per-webhook page: statistics pane at the top (lifetime and per retention period)
Opened
#369 Event bodies: per-event page, expandable recent events, full bodies under 32k, JSON formatted, scroll well over 200 lines
Opened
#370 Targets on the webhook page: one + Add, then pick a target type, then that type's settings
Opened
#371 The UI's Alpine.js never runs: the Content-Security-Policy forbids the eval it needs
Opened
#372 Target list: successful and failed deliveries per target, in total and in the last 24h
Opened
#373 New-webhook page: optional HTTP target URL and archive checkbox with pruning choice, creating those targets
Opened
#374 Database targets: a Download button that exports the SQLite contents as gzipped JSON
Opened
#375 Clickable things must look clickable: the entrypoint URL "copy" control, "+ Add", and every other one
Opened
#376 Archive database filename includes the webhook name and the target name
Opened
#377 Audit: missing basic functionality and information across the whole UI
Opened
#379 Archive database target: rotation setting puts year-month, day or hour in the filename
Opened
#381 Target and webhook edit pages lose what was typed when a save is rejected
Opened
#382 Error pages outside forms are bare text with no way back
Opened
#383 No message after saving, deleting, activating or signing out
Opened
#384 Signing in does not return to the page that was asked for
Opened
#385 A target paused by its circuit breaker is not shown as paused
Opened
#386 Event log: attempts and deliveries show no time, event times have no zone, replays look like originals
Opened
#387 Replay is offered for a deleted target, and its refusal gives advice that cannot work
Opened
#388 Database and log target deliveries read "Status: — (no response)"
Opened
#389 The event log never shows an event's request headers or the entrypoint it arrived at
Opened
#390 Event log cannot show only the events whose delivery failed
Opened
#391 At phone width the event log and the target list cut off statuses and controls
Opened
#392 An entrypoint's description cannot be changed
Opened
#393 Entrypoints do not show when they last received an event
Opened
#394 Webhook list does not show which webhooks are receiving or failing
Opened
#395 The slack target's retry setting is not shown in the target list
Opened
#396 Archive expiry is a raw duration typed by hand (720h)
Opened
#397 A database target does not show its archive file, size or last write
Opened
#398 Refusing a private target address does not say how to allow it
Opened
#399 The UI names the same things in different ways
Opened
#400 Delete confirmations do not name the item or say what is lost
Opened
#401 Profile page says "Account Type: Standard User" for the admin account
Opened
#402 No page shows the server's settings
Opened
#412 Remove buildarch mentions: the architecture is read at runtime
Opened
#414 Make main and next green: make test fails in the Docker build, and its output is cut off before the failure
Opened
#421 TODO.md says a docs-only commit replays from the layer cache, which is no longer true
Opened
#431 The target toggle saves the whole row, so it can undo an edit of the same target
Opened
#452 Tests outside the config package still read the developer's shell when they build a Config
Opened
#455 The eventBodyQuery comment credits the soft-delete predicate for refusing a reaped event
Opened
#459 The main database's open errors do not name the file
Opened
#462 Six test-only gorm.Open calls still pass a bare gorm.Config
Opened
#477 An http target's max_queue_size is stored and shown but nothing enforces it
Opened
#493 yarn 1 prints a url.parse() deprecation warning in the js-deps stage
Opened
#497 Merge main into next so the milestone PR merges again after 416
Opened
#499 Recommendations for a clearer, simpler object and data model
Opened
#500 The Redactor misses an echoed request line when the target URL has a query string but no path
Opened
#504 Re-vendor the canonical files from sneak/prompts at dd4027b
Opened
#506 Test helpers are compiled into the shipped binary
Opened
#507 Tests that fail at random under load
Opened
#508 CI fails at bootstrap: the runner cannot install Go
Opened
#511 Make next green: TestArchiveExport_Streams measures the shared heap and fails go test on noise
Opened
#518 A # or ? in DATA_DIR makes every database open the same, shorter path
Opened
#520 The README describes an upgrade path that does not exist before 1.0
Opened
#522 Two code comments explain behaviour by what an earlier build left behind
Opened
#525 The static image build links glibc's getaddrinfo and dlopen, which the Alpine runtime cannot satisfy
Opened
#527 A clean stop cancels in-flight delivery attempts and records them as failed; fire-and-forget deliveries are lost to a restart
Opened
#528 BIND_ADDRESS=0.0.0.0 binds IPv6 too; the README describes it as IPv4-only and distinct from ::
Opened
#529 finished_at and archived_at are stored with Go's monotonic clock reading appended (m=+365.03)
Opened
#530 CSP allows unsafe-inline scripts and styles and the README never says why
Opened
#531 webhooker logs the entrypoint UUID at INFO although the README says to keep it out of logs
Opened
#535 A comment in the middleware says the query logger writes client values into statements; it drops them
Opened
#538 why is CGO being used?
Opened
#539 Store a webhook's retention as a plain day count, 0 meaning forever
Opened
#540 Store a target's number of delivery attempts, at least one, instead of its retries
Opened
#541 Move the archive files into their own package
Opened
#542 Use one recovery routine at start and on every sweep tick
Opened
#543 Store a target's settings as columns instead of a per-type JSON string
Opened
#544 Move storing an event and creating its deliveries from the handlers into the delivery engine
Opened
#545 Build the binary without cgo
Opened
#548 Sentry events can carry the entrypoint URL in the Referer header
1 Unresolved Conversation
Open
#33
1.0/mvp