Skip to content

Commit 306da2c

Browse files
committed
feat: Dash webhook receiver reference implementation
Public release of the reference PHP implementation for receiving and verifying Dash webhook deliveries: signature verification, JWKS caching, and the validation handshake endpoint. Release-As: 0.1.0
0 parents  commit 306da2c

74 files changed

Lines changed: 12770 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.

.dockerignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
\.env
2+
\.env.*
3+
!.env.example
4+
5+
.git
6+
.github
7+
.idea
8+
.claude
9+
.vscode
10+
.nova
11+
.zed
12+
.codex
13+
.cursor
14+
15+
docker
16+
docker-compose*.yml
17+
18+
node_modules
19+
vendor
20+
21+
tests
22+
.phpunit.result.cache
23+
.phpunit.cache
24+
25+
storage/framework/cache/*
26+
storage/framework/sessions/*
27+
storage/framework/testing/*
28+
storage/framework/views/*
29+
storage/logs/*
30+
!storage/framework/cache/.gitignore
31+
!storage/framework/sessions/.gitignore
32+
!storage/framework/testing/.gitignore
33+
!storage/framework/views/.gitignore
34+
!storage/logs/.gitignore
35+
36+
*.md
37+
LICENSE

.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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
# --- Webhook Receiver settings ---
42+
43+
# URL of the sender's JWKS endpoint (required for signature verification)
44+
WEBHOOK_SENDER_JWKS_URL=
45+
46+
# The WebHook-Request-Origin value to allow — a hostname (e.g. api.example.com),
47+
# not a URL. Use * to allow any origin.
48+
WEBHOOK_SENDER_ORIGIN=*
49+
50+
# Rate limit to advertise in the validation handshake (requests/minute)
51+
WEBHOOK_ALLOWED_RATE=1000
52+
53+
# Acceptable clock drift in seconds for the RFC 9421 'created' parameter
54+
WEBHOOK_REPLAY_WINDOW=300
55+
56+
# Optional shared Bearer secret for secondary authenticity check
57+
WEBHOOK_SECRET=
58+
59+
# How long to cache the sender's JWKS (seconds)
60+
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: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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.5'
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
51+
52+
docker-build:
53+
name: Docker build
54+
runs-on: ubuntu-latest
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Set up Docker Buildx
59+
uses: docker/setup-buildx-action@v3
60+
61+
- name: Build production target
62+
uses: docker/build-push-action@v6
63+
with:
64+
context: .
65+
target: production
66+
push: false
67+
cache-from: type=gha
68+
cache-to: type=gha,mode=max
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
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Release Please
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-please:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: googleapis/release-please-action@v4
17+
with:
18+
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
19+
config-file: release-please-config.json
20+
manifest-file: .release-please-manifest.json

.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

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.0.0"
3+
}

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

0 commit comments

Comments
 (0)