Hooks and origin routing
defineHooks(name, register) is where your identity vendor gets named — once,
in one file, outside every workflow. It registers the provider, optionally how
to resolve recipients, and any HTTP webhooks.
This runs at host startup, never during workflow replay. That’s the point: none of it is recorded in an event stream, so you can change it without invalidating runs that are already in flight.
Gate G3 — package publication. The API is current and stable. The published package and the starter’s hook file are still being finished.
Use siam as the provider ID everywhere in the workshop.
Registration supplies a principals(account) lookup: given a verified account,
return the principals it has. The provider decides what its subjects and
membership keys mean. IdentityFlow stores them and compares them; it never
parses them.
Which provider handles a given login is decided by the OIDC origin. The mapping
lives in identity.originProviders[auth.oidc.origin] in your host
configuration.
Test it against your local issuer before anyone opens a browser — this is the step people skip and then spend an hour on.
An origin is a routing input, not a substitute for the provider ID. The config parser rejects an origin that maps to nothing, rather than guessing.
Keep these apart in your head: the verified account is who logged in; the principal is who a workflow addresses.
They are different things and the engine treats them differently. When you’re asserting who can see or complete a step, you’re asking about principals.
The local source-change webhook is authenticated, validated, and turned into a command with an idempotency key.
The receiver records the event before applying the change, so a retry produces the same result instead of a second change. Webhook handlers never run as a side effect of replay.
See Assignee Sources for the resolver and Audit Evidence for what to keep when membership changes.