Skip to content

Keep a webhook trigger's auth when an update spec leaves it out - #95

Merged
2 commits merged into
mainfrom
bug/webhook-auth-reset-on-update
Oct 27, 2026
Merged

2 commits merged into
mainfrom
bug/webhook-auth-reset-on-update

Conversation

@jbedient-kizen

@jbedient-kizen jbedient-kizen commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Since Kizen's 2026-10-26 release a webhook trigger carries auth_type, headers and secret. A PUT whose webhook block leaves out auth_type resets the trigger to Kizen API auth and drops its headers or secret. Every spec written before the release leaves it out, so automations update from such a spec silently switched header, basic and no-auth webhooks back to Kizen API auth, and changed their ?business_id= URLs under external callers, who then got 401s. diff showed the reset, and also showed a spec restating the live auth as a change, because the read shape of secret and the empty html_value didn't match the write shape.

Solution

_merge_server_state now carries the live trigger's auth across when a spec's webhook block has no auth_type, the same way an omitted active keeps its live value. Triggers match by id, then by webhook name, and a spec that sets auth_type (any value) is sent as written. One reduction, _webhook_auth, serves the builder, the GET→PUT read path and the carry-over, so diff compares like with like.

TriggerWebhookConfig types auth_type, headers and secret, and refuses headers on a non-http_header trigger and secret on a non-basic_auth one, which Kizen drops without a word. It also refuses the retired auth_header_* keys, pointing at headers. Each header gets the html_value mirror the UI writes, labelling an {{ integration_secret.x }} reference with the secret's description; that needs a single read of /api/integration-secrets per plan, keeping only api_name → description. automations get gains an auth column. kizen docs show automation has a webhook-auth section with the enforcement rules seen live.

Testing

Local checks after merging main: lint, format, typecheck, pytest (2855 passed, 4 skipped, 1 xfailed) and the CLI-tree diff, passed: lint format typecheck test extra_checks. With the carry-over call removed, the omitted-auth, by-name and omitted-diff tests fail.

Live on a test tenant, with a scratch automation holding all four auth types: create stored the derived html_value; diff against a spec omitting auth and one restating it showed no auth lines; update from a spec with no auth and no ids kept every trigger's auth, headers, secret and URL; an explicit auth_type: kizen_api was applied; roundtrip --execute reported drift: []. On a UI-built automation (read only), the derived html_value matched the UI's byte for byte. New drift test test_active_preserved_on_update.py -k webhook and test_roundtrip_automations.py -k wired_trigger_type pass. The full drift tier has 4 failures, all also failing on main: its schema snapshot predates the 2026-10-26 release.

Design notes / tradeoffs

Keep-live over two alternatives. Refusing the plan when live auth exists and the spec omits it would reject every spec written before the release. Checking client-side the rules the server already rejects with a precise 400 would duplicate them; the model checks only what the server drops silently. The cost of keep-live: turning auth off takes an explicit auth_type: kizen_api or none.

A literal header value is accepted by Kizen and stored in plain text, so the docs steer to a secret reference.

The integration-secret lookup is a hand-rolled lazy cache on LiveContext. #99 (the Call LLM MCP-server fix) adds a generic lazy step-picker cache there; once both are on main, this lookup could move onto it.

Overlaps: #96 (the loops fix) and #99 (the Call LLM MCP-server fix) also change tools/planners/automations.py, docs/specs/automation.md and CHANGELOG.md; #100 (the mcp-servers command group) and #101 (the service-accounts command group) also add lines to the CONTRIBUTING.md source tree. The second of these to merge should need a small conflict fix. The merge from main also refreshes scripts/cli-tree-baseline.txt for #92's new kizen upgrade --check help text, which main's baseline lacks; every PR in this set carries that same line, so they don't conflict on it.

Since Kizen's 2026-10-26 release a webhook trigger carries auth_type,
headers and secret, and a PUT without auth_type resets the trigger to
Kizen API auth, which also changes its URL under external callers.
Every spec written before the release omits the key, so an update now
carries the live trigger's auth across, matched by trigger id and then
by webhook name. Setting auth_type still changes it.

Specs can now set all four auth types. The model refuses headers or
secret on a type Kizen silently drops them for, and the retired
auth_header_* keys. Headers get the same html_value the UI writes,
labelling a secret reference with the secret's description, and
automations get shows each webhook's auth type.
@jbedient-kizen

Copy link
Copy Markdown
Contributor Author

Included in the 0.4.0 release PR #102; merge that instead.

@sangyeT sangyeT left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the typed webhook auth models, the server-state carry-over in _carry_webhook_auth (matched by trigger id, then webhook name), the validator for Kizen's silently-dropped combinations, and the html_value mirror. Unit coverage against the four-auth-type fixture plus the drift guard look thorough. Approving.

@jbedient-kizen jbedient-kizen closed this pull request by merging all changes into main in 39beea1 Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants