/**
 * L1 authn — Zitadel JWT (@mesh-tech/authn).
 *
 * `projectId` (the app's own Zitadel project id / token audience) is passed so
 * the scheme reads the PROJECT-ID-KEYED roles claim
 * (`urn:zitadel:iam:org:project:${projectId}:roles`) that machine
 * (client-credentials / API-key) tokens actually carry — the generic claim is
 * empty for those, so wiring the wrong key silently 403s every gated route.
 * Fails closed when unconfigured.
 */
import { createAuthn, type Authn, type AuthnScheme } from "@mesh-tech/authn";
import { zitadelJwtScheme } from "@mesh-tech/authn/schemes/zitadel-jwt";

export const createAuthnFromEnv = (env: NodeJS.ProcessEnv = process.env): Authn | undefined => {
  const schemes: Record<string, AuthnScheme> = {};
  if (env.ZITADEL_ISSUER) {
    const audience = env.ZITADEL_AUDIENCE ?? env.ZITADEL_PROJECT_ID;
    if (!audience) throw new Error("{{name}} authn: ZITADEL_ISSUER set but no ZITADEL_PROJECT_ID/ZITADEL_AUDIENCE");
    // The app knows its own project id (== audience here); let the scheme derive
    // the exact project-scoped roles claim from it.
    const projectId = env.ZITADEL_PROJECT_ID ?? audience;
    schemes["zitadel-jwt"] = zitadelJwtScheme({
      issuer: env.ZITADEL_ISSUER,
      audience,
      projectId,
    });
  }
  return Object.keys(schemes).length > 0 ? createAuthn({ schemes }) : undefined;
};
