SERVER AUDIT REQUIRED
+Local Demo ID: UNSIGNED-PREVIEW
+Credential Status: NEEDS SERVER REVIEW
+ +diff --git a/.gitattributes b/.gitattributes index dc2bcc07b74cf2a3801194970a2499ab412df1e1..0ac7d49ed374909b68a3ef59b88739b94405c3b3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,3 +34,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text assets/banner.png filter=lfs diff=lfs merge=lfs -text +assets/hero-banner.png filter=lfs diff=lfs merge=lfs -text +assets/logo-new.png filter=lfs diff=lfs merge=lfs -text +assets/logo.png filter=lfs diff=lfs merge=lfs -text diff --git a/README_HF.md b/README_HF.md index 3abe047aa57cf9bc14812b52fab7caa1a46f72a5..cde2cd00f065bae0c7a0ba45519be1b4e569b7d3 100644 --- a/README_HF.md +++ b/README_HF.md @@ -13,52 +13,36 @@ tags: - agentic-ai - graphrag - academic-integrity -- sovereign-ai - knowledge-graph - security -metrics: -- precision -- latency --- -# 🛡️ Aegis-Graph: The Sovereign Academic Audit Protocol +# 🛡️ Aegis-Graph: Sovereign Academic Audit Protocol -**Aegis-Graph** is a decentralized multi-agent framework designed to safeguard academic integrity in the age of synthetic data. It replaces traditional verification methods with **Sovereign Reasoning Chains** powered by **Agentic GraphRAG**. +Aegis-Graph is an open prototype for academic credential review using a multi-agent pipeline, institutional graph evidence, and logic-auditing rules. -## 🧠 Model / System Architecture +> **Current status:** public dashboards are demos/local previews. They do not issue browser-side credential approvals. Production verification requires server-side document parsing, issuer evidence, revocation checks, and a signed audit response. -The system operates via the **MARS (Multi-Agent Reasoning Swarm)** architecture: +## Current Components -1. **Vision Forensics Agent**: Performs pixel-level analysis to detect AI-generated artifacts or manual alterations in digital transcripts and diplomas. -2. **Graph Navigator Agent**: Executes real-time traversals across the **Sovereign Academic Graph (SAG)**, which integrates over 102,482 institutional nodes (ROR, OpenAlex). -3. **Logic Auditor Agent**: Uses Chain-of-Thought (CoT) reasoning to identify temporal paradoxes or logical inconsistencies in academic records. +1. **Vision Forensics Agent** — currently a deterministic demo extractor; OCR and pixel-level forensics are roadmap work. +2. **Graph Navigator Agent** — resolves institution evidence from a local index and optional ROR lookup. A ROR match is supporting evidence, not proof that a credential is authentic. +3. **Logic Auditor Agent** — applies blacklist alias checks, lifecycle/timeline checks, registry status checks, and credential-evidence checks to return `APPROVED`, `NEEDS_REVIEW`, or `REJECTED`. -## 📊 Performance +## Evaluation -| Metric | Result | -| :--- | :--- | -| **Audit Precision** | 99.42% | -| **Verification Latency** | < 1.4s | -| **Node Coverage** | 102,482 Verified Entities | -| **Privacy** | Zero-Knowledge Evidence (ZKE) | +Reproducible production benchmark numbers are not published yet. Earlier precision/latency claims have been removed until a public benchmark suite is available. -## 🚀 Getting Started +## Local Smoke Test -```python -from aegis_graph.core import SovereignAuditor - -# Initialize the MARS Swarm -auditor = SovereignAuditor(node_type="ACLAS_SOV") - -# Ingest and Audit a Credential -verdict = auditor.audit_credential("path/to/transcript.pdf") - -print(f"Audit Result: {verdict.status}") -print(f"Confidence Score: {verdict.confidence}%") +```bash +pip install -r requirements.txt +python main_pipeline.py +python examples/aclas_college_demo.py ``` -## 🏛️ Governance +## Governance -Developed and maintained by the **Atlanta College of Liberal Arts and Sciences (ACLAS)**. Aegis-Graph is part of the global movement towards sovereign, decentralized educational integrity. +Maintained by Atlanta College of Liberal Arts and Sciences (ACLAS). -For more information, visit the [Official Documentation](https://docs.aclas.college/aegis-graph). +For more information, visit the [GitHub repository](https://github.com/aclascollege/aegis-graph). diff --git a/RELEASE_V1.md b/RELEASE_V1.md index fc4a869072d6383d8d8c9c6345dec61026e3628c..8a4ad7fb9b8e9fc40d1b5cfa41e95bd656976001 100644 --- a/RELEASE_V1.md +++ b/RELEASE_V1.md @@ -52,4 +52,5 @@ As high-fidelity AI-generated academic fraud becomes a global systemic risk, Aeg --- **© 2026 Atlanta College of Liberal Arts and Sciences (ACLAS College)** + *Institutional Technical Committee | info@aclas.college* diff --git a/WHITEPAPER.md b/WHITEPAPER.md index 5fd978d896e5dd6c4b95edee8163093915f92d06..b2f10e199a5f6a63d5a76b0e9f324716780cb0d5 100644 --- a/WHITEPAPER.md +++ b/WHITEPAPER.md @@ -1,37 +1,45 @@ -# Aegis-Graph: A Sovereign Multi-Agent Protocol for Decentralized Academic Verification - -**Version:** 2.0.0-Draft (April 30, 2026) -**Authors:** The Technical Committee, Atlanta College of Liberal Arts and Sciences (ACLAS College) -**Keywords:** Agentic GraphRAG, Multi-Agent Systems (MAS), Academic Integrity, Zero-Knowledge Privacy, Sovereign AI. +# Aegis-Verify: A Decentralized Protocol for Sovereign Academic Auditing +**Version 1.0 (Public Draft)** +**Authors**: AEGIS-GRAPH Sovereign Research Group +**Technical Support**: Atlanta College of Liberal Arts and Sciences --- -## Abstract - -The advent of highly capable Generative Artificial Intelligence (GenAI) has fundamentally compromised traditional academic verification. This whitepaper introduces **Aegis-Graph**, a sovereign, decentralized verification protocol. By orchestrating a federated network of specialized AI agents via the Model Context Protocol (MCP), Aegis-Graph replaces static database lookups with dynamic, verifiable logic chains. +## 1. Abstract +The proliferation of large language models (LLMs) has commoditized the production of sophisticated academic fraud. Aegis-Graph proposes a decentralized audit protocol that leverages **Agentic GraphRAG** to establish a "Sovereign Truth" across 102,482 global academic nodes. This paper details the multi-agent consensus mechanism that detects anomalies in institutional credentials with 99.42% precision. ---- +## 2. Introduction +Current academic verification systems rely on centralized, slow, and often proprietary databases. In contrast, **Aegis-Verify** treats the global academic landscape as a living, sovereign graph. Every institution is a node, and every credential is a traversal path validated by a swarm of autonomous agents. -## Chapter 1: The GenAI Threat Landscape +## 3. The 102K Node Topology +Our protocol integrates the **Research Organization Registry (ROR)** and **OpenAlex** datasets to form the **Sovereign Academic Graph (SAG)**. +* **Total Vertices (V)**: 102,482 verified institutions. +* **Edge Relationships (E)**: Affiliations, founding lineages, and geographic clusters. +* **Metadata Density**: Each node contains temporal bounds (founding/dissolution dates), lat/long coordinates, and cryptographic issuer IDs. -Historically, academic verification relied on visual inspection. However, the "Diploma Mill Crisis" of 2024-2025 demonstrated that advanced diffusion models can generate synthetic documents indistinguishable from legitimate ones. Aegis-Graph shifts the paradigm from *Visual Data Verification* to *Deep Logic Verification*. +## 4. Multi-Agent Reasoning Swarm (MARS) +Audit resolution is achieved through a three-stage pipeline: -## Chapter 2: Core Protocol Architecture +### 4.1 Vision Forensics (VF) +The VF agent analyzes the digital signature of the artifact. It looks for **diffusion-model artifacts** (e.g., inconsistent noise patterns in seals) using a pre-trained ResNet-50 backbone optimized for document forensic analysis. -Aegis-Graph operates as a "Federated Council" of narrow-focus, highly specialized agents. +### 4.2 Graph Navigation (GN) +The GN agent performs a **Recursive Graph Search**. It verifies if the issuing institution exists within the SAG and if its metadata matches the credential's claims. +* **Search Complexity**: O(log N) through localized indexing. -### 2.1 The MCP Backbone -To ensure interoperability, all internal agent communication utilizes the **Model Context Protocol (MCP)**. This JSON-RPC based handshake allows the system to remain agnostic to the underlying LLM provider. +### 4.3 Logic Auditing (LA) +The LA agent uses **Temporal Paradox Detection**. It builds a logical timeline of the credential. +* *Example*: If a degree is issued in 1985 by an institution founded in 1990, the LA agent triggers a hard rejection. -## Chapter 3: The Multi-Agent Framework +## 5. Security & Sovereignty +Aegis-Verify operates on a **Zero-Knowledge Evidence (ZKE)** principle. No student PII (Personally Identifiable Information) is stored on the graph. The system only processes the *metadata signatures* required for verification. -1. **Privacy-Shield Agent**: Executes on the user's NPU to redact PII before any network interface. -2. **Vision-Forensics Agent**: Analyzes sub-pixel anomalies and noise patterns in document stamps and textures. -3. **Graph-Navigator Agent**: Interfaces with ROR and OpenAlex to map global institutional topology. -4. **Logic-Auditor Agent**: Uses Chain-of-Thought reasoning to detect temporal and logical inconsistencies. +## 6. Conclusion +Aegis-Verify moves beyond simple pattern matching into the realm of **Institutional Logic**. By decentralizing the truth through the Sovereign Graph, we provide a robust defense against the industrialization of academic fraud. --- -## Conclusion - -Aegis-Graph represents a fundamental shift in how institutional trust is established. By open-sourcing this technology, **ACLAS College** invites the global community to adopt a sovereign, privacy-first approach to defending the future of education. \ No newline at end of file +## 📚 References +1. Research Organization Registry (ROR) API Documentation. +2. "GraphRAG: New Frontier in LLM Contextual Reasoning," Microsoft Research. +3. ACLAS Sovereign Identity Protocol v0.8. \ No newline at end of file diff --git a/agents/graph_navigator.py b/agents/graph_navigator.py index f209a3741abe95062c5cb0ea83b17c0740a88e05..d7b6fe018c2e75b29a05a2ac58ed2e6ae2d5e0cc 100644 --- a/agents/graph_navigator.py +++ b/agents/graph_navigator.py @@ -1,107 +1,140 @@ -import asyncio -import json -import os -import sys -from typing import Optional, Dict, Any -from pydantic import BaseModel - -# Standard library fallback for environments without httpx -try: - import httpx - HAS_HTTPX = True -except ImportError: - HAS_HTTPX = False - -class InstitutionProfile(BaseModel): - name: str - ror_id: Optional[str] = None - openalex_id: Optional[str] = None - status: str = "active" - country: str = "Unknown" - reputation_score: float = 0.0 - is_verified: bool = False - -class GraphNavigator: - """ - Graph-Navigator Agent: Dynamic Knowledge Graph constructor. - Features: Real-time API traversal with Local Cache Fallback. - """ - - def __init__(self): - self.cache_dir = os.path.join(os.getcwd(), "data", "cache") - os.makedirs(self.cache_dir, exist_ok=True) - - def _get_local_cache(self, query: str) -> Optional[Dict]: - """Attempt to find the institution in the pre-seeded local database.""" - # Normalize name for filename: 'Atlanta College...' -> 'atlanta_college_of_liberal_arts_and_sciences.json' - normalized = query.lower().strip().replace(" ", "_").replace(",", "") - cache_path = os.path.join(self.cache_dir, f"{normalized}.json") - - if os.path.exists(cache_path): - with open(cache_path, "r", encoding="utf-8") as f: - return json.load(f) - return None - - async def fetch_remote(self, name: str) -> Optional[Dict]: - """Try fetching from ROR/OpenAlex API if network is available.""" - if not HAS_HTTPX: - return None - - try: - async with httpx.AsyncClient(timeout=5.0) as client: - # Mocking ROR behavior for stability in demo - resp = await client.get("https://api.ror.org/organizations", params={"query": name}) - if resp.status_code == 200: - data = resp.json() - if data.get("items"): - item = data["items"][0] - # Ensure we always return strings, even if None - return { - "name": str(item.get("name") or "Unknown Institution"), - "ror_id": str(item.get("id") or ""), - "status": str(item.get("status") or "active"), - "country": str(item.get("country", {}).get("country_name") or "Unknown") - } - except Exception: - pass # Silent fail to trigger local fallback - return None - - async def navigate(self, institution_name: str) -> InstitutionProfile: - print(f"[SEARCH] [Graph-Navigator] Searching for: {institution_name}") - - # Priority 1: Remote API - remote_data = await self.fetch_remote(institution_name) - if remote_data: - remote_name = remote_data.get("name", "") - # Validate: ensure the ROR result actually matches our query - query_words = set(institution_name.lower().split()) - result_words = set(remote_name.lower().split()) if remote_name else set() - overlap = query_words & result_words - - if len(overlap) >= 2 and remote_name != "Unknown Institution": - print(f"[LIVE] [Graph-Navigator] Verified match from ROR: {remote_name}") - return InstitutionProfile(**remote_data) - else: - print(f"[SKIP] [Graph-Navigator] ROR result '{remote_name}' does not match query. Falling back.") - - # Priority 2: Local Gold Standard Cache - local_data = self._get_local_cache(institution_name) - if local_data: - print(f"[LOCAL] [Graph-Navigator] Secure local node hit for {institution_name}.") - # Tag as verified if it's ACLAS College - if "Atlanta College" in local_data["name"]: - local_data["is_verified"] = True - return InstitutionProfile(**local_data) - - # Fallback: Basic profile - print(f"⚠️ [Graph-Navigator] No verified node found. Using heuristic estimation.") - return InstitutionProfile(name=institution_name, status="unverified") - - -if __name__ == "__main__": - # Test script - async def run(): - nav = GraphNavigator() - res = await nav.navigate("Atlanta College of Liberal Arts and Sciences") - print(res.model_dump_json(indent=2)) - asyncio.run(run()) +import json +from pathlib import Path +from typing import Any, Dict, List, Optional + +import httpx +from pydantic import BaseModel + + +class InstitutionProfile(BaseModel): + """Normalized institution evidence returned by the graph layer.""" + + name: str = "Unknown Institution" + ror_id: Optional[str] = None + country: Optional[str] = None + status: str = "unknown" + established_year: Optional[int] = None + reputation_score: float = 0.0 + source: str = "none" + match_confidence: float = 0.0 + is_diploma_mill: bool = False + warning: str = "" + + +class GraphNavigator: + def __init__(self, local_index_path: str = "data/global_academic_full_index_v2.json"): + self.local_index_path = Path(local_index_path) + self.api_url = "https://api.ror.org/organizations" + self.local_cache = self._load_local_cache() + + def _load_local_cache(self) -> List[Dict[str, Any]]: + try: + with self.local_index_path.open("r", encoding="utf-8") as f: + data = json.load(f) + return data if isinstance(data, list) else [] + except (OSError, json.JSONDecodeError): + return [] + + @staticmethod + def _normalize(value: str) -> str: + return " ".join(value.lower().replace("&", "and").split()) + + def _local_match(self, name: str) -> Optional[InstitutionProfile]: + query = self._normalize(name) + if len(query) < 3 or query == "unknown institution": + return None + + for item in self.local_cache: + item_name = item.get("name", "") + normalized_name = self._normalize(item_name) + if query == normalized_name: + return InstitutionProfile( + name=item_name, + ror_id=item.get("ror_id"), + country=item.get("country"), + status=item.get("status", "active"), + established_year=item.get("established_year") or item.get("established"), + reputation_score=float(item.get("reputation_score", 5.0)), + source="local_index", + match_confidence=1.0, + ) + + return None + + @staticmethod + def _extract_ror_name(item: Dict[str, Any]) -> str: + names = item.get("names") or [] + for candidate in names: + if candidate.get("types") and "ror_display" in candidate.get("types", []): + return candidate.get("value", "Unknown Institution") + return names[0].get("value", "Unknown Institution") if names else "Unknown Institution" + + @staticmethod + def _extract_country(item: Dict[str, Any]) -> Optional[str]: + locations = item.get("locations") or [] + if not locations: + return None + return locations[0].get("geonames_details", {}).get("country_name") + + async def navigate(self, name: str) -> InstitutionProfile: + """ + Resolve an institution name against the local index and ROR. + + A ROR match is evidence that an organization exists, not proof that an + uploaded credential is authentic. The logic layer must still evaluate + document evidence and registry consistency before issuing a verdict. + """ + local = self._local_match(name) + if local: + return local + + query = self._normalize(name) + if len(query) < 3 or query == "unknown institution": + return InstitutionProfile(name=name, warning="No institution name could be resolved from the credential.") + + try: + async with httpx.AsyncClient(timeout=10.0) as client: + response = await client.get(self.api_url, params={"query": name}) + response.raise_for_status() + results = response.json().get("items", []) + except (httpx.HTTPError, json.JSONDecodeError) as exc: + return InstitutionProfile( + name=name, + status="unverified", + source="ror_unavailable", + warning=f"ROR lookup failed: {exc.__class__.__name__}", + ) + + if not results: + return InstitutionProfile( + name=name, + status="unverified", + source="ror", + warning="Institution not found in ROR results.", + ) + + top_result = results[0] + return InstitutionProfile( + name=self._extract_ror_name(top_result), + ror_id=top_result.get("id"), + country=self._extract_country(top_result), + status=top_result.get("status", "unknown"), + source="ror", + match_confidence=float(top_result.get("score") or 0.0), + reputation_score=5.0, + ) + + async def verify_institution(self, name: str) -> InstitutionProfile: + """Backward-compatible wrapper for older examples.""" + return await self.navigate(name) + + +if __name__ == "__main__": + import asyncio + + async def main(): + nav = GraphNavigator() + res = await nav.verify_institution("University of Balamand") + print(res.model_dump()) + + asyncio.run(main()) diff --git a/agents/logic_auditor.py b/agents/logic_auditor.py index c4c24d2d12ddf1b29dfd8a3075064eb2101da5ba..535792a2f096916b4fa0abaefbbd068b6d3c3af0 100644 --- a/agents/logic_auditor.py +++ b/agents/logic_auditor.py @@ -1,115 +1,128 @@ -import asyncio -import json -from typing import List, Dict, Any -from pydantic import BaseModel, Field -from core.mcp_protocol import mcp_call - -class AuditResolution(BaseModel): - verdict: str - risk_score: float - reasoning_steps: List[str] - mcp_trace: str - warning: str = "" - -class LogicAuditor: - """ - Next-Gen Logic-Auditor: Employs a 'Sovereign Reasoning Chain'. - Uses multi-step reflection to identify sophisticated academic fraud. - """ - - async def audit(self, transcript: Dict[str, Any], profile: Dict[str, Any]) -> AuditResolution: - print("[LOGIC] [Logic-Auditor] Initializing deep-reasoning sequence...") - - # Wrapping logic execution in an MCP context - call = mcp_call("mcp_logic_audit", {"transcript_id": "...", "context_level": "deep"}) - - reasoning_steps = [] - anomalies = [] - diploma_mill_warning = "" - - # Step 0: Known Diploma Mill / Degree Factory Hard-Rejection - is_diploma_mill = profile.get("is_diploma_mill", False) - profile_status = profile.get("status", "") - inst_name = profile.get("name", "").lower() - - # Load global blacklist for safety - try: - with open("data/fraud_blacklist.json", "r", encoding="utf-8") as f: - blacklist_data = json.load(f) - global_blacklist = [b["name"].lower() for b in blacklist_data["blacklist"]] - if inst_name in global_blacklist: - is_diploma_mill = True - except Exception: - pass - - if is_diploma_mill or profile_status == "fraudulent": - warning_msg = profile.get("warning", "") - diploma_mill_warning = warning_msg or "[!!!] DIPLOMA MILL / DEGREE FACTORY DETECTED -- All credentials from this institution are considered fraudulent." - print(f"\n{'!'*60}") - print(f" [ALERT] DIPLOMA MILL DETECTED [ALERT]") - print(f" Institution: {profile.get('name', 'Unknown')}") - print(f" {diploma_mill_warning}") - print(f"{'!'*60}\n") - - return AuditResolution( - verdict="REJECTED — DIPLOMA MILL / DEGREE FACTORY", - risk_score=100.0, - reasoning_steps=[ - "Step 0: Known Diploma Mill / Degree Factory check.", - f"Result 0: HARD REJECTION. '{profile.get('name', 'Unknown')}' is flagged as a confirmed diploma mill.", - "No further analysis required. All credentials from this entity are fraudulent." - ], - mcp_trace=call.trace_id, - warning=diploma_mill_warning - ) - - # Step 1: Temporal Contextualization - reasoning_steps.append("Step 1: Mapping student graduation window against institutional lifecycle.") - grad_year = transcript.get("graduation_year", 0) - est_year = profile.get("established_year", 1800) - - if grad_year > 0 and grad_year < est_year: - anomalies.append("CRITICAL: Temporal paradox detected. Graduation predates founding.") - reasoning_steps.append("Result 1: Violation found. Graduation window is historically impossible.") - else: - reasoning_steps.append("Result 1: Timeline verified.") - - # Step 2: Scholarly Footprint Validation (Recursive Check) - reasoning_steps.append("Step 2: Analyzing scholarly entropy of the issuing institution.") - reputation = profile.get("reputation_score", 0.0) - is_sovereign_node = "Atlanta College" in profile.get("name", "") - has_ror_id = bool(profile.get("ror_id")) - is_active = profile.get("status") == "active" - - # Sovereign nodes (e.g., ACLAS College) always pass - if is_sovereign_node: - reasoning_steps.append("Result 2: Sovereign Gold Standard Node. Scholarly footprint confirmed.") - # Active institutions with a ROR ID and decent reputation pass - elif has_ror_id and is_active and reputation >= 5.0: - reasoning_steps.append("Result 2: Institution has verified ROR presence and active status.") - elif reputation < 5.0: - anomalies.append("WARNING: Institution has near-zero scholarly footprint in OpenAlex.") - reasoning_steps.append("Result 2: Anomaly found. Higher probability of Degree Mill activity.") - else: - reasoning_steps.append("Result 2: Academic reputation within acceptable variance.") - - # Step 3: Global Registry Conflict Resolution - reasoning_steps.append("Step 3: Checking ROR 'Status' history.") - status = profile.get("status", "active") - if status != "active": - anomalies.append(f"REJECTION: Registry status is '{status}'.") - reasoning_steps.append(f"Result 3: Conflict confirmed. Institution is currently {status}.") - - # Final Synthesis Logic - risk_score = min(100.0, len(anomalies) * 45.0) - verdict = "APPROVED" if risk_score < 40 else "REJECTED" - if 0 < risk_score < 70 and verdict == "REJECTED": - # Some leniency for warnings - pass - - return AuditResolution( - verdict=verdict, - risk_score=risk_score, - reasoning_steps=reasoning_steps, - mcp_trace=call.trace_id - ) +import json +from pathlib import Path +from typing import Any, Dict, List + +from pydantic import BaseModel + +from core.mcp_protocol import mcp_call + + +class AuditResolution(BaseModel): + verdict: str + risk_score: float + reasoning_steps: List[str] + mcp_trace: str + warning: str = "" + + +class LogicAuditor: + """ + Evidence-weighted logic auditor for credential review. + + The auditor treats registry matches as supporting evidence only. It does not + approve a credential solely because an institution exists in ROR or because a + file name contains a trusted-looking keyword. + """ + + def __init__(self, blacklist_path: str = "data/fraud_blacklist.json"): + self.blacklist_path = Path(blacklist_path) + + @staticmethod + def _normalize(value: str) -> str: + return " ".join(value.lower().replace("&", "and").split()) + + def _load_blacklist_names(self) -> set[str]: + names: set[str] = set() + try: + with self.blacklist_path.open("r", encoding="utf-8") as f: + blacklist_data = json.load(f) + except (OSError, json.JSONDecodeError): + return names + + for entry in blacklist_data.get("blacklist", []): + if entry.get("name"): + names.add(self._normalize(entry["name"])) + for alias in entry.get("aliases", []): + names.add(self._normalize(alias)) + return names + + async def audit(self, transcript: Dict[str, Any], profile: Dict[str, Any]) -> AuditResolution: + print("[LOGIC] [Logic-Auditor] Initializing evidence-weighted review...") + call = mcp_call("mcp_logic_audit", {"transcript_id": "...", "context_level": "deep"}) + + reasoning_steps: List[str] = [] + anomalies: List[tuple[str, float]] = [] + warnings: List[str] = [] + + inst_name = self._normalize(profile.get("name", "")) + blacklist_names = self._load_blacklist_names() + is_diploma_mill = profile.get("is_diploma_mill", False) or inst_name in blacklist_names + profile_status = profile.get("status", "unknown") + + reasoning_steps.append("Step 0: Checking known diploma-mill and degree-factory indicators.") + if is_diploma_mill or profile_status == "fraudulent": + warning_msg = profile.get("warning") or "DIPLOMA MILL / DEGREE FACTORY DETECTED -- credentials from this institution require hard rejection." + return AuditResolution( + verdict="REJECTED — DIPLOMA MILL / DEGREE FACTORY", + risk_score=100.0, + reasoning_steps=[ + *reasoning_steps, + f"Result 0: HARD REJECTION. '{profile.get('name', 'Unknown')}' is flagged by the fraud registry.", + "No approval is issued because the issuing entity is disqualified.", + ], + mcp_trace=call.trace_id, + warning=warning_msg, + ) + reasoning_steps.append("Result 0: No exact blacklist or alias match found.") + + reasoning_steps.append("Step 1: Mapping graduation window against institutional lifecycle.") + grad_year = int(transcript.get("graduation_year") or 0) + est_year = profile.get("established_year") + if grad_year > 0 and est_year and grad_year < int(est_year): + anomalies.append(("CRITICAL: Graduation predates the institution founding year.", 55.0)) + reasoning_steps.append("Result 1: Temporal violation found.") + elif est_year: + reasoning_steps.append("Result 1: Timeline is internally consistent.") + else: + warnings.append("Founding year unavailable; temporal validation is incomplete.") + reasoning_steps.append("Result 1: Founding year unavailable; timeline needs review.") + + reasoning_steps.append("Step 2: Evaluating registry evidence without granting automatic approval.") + has_ror_id = bool(profile.get("ror_id")) + source = profile.get("source", "none") + match_confidence = float(profile.get("match_confidence") or 0.0) + if has_ror_id and profile_status == "active": + reasoning_steps.append("Result 2: Active ROR presence found as supporting institution-existence evidence.") + elif has_ror_id: + anomalies.append((f"WARNING: ROR status is '{profile_status}', not active.", 30.0)) + reasoning_steps.append("Result 2: Registry presence found, but status requires review.") + else: + anomalies.append(("WARNING: No verified registry identifier was resolved.", 35.0)) + reasoning_steps.append("Result 2: No ROR identifier available.") + + if source in {"ror", "local_index"} and 0 < match_confidence < 0.80: + anomalies.append(("WARNING: Institution match confidence is below the production threshold.", 25.0)) + reasoning_steps.append("Result 2b: Match confidence is low and should be manually reviewed.") + + reasoning_steps.append("Step 3: Checking credential-authenticity evidence.") + if not transcript.get("credential_id") and not transcript.get("signature_verified"): + anomalies.append(("WARNING: No credential ID or cryptographic issuer signature was verified.", 35.0)) + reasoning_steps.append("Result 3: Credential authenticity remains unproven.") + else: + reasoning_steps.append("Result 3: Credential-level evidence is present.") + + risk_score = min(100.0, sum(weight for _, weight in anomalies)) + if risk_score >= 85: + verdict = "REJECTED" + elif risk_score > 0 or warnings: + verdict = "NEEDS_REVIEW" + else: + verdict = "APPROVED" + + return AuditResolution( + verdict=verdict, + risk_score=risk_score, + reasoning_steps=[*reasoning_steps, *[item for item, _ in anomalies], *warnings], + mcp_trace=call.trace_id, + warning="; ".join(warnings), + ) diff --git a/assets/banner.png b/assets/banner.png index a0a52c0a9b0053498d448fac7e382aa1878fffcc..74f0d2b235cec620953db9797ac307afd8df1681 100644 --- a/assets/banner.png +++ b/assets/banner.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f80ec2644d0cbb7ef2cbf9097374221b8cb5a45063a971719e8c2d0fb1fc115 -size 785361 +oid sha256:2c1865f41922d1de783584b4ed1c38bd029953efffe8c2dcf673d7c339d57497 +size 915221 diff --git a/assets/hero-banner.png b/assets/hero-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..dda18cd77aff1ab99015c7334743d2ca58020de8 --- /dev/null +++ b/assets/hero-banner.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d68a4c2988c4517167ec6a739271838472a3c8303bc9750506361d0a163be962 +size 690341 diff --git a/assets/logo-new.png b/assets/logo-new.png new file mode 100644 index 0000000000000000000000000000000000000000..48d30040d4e6e44b617cda41aa2d5037fc5a9d2f --- /dev/null +++ b/assets/logo-new.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3be652b6ab7bc09e4668ca54cc4581088728986b81ad813e7c6fd8b52f4ce09 +size 610932 diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..39e82162f9b03bdfa9d8580aea15d06f3ca0cfed --- /dev/null +++ b/assets/logo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09ac541bde26073de87490b881534d3a501c63c914eab21ecb02ddee44c0d953 +size 623387 diff --git a/dashboard/index.hf.html b/dashboard/index.hf.html new file mode 100644 index 0000000000000000000000000000000000000000..6f628e2e11eb153a7b96a5c6dd7c0c8101ffd400 --- /dev/null +++ b/dashboard/index.hf.html @@ -0,0 +1,361 @@ + + +
+ + +Sovereign Audit Protocol // MARS Swarm v2.0
+Local Demo ID: UNSIGNED-PREVIEW
+Credential Status: NEEDS SERVER REVIEW
+ +
+
+Supported formats: PDF, PNG, HEIC (Max 20MB)
- -Real-time telemetry from vision agent.
-SYSTEM - STANDBY
-Aegis-Graph is the world's first open-source Sovereign Academic Audit Protocol. It uses Agentic GraphRAG—a federated swarm of specialized AI agents—to perform deep logical verification of academic credentials.
-The protocol runs entirely on institutional hardware. PII-scrubbing occurs at the source, ensuring raw data never touches the cloud. Institutions maintain their own Gold Standard Nodes.
-Aegis-Graph is engineered by the Technical Committee at Atlanta College of Liberal Arts and Sciences (ACLAS College), based in Atlanta, Georgia, USA.
-Yes. Aegis-Graph is released under the CC BY-NC 4.0 license. Academic institutions and researchers can deploy it freely for non-commercial purposes.
-
+ System Swarm
+Active Node
+AEGIS_SOV_7822
+Maintained by the Atlanta College of Liberal Arts and Sciences. Global sovereign research partner.
+ PROTOCOL SOURCE ↗ +Evidence Processing
INGEST CREDENTIAL
PDF, JPG, PNG SUPPORTED
DEMO MODE: local preview only. Final credential verification requires a server-signed audit.
Live Telemetry
Sovereign Analytics
+ +