authenticate

authenticate(resolver: (exchange: Exchange<Current>) => PrincipalClaims | undefined | Promise<PrincipalClaims | undefined>): RouteBuilder<Current>

Establish the authenticated principal for the exchange. The resolver returns identity claims you have verified yourself (an e-mail sender, a Slack signature, a webhook HMAC); they are minted into a branded, frozen Principal and attached to headers["routecraft.auth.principal"]. Return undefined to leave the caller anonymous. The body is unchanged.

This is the explicit way to establish identity from a source the framework cannot verify on its own. authorize() trusts only principals minted this way (or attached by a source verifier such as jwt() / jwks() / oauth()); a plain object written via .header('routecraft.auth.principal', ...) or .process() is rejected with RC5023. Sugar over the authenticate() helper, which you can call directly in tests, custom source adapters, or a .choice() branch.

Only subject is required; kind defaults to "custom" and scheme to "custom".

.authenticate() establishes identification: who the caller is. It answers nothing about delegation. When an agent should act on the authenticated caller's behalf, follow it with .delegate(), which marks the actor and narrows scopes under a consent record; minting a principal from a channel identifier alone and handing it to an agent gives the agent the caller's full authority with no consent trail.

// Mint identity from a verified inbound email, then authorize it
craft()
  .from(mail('INBOX'))
  .filter(verifiedSenders)
  .authenticate((ex) => {
    // The mail source attaches the computed sender to a header.
    const sender = ex.headers['routecraft.mail.sender']
    return {
      scheme: 'email',
      subject: sender.address,
      roles: sender.address.endsWith('@acme.com') ? ['internal'] : [],
    }
  })
  .authorize({ roles: ['internal'] })
  .to(dest)

// Return undefined to stay anonymous
.authenticate((ex) => {
  const sender = ex.headers['routecraft.mail.sender']
  return sender ? { subject: sender.address } : undefined
})