ruvnet/ruflo · error · TypeError

Unsupported federation authorization mode: ${String(mode)}

Error message

Unsupported federation authorization mode: ${String(mode)}

What it means

createFederationClaimChecker() accepts exactly three authorization modes: 'legacy' (the default when mode is omitted), 'observe', and 'enforce'. Any other value throws a TypeError at construction time, before any claim is evaluated. This is a programmer/config error, not a runtime data condition.

Source

Thrown at v3/@claude-flow/plugin-agent-federation/src/application/claim-checker.ts:45

/**
 * Compatibility bridge for the legacy federation policy engine.
 *
 * This removes the anonymous `() => true` production stub and makes
 * compatibility behavior explicit:
 * - legacy: preserve pre-ADR-325 behavior;
 * - observe: calculate and report missing grants without blocking;
 * - enforce: default deny unless the exact claim is configured.
 *
 * ADR-324 policy adapters can supply the `grantedClaims` set after evaluating
 * the request; ownership-changing federation messages remain disabled in the
 * default message policy until the full ingress PEP is composed.
 */
export function createFederationClaimChecker(
  config: FederationClaimCheckerConfig = {},
): FederationClaimChecker {
  const mode = config.mode ?? 'legacy';
  if (mode !== 'legacy' && mode !== 'observe' && mode !== 'enforce') {
    throw new TypeError(`Unsupported federation authorization mode: ${String(mode)}`);
  }

  const grantedClaims = new Set<FederationClaimType>();
  for (const claim of config.grantedClaims ?? []) {
    if (!FEDERATION_CLAIMS.has(claim as FederationClaimType)) {
      throw new TypeError(`Unknown federation claim: ${claim}`);
    }
    grantedClaims.add(claim as FederationClaimType);
  }

  return {
    mode,
    grantedClaims,
    checkClaim: (claim) => {
      const granted = grantedClaims.has(claim);
      if (mode === 'observe') config.onObservation?.(claim, granted);
      return mode !== 'enforce' || granted;
    },

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Use exactly one of the literals 'legacy', 'observe', or 'enforce'
  2. If mode comes from env/config, trim and lowercase it, then validate against the allowed set before constructing
  3. Type the config field as the union 'legacy' | 'observe' | 'enforce' so TypeScript rejects bad literals at compile time
  4. Align package versions if the mode name genuinely exists in a newer release

Example fix

// before
createFederationClaimChecker({ mode: 'Enforce' as any });
// after
const mode = 'enforce' as const;
createFederationClaimChecker({ mode });
Defensive patterns

Strategy: type-guard

Validate before calling

const MODES = ['legacy', 'observe', 'enforce'] as const;
const raw = (config.mode ?? 'legacy').toString().trim().toLowerCase();
const mode = (MODES as readonly string[]).includes(raw)
  ? (raw as (typeof MODES)[number])
  : 'legacy';
createFederationClaimChecker({ ...config, mode });

Type guard

type FederationAuthMode = 'legacy' | 'observe' | 'enforce';
function isFederationAuthMode(m: unknown): m is FederationAuthMode {
  return m === 'legacy' || m === 'observe' || m === 'enforce';
}

Prevention

When it happens

Trigger: Typos such as 'enforced' or 'stric'; wrong casing like 'Enforce'; mode strings sourced from env vars or config files with trailing whitespace; mode names from a newer package version passed to an older one.

Common situations: Env-var-driven policy configuration without normalization; configs copied from documentation of a different release; ADR-324 adapters emitting their own mode vocabulary.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/acee9085d66c2e00. Report an issue: GitHub.