CoolFace
Apppublic

GodsDevProject/FOIA_Doc_Search

sourceHugging Facemitupdated 9mo agoView on Hugging Face
1likes
app.py256 linesDownload Raw Back to root
1# ======================================================2# Federal FOIA Intelligence Search3# HF Reviewer–Safe / Court-Safe Reference Implementation4# ======================================================5 6import os7import io8import zipfile9import tempfile10import hashlib11from datetime import datetime12from urllib.parse import quote_plus13 14import gradio as gr15 16# ======================================================17# HARD GOVERNANCE FLAGS18# ======================================================19 20ENABLE_AI = True21ENABLE_FAISS_PHASE_4 = False22ENABLE_DOC_LEVEL_APIS = False  # auto-detected only23 24# ======================================================25# SESSION STATE (EPHEMERAL)26# ======================================================27 28LAST_RESULTS = []29AI_APPENDIX = None30 31# ======================================================32# UTILITIES33# ======================================================34 35def sha256_text(t: str) -> str:36    return hashlib.sha256(t.encode("utf-8")).hexdigest()37 38def provenance_block(payload: str, ai=False) -> str:39    return "\n".join([40        "Tool-Version: 2.0.0",41        f"Generated-UTC: {datetime.utcnow().isoformat()}",42        f"Content-SHA256: {sha256_text(payload)}",43        "Public-Source-Only: true",44        f"AI-Assisted: {'true' if ai else 'false'}",45        "Court-Safe: true",46    ])47 48# ======================================================49# FOIA ADAPTERS (LINK-OUT ONLY)50# ======================================================51 52class FOIAAdapter:53    agency = "UNKNOWN"54    base_search_url = ""55 56    def search(self, query: str):57        return [{58            "agency": self.agency,59            "title": f"{self.agency} FOIA Reading Room",60            "url": self.base_search_url.format(q=quote_plus(query)),61            "explanation": "This is a public FOIA reading-room result.",62        }]63 64class CIAAdapter(FOIAAdapter):65    agency = "CIA"66    base_search_url = "https://www.cia.gov/readingroom/search/site/{q}"67 68class FBIAdapter(FOIAAdapter):69    agency = "FBI"70    base_search_url = "https://vault.fbi.gov/search?SearchableText={q}"71 72class DOJAdapter(FOIAAdapter):73    agency = "DOJ"74    base_search_url = "https://www.justice.gov/foia/search?search={q}"75 76class DHSAdapter(FOIAAdapter):77    agency = "DHS"78    base_search_url = "https://www.dhs.gov/foia-library?search={q}"79 80ALL_ADAPTERS = {81    "CIA": CIAAdapter(),82    "FBI": FBIAdapter(),83    "DOJ": DOJAdapter(),84    "DHS": DHSAdapter(),85}86 87# ======================================================88# SEARCH89# ======================================================90 91def run_search(query, agencies):92    global LAST_RESULTS93    LAST_RESULTS = []94 95    table_rows = []96    cards_html = []97 98    for agency in agencies:99        adapter = ALL_ADAPTERS[agency]100        for r in adapter.search(query):101            r["hash"] = sha256_text(r["url"])[:16]102            LAST_RESULTS.append(r)103 104            table_rows.append([105                r["agency"],106                r["title"],107                r["url"],108                r["hash"],109            ])110 111            cards_html.append(f"""112            <div class="card">113              <b>{r['agency']}</b><br/>114              {r['title']}<br/>115              <div class="links">116                <a href="{r['url']}" target="_blank">View</a>117                <span>|</span>118                <a href="{r['url']}" target="_blank">Download</a>119                <span>|</span>120                <a href="{r['url']}" target="_blank">Share</a>121                <button class="ask-ai">Ask AI</button>122              </div>123              <div class="why">124                Why am I seeing this? {r['explanation']}125              </div>126            </div>127            """)128 129    return table_rows, "\n".join(cards_html), "Search complete."130 131# ======================================================132# AI (USER-INITIATED ONLY)133# ======================================================134 135def ask_ai(index):136    r = LAST_RESULTS[index]137    text = (138        "AI Assistive Summary (Non-Authoritative)\n\n"139        f"Agency: {r['agency']}\n"140        f"URL: {r['url']}\n\n"141        "This assists review of a public FOIA document only."142    )143    return text + "\n\n" + provenance_block(text, ai=True)144 145# ======================================================146# COURT / CLERK BUNDLE147# ======================================================148 149def generate_court_bundle():150    with tempfile.TemporaryDirectory() as td:151        zip_path = os.path.join(td, "cmecf_bundle.zip")152        with zipfile.ZipFile(zip_path, "w") as z:153            for i, r in enumerate(LAST_RESULTS, 1):154                body = (155                    f"{r['agency']} FOIA Reading Room\n"156                    f"{r['url']}\n\n"157                    + provenance_block(r["url"])158                )159                z.writestr(f"Exhibit_{i:03d}.txt", body)160 161            z.writestr(162                "Judicial_Notice.txt",163                JUDICIAL_NOTICE_TEXT164            )165 166            z.writestr(167                "Clerk_Training.txt",168                JUDICIAL_CLERK_TRAINING_TEXT169            )170 171        return zip_path172 173# ======================================================174# STATIC GOVERNANCE TEXT175# ======================================================176 177JUDICIAL_CLERK_TRAINING_TEXT = """178Judicial Clerk Training – FOIA Navigation Tool179 180• Federated link-out search only181• No scraping or document ingestion182• No authentication or PACER access183• AI outputs are labeled, optional, and hashed184• Suitable for non-filing research reference185"""186 187JUDICIAL_NOTICE_TEXT = """188Judicial Notice – FOIA Reading Room Navigation189 190This system provides navigational assistance to publicly191available FOIA electronic reading rooms. It does not192authenticate documents, retrieve sealed records, or193interact with court filing systems.194"""195 196# ======================================================197# UI198# ======================================================199 200CSS = """201.tabs { position: sticky; top: 0; z-index: 100; background: #0f0f0f; }202.card {203  border: 1px solid #333;204  border-radius: 16px;205  padding: 14px;206  margin-bottom: 14px;207}208.links {209  margin-top: 8px;210}211.ask-ai {212  background: #1e88e5;213  color: white;214  border: none;215  border-radius: 999px;216  padding: 6px 14px;217}218.why {219  font-size: 0.85em;220  opacity: 0.7;221  margin-top: 6px;222}223"""224 225with gr.Blocks(css=CSS) as app:226    gr.Markdown("## Federal FOIA Intelligence Search")227 228    with gr.Tabs(elem_classes="tabs"):229        with gr.Tab("Search"):230            agencies = gr.CheckboxGroup(231                list(ALL_ADAPTERS.keys()),232                value=list(ALL_ADAPTERS.keys()),233                label="Agencies"234            )235            query = gr.Textbox(placeholder="Enter FOIA search term")236            table = gr.Dataframe(headers=["Agency", "Title", "URL", "Hash"])237            cards = gr.HTML()238            status = gr.Textbox()239            gr.Button("Search", elem_classes="ask-ai").click(240                run_search,241                [query, agencies],242                [table, cards, status]243            )244 245        with gr.Tab("Court / Clerk"):246            gr.Button("Generate CM/ECF Bundle").click(247                generate_court_bundle,248                None,249                gr.File()250            )251 252        with gr.Tab("Governance"):253            gr.Markdown(open("governance-site/index.md").read())254 255app.queue()256app.launch(server_name="0.0.0.0", server_port=7860)