Repository navigation
Releases: goldnead/statamic-webhook-manager
Release list
2.11.0
Changed
- Settings: the addon now declares
settingsNavParent()([section, name]of its own Control Panel navigation entry). With statamic-brand-context 1.16 or newer its settings show as the sub-item "Einstellungen" under that entry; addons without a navigation of their own share one "Addon-Suite" page under Settings. Older brand-context versions ignore the method and keep the previous layout. - The addon no longer registers its own settings sub-item under its navigation entry; statamic-brand-context 1.16 adds it. With an older statamic-brand-context the sub-item is gone, so update that package to 1.16 or newer together with this one.
Upgrading
- No migration, no new config key. Update
goldnead/statamic-brand-contextto 1.16 or newer.
2.10.0
Upgrading
- No migration, no new config key.
- Published language files: if you ran
vendor:publish --tag=webhook-manager-langbefore,
publish again with--force(or merge by hand). Trigger labels now read "Group: moment"
("Eintrag: gespeichert" instead of "Eintrag — gespeichert"), and the new group headings and
subject-type labels live there; an old copy keeps the old strings. - A new webhook or rule starts without a trigger, and the field is required. Nothing is
preselected any more; existing hooks keep theirs. - Outbound requests now carry
X-Webhook-Id, and with the hook's Idempotency switch on also
Idempotency-Key. A receiver that rejects unknown headers needs to accept them; a header of the
same name configured on the hook wins. - Suite addons register their moments here as triggers from statamic-payments 1.26,
statamic-invoices 2.3, statamic-offers 1.13, statamic-courses 0.3, statamic-funnels 1.18 and
statamic-affiliates 0.2 on.
Added: the trigger picker is grouped and searchable
Six suite addons now register their moments as triggers, and the picker was one flat list of
sixty entries sorted by handle. It is now core's searchable Combobox, grouped by the trigger's
source_type (Einträge, Zahlungen, Kurse …) with the groups sorted by heading and the triggers by
label. Search matches label, group heading and handle. Group headings come from
webhook-manager::messages.trigger_groups.<source_type>; a type without a translation takes the
prefix its labels share, else its handle. Core's Combobox has no option groups, so the headings
are rows that cannot become the value. Outbound webhooks and rules both use it
(TriggerRegistry::groupedOptions(), prop triggerChoices).
Changed: a new webhook or rule starts without a trigger
The form preselected the first trigger of the list, which made "Partner: Provision verdient" the
default of every new hook. The field now starts empty and stays required.
Changed: one label form for triggers, "Gruppe: Moment"
The built-in labels read "Eintrag — gespeichert" next to the suite's "Zahlungen: Zahlung
eingegangen". They now read "Eintrag: gespeichert", "Formular: abgeschickt", "Benutzer:
gespeichert" (was "Benutzer:in"), "Datei: gespeichert"; in English "Entry: saved" and so on.
Sites with published language files keep their old strings until they re-publish.
Added: outbound requests carry the idempotency key
The key was computed and stored on the delivery row but never sent. Every outbound request now
carries X-Webhook-Id, and with the hook's Idempotency switch on also Idempotency-Key; a
header of the same name configured on the hook wins. When the payload has an event_id
(string or integer, at most 128 characters) that is the key, so the same event keeps its key
across dispatches. Retries and snapshot replays resend the first value. See the README section
"Idempotency headers on outbound deliveries".
Fixed: subject types from the suite had no label
The "Objekt" column showed ucfirst() of types it did not know: "Commission" in a German CP,
"Seat_pool" with its underscore. subscription, invoice, commission, partner, course, seat,
seat_pool and coupon now have German and English labels, and a type nobody translated shows its
handle unchanged.
Fixed: settings labels printed their keys after an early settings read
Since brand-context 1.14 SettingsRegistry::register() catches up on stored settings at once and
reads every settings label. bootAddon() registered the settings before it loaded its own
translation namespace, so that read cached the settings group as empty for the current locale.
In a normal Statamic boot the addon's translations are loaded earlier and hid this; the test bed
(and any host that calls bootAddon() itself) did not. Translations now load first.
Chore: PHPStan tolerates both Statamic docblocks for $vite
Statamic 6.34 corrected the AddonServiceProvider::$vite docblock, which made the baseline
entry for it unmatched in CI (latest dependencies) while it still matches locally (lock). The
entry moved to phpstan.neon with reportUnmatched: false.
2.9.3
Fixed: der Kopier-Knopf in der Inbound-Tabelle zentrierte sich selbst
Der Standard-text-align eines <button> ist center. In der Pfad-Spalte der
Inbound-Übersicht sass ein Icon-Kopierknopf ohne text-start, dieselbe fehlende Klasse wie bei
den Titel-Buttons in statamic-offers und statamic-products. Ohne sichtbare Auswirkung
bei einem einzeiligen Icon, aber derselbe Fehler, deshalb mitgenommen: text-start steht jetzt
explizit dabei.
2.9.2
Fixed: installierbar auf aktuellem Statamic 6
Das Paket verlangte inertiajs/inertia-laravel ^1.0|^2.0. Statamic 6.33.0 ist die erste
Version, die ^2.0 || ^3.0 erlaubt, und löst dort auf v3 auf — wer sie einsetzt, konnte dieses
Addon nicht mehr installieren.
Die Anforderung steht jetzt auf ^2.0 || ^3.0, wie in statamic-brand-context. Am Code war
nichts zu tun: Inertia::render, der Typ Inertia\Response und die Middleware verhalten sich
unter v3 unverändert. 431 Tests unter Inertia 3.3.4 grün.
Auf Statamic vor 6.33.0 ändert sich nichts, dort wird weiterhin Inertia 2 gezogen.
2.9.1
Fixed: the Insights screen was left out of the setup check in 2.9.0
The ninth screen went unnoticed because it builds its numbers through a stats service rather than
a repository. It now demands webhook_deliveries unconditionally — the delivery history is
database-backed under every storage driver — and webhook_outbounds only under the eloquent
driver, since the range picker and the "top failing" names read the hooks through the repository,
which is YAML under flat.
Fixed: the MySQL test leg, red since the setup check was written
SetupGuardTest reproduced the unmigrated install by dropping the addon's tables. On SQLite that
is harmless; MySQL commits DDL implicitly, so the drop escaped the RefreshDatabase transaction
and testbench's rollback at the end of the run met a down() that cannot alter a table which is
no longer there — Table 'webhook_manager_test.webhook_outbounds' doesn't exist, raised in
teardown rather than in an assertion. The test now points the default connection at an empty
in-memory database for the duration of the request instead, which needs no DDL at all and reads
the same on both engines. Nothing about the guard itself changed.
2.9.0
Changed: the Control Panel screens show an empty state instead of HTTP 500 when tables are missing
An installation that has the package but has never run its migrations answered HTTP 500 on every
screen of this addon: the nav item is there, the route resolves, and the first query throws
no such table: webhook_outbounds while the page is being built. All eight screens — overview,
outbound, inbound, rules, templates, deliveries, logs and debug — now check before their first query
and render a setup page that names the missing tables and says to run php artisan migrate.
Which tables a screen demands depends on the active storage driver. Outbound webhooks, inbound
endpoints, rules and templates live either in the database or in YAML files, so under the flat
driver those four tables are never queried and are not required — demanding them would send a
perfectly working installation to the setup screen. Deliveries and logs are database-only whatever
the driver says.
The reason does not vanish with the 500: a guarded page writes to the log why it turned somebody
away. Otherwise the install would look finished and never work.
2.8.2
Changed: goldnead/statamic-brand-context 1.13 or later
The shared settings screen this addon moved onto in 2.8.0 does not work reliably under older
versions. On an installation with a single brand, the values of the addons that registered last
were not laid over the config at all — when this was measured in the playground on 07.09.,
webhook-manager was one of them: after a reload the screen showed the saved value, while what
got read was the package default. Here that affects the retry policy, the delivery time limits
and the masking in the logs, among others. On top of that, up to 1.12 saving the same section a
second time deleted the first save's override, without a message, and adding a second field to
the same section is enough to trigger it.
Nothing changes about the screen, the migration step from 2.8.0 or the manage webhook settings
permission. If you set values between 06.09. and this update, check after updating whether they
are still there; lost values do not come back on their own.
Changed: the developer URL points to adriangoldner.dev
extra.statamic.developer-url still pointed at gldnr.studio. The publisher the Control Panel
shows on the addon, and Packagist on the package page, is now adriangoldner.dev, as with the
other addons in the suite.
2.8.1
Docs: the README still described the old settings screen
Follow-up to 2.8.0. The settings section still named webhook_settings, the
addon's own screen and "Settings → Storage". It now names the shared screen,
brand_settings, the brand scope, the migration step on upgrade, and the debug
screen as the new place for the deployment values and the storage driver
switch. Text only, no code.
2.8.0
The settings now live on the suite's shared screen
This addon had a settings screen of its own: a table, a model, a request, a
controller and a Vue page, together around 900 lines for a mechanism that
automations and leadhub had each built once more, independently of it. The
mechanism now lives once in goldnead/statamic-brand-context; what stays here
is only the field list (Support\Settings), which registers with the shared
registry in boot().
What changes for an operator:
- One screen for the whole suite. Every addon is a section on it. The
sidebar entry "Webhooks → Settings" still leads there, and
/cp/webhook-manager/settingsredirects — bookmarks stay valid. - Settings are brand-scoped from now on. On a multi-brand installation two
brands used to share one value, because the old table had no brand column. - Existing values move along.
php artisan migratetransfers every row
fromwebhook_settingstobrand_settingson the default brand. The old
table stays for one minor version, so a rollback loses nothing. - What was not a setting has moved to the debug screen: the values dictated
by the deployment, the resolved config tree with masked secrets, and the
switch for the storage driver. For that, the debug screen is now reachable
withmanage webhook settingsas well, not only with
use webhook debug tools— the debug tools themselves stay locked.
Fixed
- [fix] A saved status list silently switched retrying off. A text field returns
strings;RetryPlannercompared them strictly against a real HTTP status,
and"429"is never429. Two repairs: the planner converts the list to
integers when reading it — a hand-editedconfig/webhook-manager.phpcould
trigger this before as well —, and sincebrand-context1.12.0 the shared
layer knows a type per list item, whichsettingsGroups()declares here with
items => 'integer'. That also makes the list resettable to its package
default again; before, it stayed frozen after the first save, and a later
release could no longer move it.
2.7.0
The overview shows the webhooks themselves, not just four numbers
It used to hold four tiles and not a single row of the actual webhooks. The
page now carries the figures as a key/value table and below it the outgoing
webhooks as a real Statamic listing, with column headers, sorting, multi-select
and a "…" menu. The delivery listing was unusable — the URL column 60 px wide,
every row just "…" — and is no longer.
Fixed: two holes in the action endpoints
- [fix] A selection that collapsed to zero records server-side (a stale page, a
deleted row, a brand switch) made core run over the global action list of
all installed addons and ended in HTTP 500 with a stack trace. The
endpoint now answers with an empty list, or a 404, before core is asked. - [fix] An action of the wrong type ran through and reported success — an outgoing
webhook could be run as "Resend delivery".visibleTo()is only a guard for
the interface; when executing, Statamic checksauthorize()and nothing
else. All five CP actions now check the type there, and every endpoint
accepts only its own actions.
The Control Panel speaks German throughout
357 strings sat in the code as global translation keys. Global means a sibling
addon can redefine them — the delivery detail page was titled "Versand #266"
because another addon binds Delivery to "Versand". Everything now lives under
webhook-manager::messages.*. A test holds the state: it also catches
trans_choice, double quotes, config/ and calls with a variable key.
Smaller things
- The error type on the log page had never resolved: the server looked it up in
the delivery failure classes, while the column carries log event types. Its
own vocabulary with 26 event types; the column is now called "Event". - Removed checkbox columns that had no effect at all on four listings.
- One word per thing: the German interface says "Zustellung", no longer also
"Auslieferung".