Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/24900-webhook-label-description-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@objectstack/spec': patch
---

fix(spec): `os lint` no longer tells authors to remove a declared webhook's `label` or `description`

Clause-②: no (a liveness-ledger re-grade: no schema, accept set, served body or error code moves; only the advisory `liveness-dead-property` warning on these two keys stops)

The shipped liveness ledger (`liveness/webhook.json`) graded a declared webhook's `label` and `description` `dead` once the boot seeder that copied them into a `sys_webhook` row retired, and the advisory lint warned "Remove it" on every webhook that authored them. They are read: the Studio metadata list and quick-find show both keys, read off `GET /api/v1/meta/webhook`. Both rows are now `live`, so a declared webhook may keep its `label` and `description` and no warning is printed for them. Nothing else changes: the dispatcher still delivers on the same props as before.
2 changes: 1 addition & 1 deletion docs/qa/platform-checklist/areas/integration-system.json
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@
],
"source": [
"packages/spec/src/automation/webhook.zod.ts#WebhookTriggerType (WebhookTriggerType enum + why undelete/api are absent; materialization contract; strict shape #4001)",
"packages/spec/liveness/webhook.json (9 props live on the registry read; label/description dead since the boot seeder retired)",
"packages/spec/liveness/webhook.json (9 props live on the registry read; label/description live on the Studio metadata list and quick-find, which read the declared item over GET /api/v1/meta/webhook)",
"packages/plugins/plugin-webhooks/src/declared-webhooks.ts + auto-enqueuer.ts (the registry read and its remaps; trigger→event mapping incl. the #4639 bulk pair; #3196 unknown-trigger warn; the activation-ledger switch; an 18.0 database's seeded rows read beside the declaration)",
"packages/services/service-messaging/src/http-outbox.ts#HttpRedeliverError (delivery statuses, attempts; HttpRedeliverError + assertHttpRedeliverable/assertRedeliverAllowed — terminal-only, the attempts===0 parked-row refusal, the fail-closed guard) + packages/services/service-messaging/src/http-signature-at-rest.integration.test.ts (redelivery replays the stored signature byte-for-byte)",
"packages/plugins/plugin-webhooks/src/webhook-outbox-plugin.ts#session (POST /api/v1/webhooks/redeliver — session auth with NO capability gate by design ('every authenticated user counts'), #10740 activeOrganizationId threading, the 401/400/404/409/500 arms) + (the #8069 redeliver-guard install; its ABSENCE is an error-level log, not a silent pass)",
Expand Down
6 changes: 4 additions & 2 deletions examples/app-showcase/src/automation/webhooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { defineWebhook } from '@objectstack/spec/automation';

/**
* Outbound webhook — fans out task lifecycle events (create/update/delete)
* to an external endpoint. No `label` / `description`: a declared webhook has
* no Setup row to show them on, and the liveness ledger marks both dead.
* to an external endpoint. A declared webhook has no Setup row, but a `label` /
* `description` authored here is not inert: the liveness ledger grades both
* `live`, because the Studio metadata list and quick-find show them, read off
* `GET /api/v1/meta/webhook`.
* Authored via `defineStack({ webhooks })`; the webhooks plugin's dispatcher
* reads this declaration from the registry (ADR-0131 D2) — no `sys_webhook`
* row is written for it.
Expand Down
20 changes: 7 additions & 13 deletions packages/lint/src/lint-liveness-properties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,13 @@ describe('lintLivenessProperties', () => {
// #3494 PRUNED the aspirational dead props from the schema and the #3489
// materializer bridge made every remaining prop live. ADR-0131 D2 then
// retired that bridge: a declared webhook is read from the registry and has
// no Setup row, so the two display-only props, `label` and `description`,
// lost their only reader and the ledger marks them dead. Every delivery-
// bearing prop stays silent. Runs against the REAL webhook.json, so a ledger
// flip that is not carried to authors fails here.
// no Setup row. The two display-only props, `label` and `description`, stay
// live all the same: the Studio metadata list and quick-find draw them off
// `GET /api/v1/meta/webhook`, so the ledger grades them live and nothing
// warns. Runs against the REAL webhook.json, so a ledger flip that is not
// carried to authors fails here.

it('warns on a declared webhook\'s label and description only — every delivery-bearing prop is live', () => {
it('stays silent on a declared webhook that authors every prop, label and description included', () => {
const findings = lintLivenessProperties({
webhooks: [{
name: 'showcase_task_changed',
Expand All @@ -272,14 +273,7 @@ describe('lintLivenessProperties', () => {
description: 'Sends task lifecycle events to an external system.',
}],
});
expect(findings.map((f) => [f.rule, f.message.match(/`(\w+)`/)?.[1]])).toEqual([
['liveness-dead-property', 'label'],
['liveness-dead-property', 'description'],
]);
for (const f of findings) {
expect(f.where).toBe("webhook 'showcase_task_changed'");
expect(f.hint).toContain('no Setup row');
}
expect(findings).toEqual([]);
});

it('stays silent on a declared webhook that authors only what is delivered on', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/spec/liveness/state-counts/webhook.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ committed anywhere: `check:liveness` sums the shards when it reads them.

| Type | live | exp | elsewhere | dead | planned | classified |
|---|---|---|---|---|---|---|
| `webhook` | 17 | 0 | 0 | 2 | 0 | 19 |
| `webhook` | 19 | 0 | 0 | 0 | 0 | 19 |
Loading
Loading