# BlackAdder

Case study 05 | Co-built | Private

A private knowledge base for companies that can't send their documents to outside AI services. Ask a question, get an answer from your own files, and click any citation to see exactly where it came from.

- Role: Co-built as our McMaster senior engineering project. I worked mainly on the front end.
- Timeline: January 2026 to March 2026
- Stack: React, TypeScript, Python, FastAPI, Qdrant, .NET, Docker
- Deployment: On-premise, private

0 documents sent to outside AI services

3 services: web app, API and identity

4 hardware setups, from GPUs to Apple Silicon

129 commits in one semester

The problem

## Company knowledge is everywhere, and it can't leave the building.

Policies, specs and reports live across drives and inboxes. Public AI tools could answer questions about them, but **the data can't leave**, and different teams aren't allowed to see each other's documents.

Before

- × Answers buried across drives
- × Outside AI tools not allowed
- × No control over who sees what
- × No way to check where an answer came from

After

- → Ask in plain language
- → Models run on the company's own hardware
- → Answers only from what you're allowed to see
- → Every answer cites its sources

What we built

## What we built

A chat interface on top of a governed document library, with company sign-in and an approval step before anything enters the knowledge base.

### Ask

- → Chat over your own documents
- → Answers with clickable citations
- → Document preview from any citation
- → Collections you can access, shown up front

### Govern

- → Sign in with the company's SSO
- → Roles synced from the company directory
- → Uploads approved before they're indexed
- → Archive and management views for admins

### Run

- → Local language models, no outside calls
- → Background ingestion with retries
- → Structured logs for every service
- → Runs on NVIDIA, CPU-only or Apple Silicon

The hard part

## Answers only from what you're allowed to see.

Each role gets its own isolated collection in the vector database. A question searches the public collection plus **only the collections your roles allow**, and the answer shows its sources so people can check it.

Public Engineering Sales Executive

1

Sign in

Company SSO with OIDC and PKCE brings your roles with you.

2

Search

Your allowed collections are searched in parallel in Qdrant.

3

Answer

A model on the company's own hardware writes from those passages.

4

Cite

Every source is linked, and opens a preview of the document.

New role in the directory: a sync job creates its collection automatically.

New upload: it waits for approval before anyone can search it.

How it's built

## Privacy and engineering

### Isolation by role

One collection per role keeps teams' documents apart at the data layer.

### Standard sign-in

OAuth2 and OpenID Connect, federated to Entra ID or ADFS.

### Reliable ingestion

Uploads are processed in the background with retries and a dead-letter queue.

### Swap the model

Ollama or vLLM, chosen by configuration, not code.

### Observable

Every service logs to one place, so problems are traceable.

### Built as a team

Planned and tracked against a shared ticket board, change by change.

Screens

![BlackAdder knowledge base documents](https://abbasvirjee.com/static/img/blackadder-wide.webp)

Collections, owners and documents at a glance.

![BlackAdder approvals queue](https://abbasvirjee.com/static/img/blackadder-a.webp)

Admins review uploads before they're indexed.

![BlackAdder document upload](https://abbasvirjee.com/static/img/blackadder-b.webp)

Upload a document, tag it and choose where it belongs.

Answers from company documents, without the documents leaving the company.

BlackAdder was delivered as our senior engineering project: a working, on-premise system that answers from a company's own documents, respects who can see what, and shows its work.
