Commit Graph

11 Commits

Author SHA1 Message Date
72868c0f02 Clarify web UI terminology, copy, and the entrypoint URL (closes #57)
All checks were successful
check / check (push) Successful in 3m18s
Terminology: the nav labelled its link Sources while every heading said
Webhooks. Both nav links and the sources list page title now say
Webhooks, matching the product name and the database.Webhook model. The
/sources and /source/{id} routes are deliberately unchanged; renaming
them would break existing bookmarks for no gain, since the URL is not
what a user reads.

Profile: the "Settings" column held only placeholder copy promising
settings that would appear later. Password change is the only real
account setting and it already has its own card below, so the column is
removed and the two-column grid collapses to the single remaining one.

Retention copy on the create and edit forms now describes what the code
does rather than what the field implies. The reaper permanently deletes
events past the cutoff along with their deliveries and delivery
results, so the hint says so instead of "how long to keep event data".
Both forms state that an empty field is not a way to ask for forever:
the create path falls back to DefaultRetentionDays and the edit path
leaves the stored policy alone, while 0 is what BeforeSave rewrites to
the retain-forever sentinel.

Entrypoint URL copy button as progressive enhancement. The button is
rendered with the hidden attribute and a data-copy-target naming the
element that holds the URL. app.js reveals it only after confirming
both a resolvable target and a usable Clipboard API, so a browser
without either shows no dead control, and the URL is plain selectable
text in every case. The script uses const throughout, per the JS
styleguide the repo policies bind this repo to; nothing in the repo's
checks covers JavaScript, so that is enforced by reading rather than by
the gate.

Template rendering assertions cover the nav labels, the absence of any
remaining user-visible "Sources", the button's hidden-by-default
markup, and both forms' retention copy including the forever label, so
the copy cannot drift back silently. The edit-page assertions pass the
webhook as a pointer because RetentionLabel is a pointer method and a
map element is not addressable.
2026-08-11 12:56:15 +00:00
c2cd2c440b Add inactivity-based session timeout (closes #66) (#105)
All checks were successful
check / check (push) Successful in 4s
Sessions now carry a server-enforced idle deadline (SESSION_IDLE_TIMEOUT,
default 24h) alongside the 7-day absolute cap, refreshed on authenticated
activity. Activity never extends the absolute cap.
2026-08-10 16:12:40 +02:00
45890d4f82 Fail loudly on set-but-unparseable env config values (closes #80) (#92)
Some checks failed
check / check (push) Has been cancelled
Defaults now apply only to unset or empty environment variables; a set-but-
unparseable value aborts startup with an error naming the key and the value.
envInt is gone, envBool parses with strconv.ParseBool, and PORT is bounded.
2026-08-10 16:06:12 +02:00
0ce8565f51 Terminally fail retrying deliveries with a non-retry target type (closes #82) (#104)
Some checks failed
check / check (push) Has been cancelled
A delivery left in `retrying` whose target type was edited to a fire-and-forget
or unknown type was skipped forever by both restart recovery and the retry
sweep. Both paths now record a result row and mark it `failed`.
2026-08-10 16:00:03 +02:00
3e261d2f01 Evict archive writers on deletion and sweep idle archives (closes #89) (#95)
Some checks failed
check / check (push) Has been cancelled
Per-webhook archive writers are now evicted when the webhook or its last
database target is deleted, and a background sweeper prunes expired rows from
idle archives that no longer receive writes. Archive files themselves are never
deleted.
2026-08-10 15:52:20 +02:00
62481a6f1a Root background loops at context.Background() (closes #97) (#100)
All checks were successful
check / check (push) Successful in 5s
The delivery engine worker pool and the retention reaper both rooted their
goroutines in the fx OnStart hook context, which fx cancels 15s into startup.
Both now use context.WithCancel(context.Background()), bounded by OnStop.
2026-08-10 15:44:56 +02:00
734606b7af Update golangci-lint to v2.12.2 with canonical config (#86)
All checks were successful
check / check (push) Successful in 3s
Bumps golangci-lint from v2.11.3 to v2.12.2 and adopts the canonical lint config.

## Version pins

- `Dockerfile`: `golangci/golangci-lint:v2.12.2` Debian image, pinned by digest, dated `2026-08-07`
- `script/bootstrap`: `GOLANGCI_LINT_VERSION=2.12.2` with updated sha256 pins for the `linux-amd64` and `linux-arm64` release archives

## Config

`.golangci.yml` replaced with the canonical config. The previous file kept `lll`/`funlen`/`cyclop`/`dupl` settings under the top-level `linters-settings` key, which the v2 schema ignores; the canonical config nests them under `linters.settings`, so those thresholds now actually apply. The unsupported `issues.exclude-use-default` key was dropped.

## Lint fixes (32 findings)

- `lll` (7): wrapped or shortened over-length lines (struct tag comments moved above fields, test logger construction split, `session.NewForTest` signature wrapped, shortened a `#nosec` comment)
- `goconst` (17): replaced repeated `"POST"`/`"PUT"` literals with `http.MethodPost`/`http.MethodPut`, added shared test constants for `webhooker-test`/`test`/`application/json`, and added `tmplKeyError`/`tmplKeyWebhook` constants for template data keys in `internal/handlers`
- `dupl` (8): merged `buildHTTPTargetConfig` and `buildSlackTargetConfig` into a parameterized `buildURLTargetConfig`; removed the duplicate `iWebhookDB` test helper in favor of `testWebhookDB`; extracted shared helpers in middleware and session tests

No `//nolint` directives were added and behavior is unchanged. `make check` (fmt-check, tests, lint) passes.

Note: golangci-lint v2.12 deprecates the `gomodguard` linter in favor of `gomodguard_v2`; the canonical config change for that is left for a future coordinated update.
Co-authored-by: sneak <sneak@sneak.berlin>
Reviewed-on: #86
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-08-07 23:18:49 +02:00
2cc8723997 scripts-to-rule-them-all (#59)
All checks were successful
check / check (push) Successful in 4s
Reviewed-on: #59
Co-authored-by: sneak <sneak@sneak.berlin>
Co-committed-by: sneak <sneak@sneak.berlin>
2026-07-07 02:14:09 +02:00
e0b1e7cf54 Restore TODO.md and move TODO content out of README (#58)
All checks were successful
check / check (push) Successful in 4s
Reviewed-on: #58
Co-authored-by: sneak <sneak@sneak.berlin>
Co-committed-by: sneak <sneak@sneak.berlin>
2026-07-06 21:14:03 +02:00
f9a9569015 feat: bring repo up to REPO_POLICIES standards (#6)
All checks were successful
check / check (push) Successful in 8s
## Summary

This PR brings the webhooker repo into full REPO_POLICIES compliance, addressing both [issue #1](#1) and [issue #2](#2).

## Changes

### New files
- **`cmd/webhooker/main.go`** — The missing application entry point. Uses Uber fx to wire together all internal packages (config, database, logger, server, handlers, middleware, healthcheck, globals, session). Minimal glue code.
- **`REPO_POLICIES.md`** — Fetched from authoritative source (`sneak/prompts`)
- **`.editorconfig`** — Fetched from authoritative source
- **`.dockerignore`** — Sensible Go project exclusions
- **`.gitea/workflows/check.yml`** — CI workflow that runs `docker build .` on push to any branch (Gitea Actions format, actions/checkout pinned by sha256)
- **`configs/config.yaml.example`** — Moved from root `config.yaml`

### Modified files
- **`Makefile`** — Complete rewrite with all REPO_POLICIES required targets: `test`, `lint`, `fmt`, `fmt-check`, `check`, `build`, `hooks`, `docker`, `clean`, plus `dev`, `run`, `deps`
- **`Dockerfile`** — Complete rewrite:
  - Builder: `golang:1.24` (Debian-based, pinned by `sha256:d2d2bc1c84f7...`). Debian needed because `gorm.io/driver/sqlite` pulls `mattn/go-sqlite3` (CGO) which fails on Alpine musl.
  - golangci-lint v1.64.8 installed from GitHub release archive with sha256 verification (v1.x because `.golangci.yml` uses v1 config format)
  - Runs `make check` (fmt-check + lint + test + build) as build step
  - Final stage: `alpine:3.21` (pinned by `sha256:c3f8e73fdb79...`) with non-root user, healthcheck, port 8080
- **`README.md`** — Rewritten with all required REPO_POLICIES sections: description line with name/purpose/category/license/author, Getting Started, Rationale, Design, TODO (integrated from TODO.md), License, Author
- **`.gitignore`** — Fixed `webhooker` pattern to `/webhooker` (was blocking `cmd/webhooker/`), added `config.yaml` to prevent committing runtime config with secrets
- **`static/static.go`** — Removed `vendor` from embed directive (directory was empty/missing)
- **`internal/database/database_test.go`** — Fixed to use in-memory config via `afero.MemMapFs` instead of depending on `config.yaml` on disk. Test is now properly isolated.
- **`go.mod`/`go.sum`** — `go mod tidy`

### Removed files
- **`TODO.md`** — Content integrated into README.md TODO section
- **`config.yaml`** — Moved to `configs/config.yaml.example`

## Verification
- `docker build .` passes (lint , test , build )
- All existing tests pass with no modifications to assertions or test logic
- `.golangci.yml` untouched

closes #1
closes #2

Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Reviewed-on: #6
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-01 19:01:44 +01:00
1244f3e2d5 initial 2026-03-01 22:52:08 +07:00