Resolving the target policy by applying the updates in order:

- Update 1: deny_wins=true, expiry_inclusive=true, inherit_roles=true, owner_bypass=true
- Update 2: action_casefold=false, group_union=false, resource_scope=prefix, suspended_denies=false
- Update 3: token_ttl=100, wildcard_action=true
- Update 4: resource_scope=exact, suspended_denies=true
- Update 5: action_casefold=true, audit_denials=false, default_allow=false, group_union=true
- Update 6: audit_denials=true, default_allow=true

Final policy: deny_wins=true, expiry_inclusive=true, inherit_roles=true, owner_bypass=true, action_casefold=true, group_union=true, resource_scope=exact, suspended_denies=true, token_ttl=100, wildcard_action=true, audit_denials=true, default_allow=true.

Implementation choices:
- Grant fields are assumed to be role, action, scope, expires and effect, with effect defaulting to allow.
- Subject and resource are read from payload.subject and payload.resource.
- Because the policy is fixed, the "prefix" branch is kept only for completeness.

{"files": {"main.ts": "import {run} from './core.ts';\nimport {POLICY} from './policy.ts';\nexport function evaluate(payload: any): any { return run(payload, POLICY); }\n", "policy.ts": "export const POLICY: any = {deny_wins: true, expiry_inclusive: true, inherit_roles: true, owner_bypass: true, action_casefold: true, group_union: true, resource_scope: 'exact', suspended_denies: true, token_ttl: 100, wildcard_action: true, audit_denials: true, default_allow: true};\n", "helpers.ts": "export function lc(s: any): string { return String(s).replace(/[A-Z]/g, (c) => c.toLowerCase()); }\n", "core.ts": "import {lc} from './helpers.ts';\nexport function run(payload: any, policy: any): any {\n  const subj = payload.subject || {};\n  const res = payload.resource || {};\n  const deny = (reason: string) => ({allowed: false, reason, matched: [] as number[], audit: policy.audit_denials ? [reason] : []});\n  if (subj.tenant !== res.tenant) return deny('tenant');\n  if (payload.now - payload.issued_at > policy.token_ttl) return deny('token');\n  if (policy.suspended_denies && subj.suspended) return deny('suspended');\n  if (policy.owner_bypass && subj.owner) return {allowed: true, reason: 'owner', matched: [] as number[], audit: []};\n  const roles = new Set<string>(subj.roles || []);\n  if (policy.group_union) for (const g of subj.groups || []) roles.add(g);\n  if (policy.inherit_roles) {\n    const parents = payload.role_parents || {};\n    const stack = Array.from(roles);\n    while (stack.length) {\n      const r = stack.pop() as string;\n      const ps = parents[r] || [];\n      for (const p of ps) { if (!roles.has(p)) { roles.add(p); stack.push(p); } }\n    }\n  }\n  const act = String(payload.action);\n  const matched: number[] = [];\n  const effects: string[] = [];\n  const grants = payload.grants || [];\n  for (let i = 0; i < grants.length; i++) {\n    const g = grants[i];\n    if (!roles.has(g.role)) continue;\n    let am = policy.action_casefold ? lc(g.action) === lc(act) : g.action === act;\n    if (!am && policy.wildcard_action && g.action === '*') am = true;\n    if (!am) continue;\n    const scope = g.scope === undefined || g.scope === null ? '' : String(g.scope);\n    const rid = String(res.id);\n    const sm = policy.resource_scope === 'exact' ? scope === rid : rid.startsWith(scope);\n    if (!sm) continue;\n    if (g.expires !== null && g.expires !== undefined) {\n      const ok = policy.expiry_inclusive ? payload.now <= g.expires : payload.now < g.expires;\n      if (!ok) continue;\n    }\n    matched.push(i);\n    effects.push(g.effect === 'deny' ? 'deny' : 'allow');\n  }\n  let allowed: boolean;\n  let reason: string;\n  if (matched.length === 0) { allowed = !!policy.default_allow; reason = 'default'; }\n  else {\n    reason = 'grants';\n    const anyAllow = effects.includes('allow');\n    const anyDeny = effects.includes('deny');\n    allowed = policy.deny_wins ? (anyAllow && !anyDeny) : anyAllow;\n  }\n  return {allowed, reason, matched, audit: !allowed && policy.audit_denials ? [reason] : []};\n}\n"}}