Getting Started
Welcome to the Witness Project investigative platform. Start here if you're new.
1
Create Your Profile
Go to Profiles and create an investigator handle. Use a codename — no real names. Pick a color and specialty. Your profile ties your workspace and chat identity together.
2
Review the Case Dashboard
Go to Dashboard and review the current case data — entities, timeline, leads, tail numbers. Use the search bar to find specific names or events.
3
Review Intel Cards
Go to Intel to see visual entity cards with photos, notes, and timeline connections. Click any card to expand its full profile.
4
Set Up Your Workspace
Go to Workspace to add URLs, documents, and notes to your personal research space. Your workspace is private by default.
5
Join the Team Chat
Go to Chat and set your handle to start messaging the team. Real-time, all investigators see all messages.
Platform Guide
PageWhat It Does
DashboardFull case database — entities, timeline, leads, tail numbers, contradictions, findings. Search everything. Log new findings directly.
IntelVisual entity cards with photos pulled from Wikipedia. Click any card for full profile, notes, and timeline. Override photos with custom URLs.
WikiTeam knowledge base. Filter by category. Expand entries. Add new entries — they save to Google Sheets automatically.
WorkspaceYour personal research space. Add URLs, upload documents, write notes. Private by default — toggle to share with team.
CollaborateShared team workspace for joint investigations. Create projects, add items, everyone can contribute.
ChatReal-time team messaging. Set your handle before sending. Messages load last 100, polls every 3 seconds.
ConverterConvert any file to TXT or Markdown for AXIOM. PDF, DOCX, EPUB, JSON, images with OCR, and more. Everything stays in your browser.
ToolsCurated OSINT and investigative resources. 15 built-in tools. Add your own for the team.
TransactionsForensic financial ledger. Log money flows between entities, filter by status/instrument, view net flow per entity. Requires Supabase table setup.
ProfilesCreate and manage investigator identities. Handles only — no real names. Activate a profile to link it to your session.
The Dashboard has three extra tabs beyond the default: Cross-Ref ⚡ (automated internal queries), Assets (asset registry), and Findings (log new findings). The + FAB button on every page scrolls directly to the Log Finding form.
Forensic Accounting
All financial data lives in Supabase. No external calls are made — investigators enter data from verified source documents.

Transaction Ledger

Go to Transactions to log, filter, and analyze financial flows between entities.
FieldWhat to Enter
DateDate of the transaction as it appears in the source document.
Amount / CurrencyNumeric amount. Use the currency dropdown (USD, EUR, GBP, etc.).
From / To EntityStart typing — the field autocompletes from your known entity list in Google Sheets.
InstrumentWire, Cash, Check, Crypto, Invoice, Asset Transfer, or Other.
Source DocDocument title or reference where this transaction was found (e.g. "Bank Statement 2022-Q3").
StatusConfirmed = primary source evidence. Alleged = secondary/reported. Disputed = contradicted elsewhere.
TagsComma-separated labels (e.g. "shell-company, offshore, wire-fraud").
The Entity Financial Summary panel on Transactions shows net flow per entity — total received minus total sent — calculated entirely from your logged transactions.

Asset Registry

The Assets tab on the Dashboard tracks physical and financial assets, beneficial ownership, and flags discrepancies.
FieldPurpose
Asset TypeReal Estate, Vehicle, Aircraft, Bank Account, Business, Investment, Crypto Wallet, Other.
Owner of RecordThe legal registered owner as shown in public records.
Beneficial OwnerThe actual controlling party — often different from the record owner in financial crimes.
Discrepancy FlagCheck this when the asset value doesn't match declared income or when beneficial/record owner mismatch is suspicious.

Cross-Reference Engine

The Cross-Ref ⚡ tab on the Dashboard runs four automated queries across all internal data simultaneously:
QueryWhat It Finds
Entity Overlap ScoreEntities that appear in the most data categories (timeline + transactions + leads + findings). High overlap = high investigative priority.
Unregistered TX EntitiesNames in your transaction ledger that don't match any known entity in your Google Sheets entity list — possible unknown actors.
Financial ContradictionsEntries in the Contradictions sheet where the description contains financial keywords (amount, payment, transfer, etc.).
Leads Without TimelineOpen/In-Progress leads whose subject entity has no corresponding timeline entry — potential investigative gaps.

Extract & Save (Converter Pipeline)

After converting any document in the Converter, click 🔍 Extract & Save to automatically detect financial data:
1
Convert the document
Upload a PDF, DOCX, image, or Discord export. Convert to text as normal.
2
Click Extract & Save
The tool scans the converted text for dollar amounts, dates, and entity name matches from your internal entity list.
3
Review the extraction modal
Detected amounts, dates, and entities are shown as clickable badges. Click any badge to pre-fill the quick transaction form.
4
Save as Transaction or Finding
Fill in the quick form and click Save Transaction, or use Save as Finding to flag the whole document extract for review.

Corporate Ownership (Intel Cards)

When viewing an entity card in Intel, the Corporate Structure & Ownership section appears if you have populated the following columns in your Google Sheets Entities tab:
ColumnContent
Column F (index 5)Parent_Entity — the parent company or controlling organization
Column G (index 6)Subsidiaries — comma-separated list of subsidiaries
Column H (index 7)Beneficial_Owner — the real controlling person or entity
Column I (index 8)Jurisdiction — country or state of incorporation
Column J (index 9)Reg_Date — date of incorporation or registration
Supabase tables required for Transactions and Assets must be created before those features work. Open the Transactions or Dashboard Assets tab while logged in — the SQL to create both tables is shown in an info box at the top of each page.
Discord Sync
There are two ways to get Discord data into the platform — a one-time JSON export (easiest) or an ongoing Python bot sync (most powerful).

Option 1 — DiscordChatExporter (One-Time Import)

1
Export your channel
Download DiscordChatExporter (free, open source). Run it, select your channel, export as JSON.
2
Open Converter
Go to Converter, click the JSON tab, and upload the exported .json file.
3
Convert and Extract
The converter detects the Discord format automatically and formats it as a timestamped message log. Then click 🔍 Extract & Save to pull out financial data.

Option 2 — discord_sync.py (Ongoing Sync)

The discord_sync.py script in the project folder reads your Discord channel history and posts findings + transactions directly to Supabase.
1
Create a Discord Bot
Go to discord.com/developers/applications → New Application → Bot → Copy Token. Enable Message Content Intent and Server Members Intent under Bot settings.
2
Invite the bot to your server
Use the OAuth2 URL in the discord_sync.py header. Replace YOUR_APP_ID with your Application ID from the developer portal.
3
Configure the script
Open discord_sync.py, set BOT_TOKEN and CHANNEL_IDS (right-click a channel → Copy Channel ID in Discord with Developer Mode on).
4
Run the script
pip install requests then python discord_sync.py. For future runs use --since 2024-06-01 to only pull new messages. Use --dry-run to preview without saving.
discord_sync.py loads your entity list from Google Sheets automatically — any message mentioning a known entity name or a dollar amount gets saved as a Finding in Supabase, and optionally as a Transaction record too.
AXIOM Discord Bot
AXIOM is the AI investigative analyst running on your Discord server. Tag @Axiom to activate in any channel.
All searches check the internal master file first. Reply YES to authorize external searches.

Files & Analysis

CommandDescription
Upload any fileAuto-scans and analyzes PDF, TXT, MD, PNG, JPG. Extracts entities, timeline, leads, tail numbers into Google Sheets.
Reply + @AxiomReply to any Discord message and tag @Axiom to analyze the content of that message.
@Axiom YESConfirm processing of large files or authorize external searches.

Search Commands

CommandDescription
!search [query]Checks internal master file first, then asks permission to search the web.
!news [query]News search — internal first, then external news sources.
!lookup [entity]Deep entity lookup — combines web search, news, and SEC/corporate filings.
!youtube [url]Fetches video transcript and analyzes it as case evidence.

Case Intelligence

CommandDescription
!synthesizeFull case synthesis from the master file. Generates leads, cross-references, suppression patterns.
!readhistoryScans all files ever uploaded to this channel and synthesizes them.
!exportDownloads a complete case report as a .txt file — all entities, timeline, leads, tail numbers.

Database Commands

CommandDescription
!masterView the last 30 entries in the server-wide master file.
!entitiesLast 20 entities logged.
!timelineLast 20 timeline events.
!leadsAll active leads with status.
!tailnumbersAll aircraft tail numbers tracked.
!conflictsAll contradictions flagged.
!updatelead [title] | [status] | [notes]Update a lead status directly from Discord. Status: OPEN / IN PROGRESS / CONFIRMED / CLOSED
!searchesSearch history log.
!memoryMaster file status — total record count.
!queueCurrent job queue — how many files are processing.

AXIOM Classification System

TagMeaning
[CONFIRMED]Directly supported by evidence in case files.
[INFERRED]Reasonably implied by evidence but not directly stated.
[SPECULATIVE]Possible interpretation, limited evidence.
[MISSING]Critical gap in evidence — needs investigation.
[CONFLICT]Directly contradicted by other evidence.
[FLAG]Requires attention or follow-up.
[SUPPRESS-ALERT]Evidence of information suppression or narrative management.
[SURVIVOR-ALERT]Finding directly related to victim or survivor welfare.
📂 INTERNALFinding is from the internal master case file.
🌐 EXTERNALFinding is from a web or news search.
Investigation Workflow
The recommended workflow for new evidence:
1
Convert the file
If the file is a PDF, EPUB, DOCX, or image — go to Converter and convert it to .txt first. This makes AXIOM faster and cheaper to process.
2
Upload to AXIOM
In Discord, tag @Axiom and attach the .txt file. AXIOM will scan it, estimate processing time, and queue it automatically.
3
Review extraction
AXIOM posts an embed showing new entities found, timeline events added, and any contradictions. Review these and flag anything that looks wrong.
4
Search internal first
Use !search before going to external sources. If AXIOM finds internal records, review them. Only go external when internal data is exhausted.
5
Log your findings
Any connections you identify manually — go to the Dashboard and use the Log Finding panel. This creates a permanent record tied to your handle.
6
Synthesize weekly
Run !synthesize once a week to get a fresh cross-referenced synthesis of everything in the master file. This updates the leads list on the website automatically.
Never upload files containing victim personal information, testimony, or identifying details to AXIOM. Keep sensitive victim data completely off this platform.
Operational Security
The password gate on this site is a deterrent, not true security. Treat the dashboard as semi-public.
RuleWhy
Handles only — no real namesIn chat, profiles, and Discord. Anyone who gains access to the platform cannot identify you.
Rotate the password monthlyEdit auth.js and redeploy. Takes 2 minutes. Locks out anyone who had the old password.
Don't share the Cloudflare loginOnly share the site URL and password with investigators. Keep the hosting account private.
Sensitive findings in Discord onlyAXIOM chats are not public. The website is. Keep the most sensitive details in Discord.
Assume Supabase data is accessibleChat and workspace data is in Supabase. Treat it as if it could be read by others.
Don't store victim data anywhere on this platformVictim names, testimony, identifying information — keep this completely off the platform.
Back up Google Sheets weeklyFile → Download → Excel. This is your entire case database. Protect it.
FAQ
Why does AXIOM say "No internal records found" for something I know is in the database? +
The internal search uses keyword matching. If you spelled the name differently from how it was extracted, it won't find it. Try shorter search terms — just a surname or key word rather than a full name.
The website shows old data. How do I refresh it? +
The website reads from Google Sheets CSV URLs which are cached by Google for a few minutes. Click the ↻ Refresh button on any page, or wait 5-10 minutes for Google's cache to update after new data is added.
AXIOM timed out processing a large PDF. What should I do? +
Convert the PDF to .txt first using the Converter page. Text files process 10x faster and cheaper. For very large documents, split them into sections of about 50 pages each.
How do I update a lead status? +
In Discord: @Axiom !updatelead [title keywords] | [status] | [notes]. Status options: OPEN, IN PROGRESS, CONFIRMED, CLOSED. The website will reflect the change after the next refresh.
Why don't entity photos show up for some entities? +
Photos are pulled automatically from Wikipedia. If Wikipedia doesn't have an article or photo for that entity, a placeholder with initials is shown instead. You can override this by clicking the entity card and pasting a custom image URL.
Can I add entries to the Wiki from outside Google Sheets? +
Yes — on the Wiki page, click "Suggest Wiki Entry". The form will copy the entry in the correct format to your clipboard. Paste it directly into a new row in the Wiki tab in Google Sheets.
How do I change the platform password? +
Open auth.js, find PASSWORD: 'witness2026', change it to your new password, save the file, and redeploy all 9 files to Cloudflare Pages. Takes about 2 minutes.
AXIOM is using the wrong vision model. How do I fix it? +
Check console.groq.com/docs/deprecations for the current vision model name. Open axiom_discord.py, find the model name in the run_groq function, update it, commit and push to GitHub. Railway will redeploy automatically.
How often should I run !synthesize? +
Once a week, or after a major batch of new files is uploaded. Synthesis reads the most recent 100 master file entries, so running it more often than weekly doesn't significantly change the output unless a lot of new data was added.
What happens to my workspace data if I clear my browser? +
Workspace items are stored in Supabase and persist permanently. Your active profile and login session are in sessionStorage and will be cleared when you close the browser — just log in and re-select your profile next time.
The Transactions or Assets page says the table doesn't exist. What do I do? +
Go to supabase.com → your project → SQL Editor. The Assets tab on Dashboard shows the SQL for the assets table. For the transactions table, use the SQL provided by your administrator (it was removed from the UI to keep the page clean). Run both scripts in the SQL Editor and the pages will work immediately.
Entity names aren't autocompleting in the Transaction form. Why? +
The autocomplete list loads from your Google Sheets entities tab. If the sheet cache is stale, click the ↻ Refresh button on the Dashboard (or Transactions page) to force a fresh pull. If the entity simply isn't in your sheet yet, add it there first.
The Cross-Ref tab shows no results. Is something broken? +
Cross-Ref runs entirely against data already loaded in memory. Make sure the Dashboard has finished loading (all six tabs show data counts). If transactions are empty, the unregistered-entity and financial-contradiction queries will return nothing by design — they need transaction records to compare against.
Extract & Save found no amounts or entities in my document. Why? +
Amount detection looks for $ signs and keywords like "million", "USD", etc. Entity matching requires the name to appear in your Google Sheets entities list. Check that your entity list is populated and refresh the sheet cache. For scanned PDFs, OCR quality affects whether numbers are recognised — try the Tesseract OCR convert option instead of PDF-parse.
How do I run discord_sync.py on a schedule automatically? +
On Windows: open Task Scheduler, create a basic task, set the trigger to daily or hourly, and set the action to run python with the full path to discord_sync.py and the --since flag set to yesterday's date. On Mac/Linux: add a cron job. The --since flag prevents re-importing old messages on each run.
Can I use the platform offline? +
Partially. The service worker caches all HTML, CSS, and JS so pages load offline. Google Sheets data is cached in localStorage for 15 minutes and falls back to the stale cache when offline. Supabase writes (sending messages, saving findings, logging transactions) require an internet connection.