Spaces:
Build error
Build error
Commit History
-
Add read-only Data Sources page (D7, scoped to transparency only)
What: a new /datasets page listing every official source this platform draws from -- name, official URL, what kind of data, live record count in the graph, and loaded/pending status -- with click-to-expand sample records per source. Reachable from the navbar between Forensics and About. Real discovery that reshaped this: api/routes/sources.py's /sources and /sources/{dataset} endpoints already existed, fully built and already registered in main.py, computing exactly this data (real per-source graph counts, loaded/pending status, sample records) -- just with no frontend ever calling them. So this commit is entirely frontend: two new Api client methods over the existing endpoints, two small CSS badge modifiers reusing existing color tokens (not a new palette), and one new Views.datasets page mirroring the Views.forensics page's exact structure (skeleton loaders, Api call, then/catch, sanitize() everywhere). Deliberately scoped to read-only, and this is worth being explicit about rather…5761f57
-
Extend provenance badges to search results (D8)
What: search results now carry and display source_type, same as the profile page from the previous commit. Three pieces: - api/models.py: SearchResult gets a source_type field (Optional, same convention as risk_level). - api/routes/search.py: all 22 LABEL_QUERIES RETURN clauses, the fulltext-index query, and both result-construction code paths (fulltext success + label-scan fallback) now select/pass source_type through. Applied as one global, count-asserted substitution across the 22 near-identical query strings rather than 22 separate manual edits -- same reasoning as the desktop-mode chdir fix: many genuinely uniform call sites are better fixed once, centrally, when the change to each is identical. - frontend/js/components.js: ResultCard renders the badge by calling Components.ProvenanceBadge(...).outerHTML rather than duplicating its label map inline -- one source of truth for the 4 SOURCE_TYPES labels, and it inherits that component's textContent-based (not in…c91bada -
Add provenance badges to the entity profile view (D8)
What: a colored badge next to the entity-type badge on every profile page, showing graph/schema.py's SOURCE_TYPES value (OFFICIAL today; UNOFFICIAL/COMMUNITY/USER_CREATED are provenance for D7's future user-import paths). Mirrors the existing badge/risk-badge pattern exactly -- same component style (Components.ProvenanceBadge, container appended post-render), same CSS structure, reuses existing color tokens rather than inventing a new palette (OFFICIAL reuses badge--company's green, COMMUNITY reuses badge--contract's blue, USER_CREATED reuses risk-badge--MODERATE's amber, UNOFFICIAL reuses risk-badge--NONE's neutral gray). One commit, not several, because the two halves are inert alone: the backend field with no UI renders nothing, and the UI with no field has nothing to render. Real gap found and fixed, not assumed: source_type was already being read off every node (p = dict(pol['p'])) but silently dropped by the Politician and Company profile handlers' hand-curated overview dicts -…66bf6f4
-
fix(frontend): vendor D3.js locally instead of loading from CDN (N-2/F-14)
Root cause: frontend/index.html loaded D3 from cdnjs.cloudflare.com. window._d3Failed was set in the script's onerror handler but never read anywhere in the codebase (confirmed by grep across every frontend/*.js file) -- so on CDN failure, the Relationship Graph tab threw an unhandled ReferenceError instead of showing any kind of message. Trigger condition: whenever cdnjs.cloudflare.com is unreachable. Rare today for the hosted deployment, but becomes a routine condition (not an edge case) the moment any offline/local desktop build ships -- this is exactly the CDN dependency PHASE_ROADMAP.md's offline-first goal can't tolerate. Fix direction: vendored the library locally rather than wiring the existing _d3Failed flag into a real fallback message. A real offline-first / desktop build has no good 'recover from missing charting library' story worth building -- the relationship-graph feature would just be broken either way -- so removing the network dependency entirely is the correct fix…a18c616
-
feat(frontend): finish the Phase 35 entity-view tabs and forensics page (closes B-13)
Completes work that landed partially in an earlier commit -- the entity view's Promise.all expansion, tab buttons, and content panel divs were already in place, but the tab-rendering logic (Timeline/Analytics render, Forensics lazy-load, the 6-tab switch array), the standalone Views.forensics page itself, the Forensics nav link, and the test_six_tabs_defined fix had not yet been applied. Verified: node --check passes. Full suite: 116 passed, 0 failed, 0 errored.49ea00f
-
feat(frontend): build the Phase 35 entity-view tabs and forensics page (closes B-13)
Root cause / what this closes: the backend routes for Timeline, Forensics, and Network Analytics (Phase 33/34) have existed and worked since before this audit -- the frontend was never updated to add the 3 tabs (Timeline, Forensics, Analytics) those routes were built for. tests/test_phase35_frontend.py's own 14 failing assertions all traced to this one gap, not 14 separate problems. Separately, Router.register("/forensics", Views.forensics) already existed at the bottom of app.js -- the route was registered but pointed at an object property (Views.forensics) that was never defined anywhere, and had no nav link to reach it from the UI at all. Changes, by file: frontend/js/app.js: - Views.entity's Promise.all expanded from 3 calls to 7: added Api.timeline(id), Api.timelineByYear(id), Api.graphAnalytics(id, 2), Api.investigate(id) alongside the existing profile/risk/graph calls. - Entity view expanded from 3 tabs to 6 (findings, graph, timeline, forensics, analytics, evi…7b07128
-
fix(sw.js): isApiPath allowlist was missing 20 route prefixes, not the 14 the audit named
Root cause: the service worker's isApiPath check only recognized 13 of the API's real route prefixes. The audit report named 14 missing prefixes; extracting every actual @router.get/post/put/delete path from every file in api/routes/ and diffing against the old allowlist programmatically found 20 -- 6 more than the report listed: /verify (export.py), /connection-map and /node-evidence (investigation.py -- never nested under /investigate despite living in that file), and /languages, /translate, /ui-labels (multilingual.py -- none of these literally start with '/multilingual'; only /search/multilingual and /risk/multilingual/{id} do, and those were already covered by the existing /search and /risk entries). Trigger condition: only when a local developer has the service worker registered against localhost (the hosted deployment's own branch of this logic treats every path as API-like regardless of prefix, so this doesn't reach production users of the hosted site). Under that condition, r…beba5b2
-
fix(sw.js): bump CACHE version to force clients off the poisoned cache
The service worker caches app.js/api.js cache-first under a static key. Editing those files alone does not force a refetch -- only changing the service-worker script itself does. That let browsers that had visited before the two syntax-error commits keep serving old-but-working cached JS indefinitely, while new visitors got the broken files straight from the network. Bumping bharatgraph-v5 -> v6 invalidates the old cache on next visit. Still requires one bump per deploy going forward; a content-hashed cache name would remove that manual step as a follow-up.f4791ec -
fix(app.js): correct bad escape sequence in search filter button
fix_lang_search.py's find/replace introduced t!==\'All\' inside a template-literal expression slot (${...}), where a backslash-escaped single quote is not valid JS syntax outside of a string. This threw a SyntaxError at parse time and took down the entire app.js file -- Router, State, Views, initApp(), and the live-feed WebSocket logic never got defined. Changed to the double-quoted form (t!=="All") already used two tokens earlier in the same expression, matching the surrounding quoting style and needing no escaping. Verified with: node --check frontend/js/app.js353faba -
fix(api.js): restore missing closing brace on graphCommunities()
graphCommunities() was never closed, which silently absorbed every subsequent method (investigate, forensicsCircularOwnership, ..., caseMemorySimilar) as if it were still inside it, and left an orphaned extra closing brace at the end of the object literal. This was a hard parse-time SyntaxError ('Function statements require a function name' at the first nested function after the missing brace), which meant window.Api never got defined at all -- every Api.* call in the app (search, health, live feed, i18n, ...) threw ReferenceError. Verified with: node --check frontend/js/api.jsdb3dcda
-
feat(phase-35): add Api.investigate() method to api.js
Api.investigate(entityId) calls GET /investigate/{entityId} which runs all 15 parallel investigators against the entity. This is now included in the entity view Promise.all so investigation findings are loaded alongside profile/risk/graph.be7ca1d -
feat(phase-35): add /forensics page to frontend router
New page at #/forensics showing network-wide forensic intelligence: Ghost Companies panel: Calls Api.forensicsGhostCompanies(60) -- companies scoring >= 60 Shows company name + ghost score badge + reason Shadow Directors panel: Calls Api.forensicsShadowDirectors(10) -- directors of 10+ companies Shows director name + company count + address clusters Circular Ownership panel (full width): Calls Api.forensicsCircularOwnership(6) -- max 6-node cycles Shows cycle path with arrows (A -> B -> C -> A) All 3 panels load in parallel with Promise.all. Spinner shown during load, graceful empty-state messages.086d779
-
feat(phase-34): add 10 Phase 34 client methods to api.js
Forensic endpoints: Api.forensicsCircularOwnership(maxLen) Api.forensicsGhostCompanies(minScore) Api.forensicsShadowDirectors(minCount) Api.forensicsBenfords(entityId) Self-learning endpoints: Api.selfLearningPatterns() Api.selfLearningWeights() Api.selfLearningAudit() Case memory endpoints: Api.caseMemoryStats() Api.caseMemorySimilar(findingTypes)34cd641
-
feat(phase-33): add 6 Phase 33 client methods to api.js
Api.timeline(entityId, category) -- GET /timeline/{id} Api.timelineByYear(entityId) -- GET /timeline/{id}/by-year Api.graphAnalytics(entityId, depth) -- GET /graph/analytics/{id} Api.graphBetweenness(limit) -- GET /graph/centrality/betweenness Api.graphPagerank(limit) -- GET /graph/centrality/pagerank Api.graphCommunities(minSize) -- GET /graph/communities All methods use string concatenation to avoid shell backtick issues.cdc0d19 -
fix(phase-33): fix _renderTimeline to call /timeline/ not /biography/
Was calling /biography/{entityId}. BiographyResponse wraps events in nested { timeline: { events: [] } } -- narrative format, not structured. New /timeline/{entityId} returns flat structured events: { events: [{date, category, title, detail, amount_crore, source}] } Also fixed events extraction and sort order to newest-first.daf86d8
-
fix(B-06): confirm filter button data-nav-path fix applied + wire addEventListener
B-06 was applied by line-number replacement (the backtick in the original python -c command caused a SyntaxError before it could print OK, but the file write happened correctly before the error). The filter .map(t => ...) block is confirmed replaced with .map(function(t)) using data-nav-path attributes and addEventListener, eliminating the broken inline onclick double-quote HTML attribute quoting that truncated every filter button except All.0ece323
-
fix(B-25): remove incorrect D3 7.9.0 SRI hash that silently blocked graph visualisation
The integrity hash 'sha512-vc58zeo...' in index.html does not match D3 v7.9.0. Browsers that enforce Subresource Integrity refuse to execute scripts whose hash does not match -- silently, with no user-visible error. This broke ALL graph visualisation: the relationship graph tab rendered empty, the zoom controls had no effect, node clicks did nothing, and the Reset button threw JavaScript errors. The onerror handler set _d3Failed=true but no code checked this flag before calling GraphRenderer.init(). Fix: removed the incorrect integrity attribute. cdnjs.cloudflare.com is a trusted CDN that does not require SRI for basic security.c4a33c8 -
fix(B-13): move BHARATGRAPH_API_URL script to top of <head> -- eliminates race condition
api.js line 1: const API_BASE = window.BHARATGRAPH_API_URL || 'http://localhost:8000' The BHARATGRAPH_API_URL inline script was at the bottom of <body>, same position as api.js. If api.js evaluated before the inline script ran, API_BASE defaulted to localhost and ALL API calls silently failed with connection refused. No error was shown to the user. Fix: moved the URL definition script to the very first position inside <head>, guaranteeing it runs before any JS file is loaded.85fee75 -
fix(B-29): replace misleading 'court-grade PDF' claim with accurate disclaimer
SHA-256 hashing only proves the PDF was not modified after generation. It does NOT prove data accuracy, source authenticity, or legal admissibility. Presenting this as 'court-grade' to journalists or citizens could cause real harm if they rely on it for legal proceedings. Changed to 'tamper-evident PDF' with explicit 'Not a legal document -- for research use only' disclaimer.f408a8f -
fix(B-15): remove extra brace orphaning else branch in liveFeed ws.onmessage
The ws.onmessage handler had an extra closing brace after: container2.appendChild(callout); } <- extra brace closes the if-block early } else { <- this else branch became unreachable The heartbeat/fallback else branch never executed, causing the feed to silently swallow messages that should have been displayed as feed items.14ac551
-
fix(LOGIC-3): preserve &lang= in search filter buttons and search button handler
eec5179 -
fix(SEC-1,CodeQL#24): data-* attrs for connection-map evidence onclick -- prevents single-quote XSS
1c118c6
-
fix(UI-6): replace corrupted unicode chars in connection map legend with HTML entities
c12aeda -
fix(UI-2): set evidence panel width to min(460px,100vw) -- no longer overflows on 375px phones
d6e6ec5 -
fix(UI-1): add hamburger button and mobile nav drawer -- users can now navigate on screens narrower than 768px
9376839 -
fix(TEXT-1): update hardcoded '12 investigators' to '15' in How It Works and About page
5406493 -
fix(I18N-1,I18N-3): add mni/sat/ks to navbar language dropdown; restore all corrupted Indian script labels in search page dropdown
c44a433 -
fix(SEARCH-2,SEARCH-3): add datagov/crimereport filter buttons; add Arabic script U+0600-U+06FF to ALLOWED_CHARS for Urdu/Sindhi search
297cc9e -
fix(LOGIC-5): add .risk-badge--NONE CSS rule -- entities with score=0 had unstyled badge
bba794a -
fix(LOGIC-4): persist language selection to localStorage -- language now survives page refresh
db4b345 -
fix(SEC-1,CodeQL#24): sanitize entity name, type, profile.overview k/v, and risk.explanation before innerHTML injection
8ad162f -
fix(FEED-1): add pipeline-message guard in liveFeed view -- admin system message no longer shown as fake intelligence
f171783 -
fix(FEED-2): reset connect._retries=0 on each _connectFeedToHome() call -- prevents permanent feed silence after repeated navigation
0b32f6d -
fix(JS-4,FEED-4): stop D3 simulation and close WebSocket on route navigation -- prevents CPU/memory leak
4d6372a -
fix(JS-2): remove duplicate GraphRenderer._currentSimulation assignment in graph.js
4d11956 -
fix(DUP-1): remove duplicate search input prefill block -- same code appeared twice with different variable names
19b580c -
fix(JS-1 CRITICAL): remove 2 duplicate const _langLabelCache declarations -- caused SyntaxError crash in strict-mode browsers
a4a025f
-
fix(SyntaxError): move _stats_cache vars to module level; global declaration must precede use -- fixes CI SyntaxError on line 142
41a604c
-
fix(M-03): add @media overrides for inline grid-template-columns -- fixes mobile layout overflow
13a53d3 -
fix(M-10,M-11,L-06): deterministic node ID fallback; container-scoped SVG marker; store simulation for tab-switch cleanup
11b0978 -
fix(M-05): cache language labels in applyLanguage() -- avoids redundant API calls on rapid language switching
8358396 -
fix(M-05): cache language labels in applyLanguage() -- avoids redundant API calls on rapid language switching
53b2127 -
fix(H-01): sanitize event.title/detail/date/source in Timeline.render() -- XSS via scraped Neo4j data
d7d6d05 -
fix(C-01,H-03): pre-fill search input with current query; sanitize entity id in not-found XSS
8d3abc6 -
fix(BUG-M9,BUG-C2): pass driver kwarg in run_investigator; update 12->15 investigators
18aeb5b
-
fix(M-06): back button checks referrer before history.back() -- shared/direct links go to search page instead of external site
1113f2b -
fix(L-01): restore Urdu (اردو) and Sindhi (سنڌي) native script labels in navbar language dropdown
9c402cd -
fix(M-10,M-11,L-06): deterministic fallback node IDs; container-scoped SVG marker IDs; stop D3 simulation on tab switch
0fad33c -
fix(M-07): add max 20 retry cap to WebSocket reconnect loops -- prevents infinite background polling when HF Space is sleeping
fad15e0 -
fix(M-05): cache language labels in applyLanguage() -- avoids redundant API calls on rapid language switching
729c0c5