1 Commits
Author SHA1 Message Date
sneak 6e652a223a Commit Alpine.js to the repo instead of unpacking it at build time (closes #163)
check / check (push) Canceled after 0s
static/js/alpine.min.js is now committed: package/dist/cdn.min.js from
the @alpinejs/csp 3.14.9 npm package, byte for byte, taken once from the
package file that was in 3p/. The build no longer unpacks it, so
script/assets, the assets make target, its Dockerfile steps and the
ignore entries for the file are gone, and so is the package file.
Prettier and ESLint both ignore the file, so it stays as published.
Comments and the README now describe the committed file.

Model: opus-5-5
2026-10-26 03:46:37 +00:00
3 changed files with 25 additions and 23 deletions
+3 -2
View File
@@ -204,8 +204,9 @@ RUN version="$(make version VERSION="$VERSION")"; \
esac; \ esac; \
fi fi
# The Makefile's build target builds with cgo off, so the binary is # Builds through the Makefile's build target, which builds with cgo off, so
# statically linked and runs on the Alpine runtime image below. # the binary is statically linked and runs on the Alpine runtime image below
# as it is.
RUN make build VERSION="$VERSION" RUN make build VERSION="$VERSION"
# Runtime stage # Runtime stage
+21 -21
View File
@@ -47,7 +47,7 @@ identifier of its own to the request, so make your targets tolerate a duplicate.
## Getting Started ## Getting Started
You need the Go version named in `go.mod`. You need the Go version named in `go.mod`, and Docker for the checks.
```bash ```bash
git clone https://git.eeqj.de/sneak/webhooker.git git clone https://git.eeqj.de/sneak/webhooker.git
@@ -57,8 +57,9 @@ DATA_DIR=../webhooker-data make dev
``` ```
`DATA_DIR` is where webhooker keeps its databases. It defaults to `DATA_DIR` is where webhooker keeps its databases. It defaults to
`/var/lib/webhooker`, so point it at a directory you can write to. `make build` `/var/lib/webhooker`, so point it at a directory you can write to. On a host
writes the program to `bin/webhooker`. Running that file starts webhooker. without Docker, `make build` writes the program to `bin/webhooker`, and running
that file starts webhooker.
The first start creates the `admin` account and prints its password once, in a The first start creates the `admin` account and prints its password once, in a
ruled box on standard output: ruled box on standard output:
@@ -106,9 +107,9 @@ sooner after 24 hours without use, unless `SESSION_IDLE_TIMEOUT` says otherwise.
On the webhook list at `/hooks`, **New Webhook** asks for **Name**, an optional On the webhook list at `/hooks`, **New Webhook** asks for **Name**, an optional
**Description** and **Retention (days)**. Events older than the retention period **Description** and **Retention (days)**. Events older than the retention period
are deleted, along with their deliveries. The default is 30 days. `0` keeps are deleted, along with their deliveries. The default is 30 days. `0` keeps
events forever. Filling in **HTTP target URL** creates an `http` target with the events forever. The form also has an **HTTP target URL** field and an
webhook. Ticking **Archive** creates an archive target. Every new webhook gets **Archive** checkbox; each creates that target with the webhook. Every new
one entrypoint, described as `Default entrypoint`. webhook gets one entrypoint, described as `Default entrypoint`.
### Entrypoint URLs ### Entrypoint URLs
@@ -197,9 +198,9 @@ Read it with `docker logs` and the name upaas gave the container.
webhooker speaks plain HTTP. It does not handle TLS, the encryption behind webhooker speaks plain HTTP. It does not handle TLS, the encryption behind
HTTPS: it holds no certificate and accepts no HTTPS connections. The reverse HTTPS: it holds no certificate and accepts no HTTPS connections. The reverse
proxy holds the certificate and reaches webhooker over a private address. A bare proxy holds the certificate and reaches webhooker over a private address. A bare
host is a host without Docker. On a bare host the private address is loopback host is a host without Docker. On a bare host that is loopback, the address only
(`127.0.0.1`), which only this host can reach. For the image it is the Docker this host can reach. For the image it is the Docker bridge, the private network
bridge, the private network Docker puts containers on. Docker puts containers on.
Four things must be right. Four things must be right.
@@ -370,13 +371,13 @@ writes it. The reverse proxy's access log does hold it, in the request path.
### Sign-in limits ### Sign-in limits
From the fifth failure within a minute, each failure is answered `429`. Only The password is checked first, and only a failed sign-in is counted. A correct
failures are counted. A correct password is never answered `429`. Failures are password is never answered `429`. Failures are counted per client and submitted
counted per client and submitted username. At most two password checks run at username. From the fifth failure within a minute, each failure is answered
once; a request that gets no turn within 5 seconds is answered `503`. So `429`. At most two password checks run at once; a request that gets no turn
guessing speed is bounded by the limit of two checks at a time, not by the within 5 seconds is answered `503`. So guessing speed is bounded by the limit of
failure count. Choose a long random `admin` password, or rate-limit two checks at a time, not by the failure count. Choose a long random `admin`
`POST /pages/login` at the reverse proxy. password, or rate-limit `POST /pages/login` at the reverse proxy.
### Delivery destinations ### Delivery destinations
@@ -432,11 +433,10 @@ sends them on in the background, and SQLite holds everything in between.
The receiver stores the event and one pending delivery per active target in one The receiver stores the event and one pending delivery per active target in one
database write, then queues the deliveries. Background workers run them and database write, then queues the deliveries. Background workers run them and
record each attempt. At start, a recovery routine resumes every delivery left record each attempt. At start, a recovery routine queues again every delivery
`pending` or `retrying`. It then runs every minute. Each run resumes every left `pending` or `retrying`. It then runs every minute. Each run sends again a
`retrying` delivery that the engine is not already handling. It also resumes a `retrying` delivery the engine is not working on, and a `pending` one that has
`pending` delivery that has sat untouched for 15 minutes. So a stop or a crash sat untouched for 15 minutes. So a stop or a crash loses no delivery.
loses no delivery.
The main database holds configuration. Each webhook has its own event database, The main database holds configuration. Each webhook has its own event database,
so writes for one webhook never wait on another webhook's database. The program so writes for one webhook never wait on another webhook's database. The program
+1
View File
@@ -13,6 +13,7 @@ import (
// TestBaseTemplateScriptsAreServed walks every /s/ script the base // TestBaseTemplateScriptsAreServed walks every /s/ script the base
// template loads on each page and fetches it through the real router. // template loads on each page and fetches it through the real router.
// This is the check that each page gets the JavaScript it asks for.
func TestBaseTemplateScriptsAreServed(t *testing.T) { func TestBaseTemplateScriptsAreServed(t *testing.T) {
t.Parallel() t.Parallel()