/**
 * B7 · Decode the browser's DPoP proof carried as an EXTRA WS subprotocol entry.
 *
 * A browser's native WebSocket API cannot set request headers, so relay-web offers the §4.3 DPoP
 * proof-of-possession JWS as an additional `Sec-WebSocket-Protocol` entry
 *   `term.dpop.<base64url(proofJws)>`
 * — mirroring how the capability token rides `term.token.<b64u>` (relay-contracts subprotocol.ts).
 * This is the relay-side inverse of relay-web `encodeDpopSubprotocol`; the wire format is decoded
 * byte-for-byte with the SAME isomorphic base64url helper both sides share (relay-contracts), so
 * issuance and verification can never drift.
 *
 * FAIL-CLOSED (INV15): an absent entry OR malformed base64url / non-UTF-8 payload → `null`, so the
 * downstream DPoP gate denies through the audited path instead of ever seeing a half-decoded proof.
 */
import { decodeBase64UrlString } from 'relay-contracts'

/** Subprotocol entry prefix carrying the DPoP proof (mirrors relay-web `DPOP_SUBPROTOCOL_PREFIX`). */
export const DPOP_SUBPROTOCOL_PREFIX = 'term.dpop.' as const

/**
 * Extract the DPoP proof JWS from a parsed subprotocol list: find the first `term.dpop.` entry,
 * strip the prefix, and base64url-decode the remainder. Returns `null` when the entry is absent,
 * empty, or does not decode (deny-by-default).
 */
export function extractDpopProofFromSubprotocols(values: readonly string[]): string | null {
  const entry = values.find((v) => v.startsWith(DPOP_SUBPROTOCOL_PREFIX))
  if (entry === undefined) return null
  const encoded = entry.slice(DPOP_SUBPROTOCOL_PREFIX.length)
  if (encoded.length === 0) return null
  try {
    const decoded = decodeBase64UrlString(encoded)
    return decoded.length > 0 ? decoded : null
  } catch {
    return null // fail-closed: malformed base64url or invalid UTF-8
  }
}
