Skip to content

Commit bdd0254

Browse files
committed
Initial commit: Dash webhook receiver reference implementation
A Laravel reference implementation for receiving and verifying signed webhook deliveries from the Dash webhook system (RFC 9421 HTTP message signatures over RSA, EC, and Ed25519 keys), with a live Livewire dashboard for inspecting received events.
0 parents  commit bdd0254

78 files changed

Lines changed: 14200 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
indent_size = 4
7+
indent_style = space
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.{yml,yaml}]
15+
indent_size = 2
16+
17+
[{compose,docker-compose}.{yml,yaml}]
18+
indent_size = 4

.env.example

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
APP_NAME="Webhook Receiver"
2+
APP_ENV=local
3+
APP_KEY=
4+
APP_DEBUG=true
5+
APP_URL=http://localhost:8000
6+
7+
APP_LOCALE=en
8+
APP_FALLBACK_LOCALE=en
9+
APP_FAKER_LOCALE=en_US
10+
11+
APP_MAINTENANCE_DRIVER=file
12+
13+
BCRYPT_ROUNDS=12
14+
15+
LOG_CHANNEL=stack
16+
LOG_STACK=single
17+
LOG_DEPRECATIONS_CHANNEL=null
18+
LOG_LEVEL=debug
19+
20+
DB_CONNECTION=mysql
21+
DB_HOST=db
22+
DB_PORT=3306
23+
DB_DATABASE=webhook_receiver
24+
DB_USERNAME=webhook
25+
DB_PASSWORD=secret
26+
27+
SESSION_DRIVER=file
28+
SESSION_LIFETIME=120
29+
SESSION_ENCRYPT=false
30+
SESSION_PATH=/
31+
SESSION_DOMAIN=null
32+
33+
BROADCAST_CONNECTION=log
34+
FILESYSTEM_DISK=local
35+
QUEUE_CONNECTION=sync
36+
37+
CACHE_STORE=file
38+
39+
MAIL_MAILER=log
40+
41+
VITE_APP_NAME="${APP_NAME}"
42+
43+
# --- Webhook Receiver settings ---
44+
45+
# URL of the sender's JWKS endpoint (required for signature verification)
46+
WEBHOOK_SENDER_JWKS_URL=
47+
48+
# The WebHook-Request-Origin value to allow. Use * to allow any origin.
49+
WEBHOOK_SENDER_ORIGIN=*
50+
51+
# Rate limit to advertise in the validation handshake (requests/minute)
52+
WEBHOOK_ALLOWED_RATE=1000
53+
54+
# Acceptable clock drift in seconds for the RFC 9421 'created' parameter
55+
WEBHOOK_REPLAY_WINDOW=300
56+
57+
# Optional shared Bearer secret for secondary authenticity check
58+
WEBHOOK_SECRET=
59+
60+
# How long to cache the sender's JWKS (seconds)
61+
WEBHOOK_JWKS_CACHE_TTL=3600

.gitattributes

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
* text=auto eol=lf
2+
3+
*.blade.php diff=html
4+
*.css diff=css
5+
*.html diff=html
6+
*.md diff=markdown
7+
*.php diff=php
8+
9+
/.github export-ignore
10+
CHANGELOG.md export-ignore
11+
.styleci.yml export-ignore

.github/workflows/ci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
lint:
10+
name: Pint (lint)
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Setup PHP
16+
uses: shivammathur/setup-php@v2
17+
with:
18+
php-version: '8.3'
19+
extensions: openssl, mbstring, pdo_sqlite, zip
20+
coverage: none
21+
22+
- name: Install Composer dependencies
23+
run: composer install --no-interaction --prefer-dist
24+
25+
- name: Run Pint
26+
run: vendor/bin/pint --test
27+
28+
test:
29+
name: PHPUnit
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- name: Setup PHP
35+
uses: shivammathur/setup-php@v2
36+
with:
37+
php-version: '8.5'
38+
extensions: openssl, mbstring, pdo_sqlite, zip
39+
coverage: none
40+
41+
- name: Install Composer dependencies
42+
run: composer install --no-interaction --prefer-dist
43+
44+
- name: Prepare environment
45+
run: |
46+
cp .env.example .env
47+
php artisan key:generate
48+
49+
- name: Run test suite
50+
run: composer test
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Publish Docker image
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: read
9+
packages: write
10+
11+
jobs:
12+
build-and-push:
13+
name: Build and push to GHCR
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Docker Buildx
20+
uses: docker/setup-buildx-action@v3
21+
22+
- name: Log in to GHCR
23+
uses: docker/login-action@v3
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Extract metadata
30+
id: meta
31+
uses: docker/metadata-action@v5
32+
with:
33+
images: ghcr.io/${{ github.repository }}
34+
tags: |
35+
type=semver,pattern={{version}}
36+
type=semver,pattern={{major}}.{{minor}}
37+
type=semver,pattern={{major}}
38+
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
39+
40+
- name: Build and push
41+
uses: docker/build-push-action@v6
42+
with:
43+
context: .
44+
push: true
45+
tags: ${{ steps.meta.outputs.tags }}
46+
labels: ${{ steps.meta.outputs.labels }}
47+
cache-from: type=gha
48+
cache-to: type=gha,mode=max

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
*.log
2+
.DS_Store
3+
.env
4+
.env.backup
5+
.env.production
6+
.phpactor.json
7+
.phpunit.result.cache
8+
/.codex
9+
/.cursor/
10+
/.idea
11+
/.nova
12+
/.phpunit.cache
13+
/.vscode
14+
/.zed
15+
/auth.json
16+
/node_modules
17+
/public/build
18+
/public/fonts-manifest.dev.json
19+
/public/hot
20+
/public/storage
21+
/storage/*.key
22+
/storage/pail
23+
/vendor
24+
_ide_helper.php
25+
Homestead.json
26+
Homestead.yaml
27+
Thumbs.db

.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ignore-scripts=true
2+
audit=true

Dockerfile

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# syntax=docker/dockerfile:1
2+
FROM php:8.5-fpm-alpine AS base
3+
4+
# Install system dependencies and PHP extensions
5+
RUN apk --no-cache upgrade \
6+
&& apk add --no-cache \
7+
oniguruma-dev \
8+
libzip-dev \
9+
zip \
10+
unzip \
11+
&& docker-php-ext-install pdo pdo_mysql mbstring zip
12+
13+
WORKDIR /var/www/html
14+
15+
COPY docker/entrypoint.sh /entrypoint.sh
16+
RUN chmod +x /entrypoint.sh
17+
18+
ENTRYPOINT ["/entrypoint.sh"]
19+
CMD ["php-fpm"]
20+
21+
# ---------------------------------------------------------------------------
22+
# dev: Xdebug + full (dev) Composer dependencies, unoptimised autoloader.
23+
# Used by docker-compose for local development; the source tree is bind
24+
# mounted over this at runtime, so the COPY/composer install below just
25+
# make `docker build --target dev .` usable on its own too.
26+
# ---------------------------------------------------------------------------
27+
FROM base AS dev
28+
29+
RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS linux-headers \
30+
&& pecl install xdebug \
31+
&& docker-php-ext-enable xdebug \
32+
&& apk del .build-deps
33+
34+
COPY docker/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
35+
36+
COPY . .
37+
38+
RUN --mount=type=bind,from=composer:2,source=/usr/bin/composer,target=/usr/bin/composer \
39+
composer install --no-interaction --prefer-dist
40+
41+
RUN chown -R www-data:www-data storage bootstrap/cache
42+
43+
# ---------------------------------------------------------------------------
44+
# production (default target): no dev dependencies, optimized autoloader.
45+
# ---------------------------------------------------------------------------
46+
FROM base AS production
47+
48+
COPY . .
49+
50+
RUN --mount=type=bind,from=composer:2,source=/usr/bin/composer,target=/usr/bin/composer \
51+
composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist
52+
53+
RUN chown -R www-data:www-data storage bootstrap/cache

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 DaySmart
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)