#!/usr/bin/env python3
"""Add compact attack-path closure records to the validated ledger."""

from __future__ import annotations

import json
import os
from pathlib import Path


LEDGER = Path(
    "/private/var/folders/kx/8xhl68dn107bzv0r4bc6l7dr0000gn/T/"
    "codex-security-scans-QM6XF1/ai_api/"
    "a782c32b3a1c823e4f803ca07137187fbd2d32cb_20260729T024025Z_zco_cdqv/"
    "artifacts/02_discovery/candidate_ledger.jsonl"
)

HIGH = {
    "baidu-face-empty-allowlist",
    "zhaiker-forged-exam-callback",
    "tracked-environment-and-sql-credentials",
    "bank-bind-user-login-token-mint",
    "bank-user-id-account-switch",
    "terminal-face-sync-without-device-auth",
    "terminal-role-authorization-disabled",
    "healthkit-token-logging",
}

DEFERRED = {
    "zhaiker-concurrent-duplicate-import",
    "unknown-host-default-tenant",
    "unknown-platform-client-gate-bypass",
}

DATAFLOW = {
    "baidu-face-empty-allowlist": "HTTP face route -> empty allowlist -> allow-all branch -> local biometric SDK operation -> biometric result or mutation",
    "zhaiker-forged-exam-callback": "unsigned HTTP payload -> callback normalization -> attacker-selected customerId -> measurement and health writes -> weight/profile synchronization",
    "tracked-environment-and-sql-credentials": "tracked environment or SQL file -> repository clone/checkout -> credential disclosure to any repository reader",
    "bank-bind-user-login-token-mint": "public bank binding request -> caller-selected identity fields -> staff attribute match -> relation write -> application bearer token",
    "bank-user-id-account-switch": "public bank user ID -> linked-user enumeration -> caller-selected linked user -> application bearer token",
    "terminal-face-sync-without-device-auth": "whitelisted terminal request -> caller-supplied device/store identifiers -> face sync query -> biometric metadata response and sync-state update",
    "terminal-role-authorization-disabled": "low-privilege terminal login -> automatic controller route -> no-op privilege check -> administrator or refund mutation",
    "healthkit-token-logging": "OAuth callback -> vendor token response -> token array -> application log",
    "healthkit-oauth-state-unbound": "attacker-selected OAuth state/code -> logged-in callback -> syntactic state check only -> token stored under victim application account",
    "prepay-concurrent-orphan-orders": "concurrent authenticated scans -> unlocked prepay read -> duplicate order inserts -> one failed link update ignored -> orphan payable order",
    "refund-order-goods-horizontal-bypass": "same-store orderGoodsId -> ownerless goods lookup -> attacker refund row -> merchant approval path -> victim order refund",
    "anonymous-image-upload": "anonymous automatic route -> omitted flag -> login disabled -> file storage and metadata write",
    "zhaiker-concurrent-duplicate-import": "concurrent identical callbacks -> pre-transaction duplicate reads -> duplicate session and health inserts",
    "unknown-host-default-tenant": "alternate Host or direct IP -> fixed tenant fallback -> normal API processing under tenant 10001",
    "unknown-platform-client-gate-bypass": "missing or unknown platform header -> fail-open client check -> disabled client API action continues",
}

REACHABILITY = {
    "baidu-face-empty-allowlist": "A network caller needs the API route to be reachable while allowed_ips is missing or empty; no login is required by repository controls.",
    "zhaiker-forged-exam-callback": "A network caller that reaches the callback can submit an arbitrary numeric user ID; an existing ID expands impact to profile and reward mutation.",
    "tracked-environment-and-sql-credentials": "Any person or automation able to read the Codeup repository, local clone, archive, or derived artifact can obtain the committed material.",
    "bank-bind-user-login-token-mint": "An unauthenticated caller needs a valid staff name, personnel number, and school selector; the endpoint itself performs no bank-session ownership proof.",
    "bank-user-id-account-switch": "An unauthenticated caller needs a bank user identifier; the first endpoint enumerates linked application users and the second returns a token.",
    "terminal-face-sync-without-device-auth": "A caller needs a device identifier and matching store context; repository code requires no device credential or request signature.",
    "terminal-role-authorization-disabled": "Any authenticated terminal merchant user can call role-restricted endpoints directly because the permission decision is disabled.",
    "healthkit-token-logging": "A reader of application logs can recover reusable health credentials after a successful OAuth callback.",
    "healthkit-oauth-state-unbound": "An attacker must induce a logged-in victim to complete a callback using an attacker-originated Huawei authorization.",
    "prepay-concurrent-orphan-orders": "An authenticated user can replay or race the scan request for one waiting prepay row.",
    "refund-order-goods-horizontal-bypass": "An ordinary API user needs a same-store order-goods ID; final payment reversal additionally requires merchant approval.",
    "anonymous-image-upload": "Any network caller that can reach the API automatic route can upload repeated extension-approved files without a login.",
    "zhaiker-concurrent-duplicate-import": "A caller must deliver identical callbacks concurrently and the production table must lack a protective unique constraint.",
    "unknown-host-default-tenant": "The path requires a proxy or virtual host that forwards an unmapped Host or direct-IP request to this application.",
    "unknown-platform-client-gate-bypass": "A caller with the endpoint's normal prerequisites can omit or spoof the platform value.",
}

CHANGE_CONDITIONS = {
    "baidu-face-empty-allowlist": "Lower if production startup rejects an empty allowlist and ingress is independently restricted; raise if the route is publicly reachable with the default.",
    "zhaiker-forged-exam-callback": "Lower if a verified upstream gateway authenticates and signs every callback; raise if the route is Internet reachable.",
    "tracked-environment-and-sql-credentials": "Lower after all values are proven inactive and rotated; raise if any credential is active with production or cross-tenant privilege.",
    "bank-bind-user-login-token-mint": "Lower if an independently verified gateway binds the request to the same bank identity; raise if directly Internet reachable.",
    "bank-user-id-account-switch": "Lower if identifiers are unguessable and gateway ownership is enforced; raise if identifiers are exposed through clients or logs.",
    "terminal-face-sync-without-device-auth": "Lower if the endpoint is mutually authenticated at ingress; raise if device IDs are enumerable or exposed.",
    "terminal-role-authorization-disabled": "Lower only if an external authorizer enforces the same route-level permissions; raise if low-privilege terminal accounts are broadly issued.",
    "healthkit-token-logging": "Lower if production logging redacts the array before storage; raise if logs are broadly accessible or tokens have broad/long-lived scope.",
    "healthkit-oauth-state-unbound": "Raise with a browser PoC demonstrating account misbinding; lower if a verified external component issues and consumes a session-bound state before this controller.",
    "prepay-concurrent-orphan-orders": "Raise if duplicate payable orders can cause repeated settlement or fulfillment; lower if a database constraint atomically rejects and rolls back the losing insert.",
    "refund-order-goods-horizontal-bypass": "Raise if approval is automatic or attacker-controlled; lower if merchant review reliably verifies ownership before any refund.",
    "anonymous-image-upload": "Raise if public storage is billable/executable or has no global quota; lower if anonymous upload is intentional and protected by strict gateway quotas.",
    "zhaiker-concurrent-duplicate-import": "Report after schema evidence confirms no unique constraint and a concurrent test reproduces duplicate commits.",
    "unknown-host-default-tenant": "Report after an authorized alternate-Host request reaches the application and performs default-tenant processing.",
    "unknown-platform-client-gate-bypass": "Report if product owners confirm the enable flag must disable all client access; lower to hardening if unknown clients are intentionally supported.",
}


def main() -> None:
    rows = [
        json.loads(line)
        for line in LEDGER.read_text(encoding="utf-8").splitlines()
        if line.strip()
    ]
    for row in rows:
        instance = row["instance"]
        deferred = instance in DEFERRED
        severity = "high" if instance in HIGH else "medium"
        impact = "high" if instance in HIGH else "medium"
        likelihood = "medium"
        if instance in {
            "terminal-role-authorization-disabled",
            "tracked-environment-and-sql-credentials",
            "healthkit-token-logging",
            "anonymous-image-upload",
        }:
            likelihood = "high"
        row["attack_path"] = {
            "decision": "deferred" if deferred else "reportable",
            "dataflow": DATAFLOW[instance],
            "reachability": REACHABILITY[instance],
            "counterevidence": row["validation"]["counterevidence_or_proof_gap"],
            "impact": impact,
            "likelihood": likelihood,
            "severity": severity,
            "severity_rationale": (
                f"The repository trace crosses a defined trust boundary and supports {impact} impact with {likelihood} likelihood under the stated prerequisites."
            ),
            "change_conditions": CHANGE_CONDITIONS[instance],
        }
        if deferred:
            row["attack_path"]["proof_gap"] = row["validation"]["remaining_uncertainty"]

    tmp = LEDGER.with_suffix(".jsonl.tmp")
    with tmp.open("w", encoding="utf-8") as handle:
        for row in rows:
            handle.write(json.dumps(row, ensure_ascii=False, sort_keys=True) + "\n")
    os.replace(tmp, LEDGER)


if __name__ == "__main__":
    main()
