# Project export: OrgWiki

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Turn fragmented organizational documents into structured, trusted knowledge—with AI-powered deduplication, conflict detection, and source-backed evidence.
- Devpost: https://devpost.com/software/orgwiki
- GitHub: https://github.com/karthikeyansrin/OrgWiki
- Demo: https://org-wiki-site.vercel.app/
- Video: https://www.youtube.com/embed/B8UX1xTFqas?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Karthikeyan Srinivasan (21 commits)

## Devpost submission (written by the team)

### Inspiration

Every organization accumulates years of documentation across PDFs, Word documents, Markdown files, shared drives, and internal repositories. Over time, this knowledge becomes duplicated, contradictory, outdated, and difficult to trust. Employees often spend significant time searching for information, only to find multiple versions of the same document with no clear indication of which one is correct. Most AI-powered documentation tools focus on retrieving existing information. I wanted to explore a different approach: what if AI could transform fragmented organizational documentation into a structured, trusted knowledge base before anyone even searched for it? That idea became OrgWiki.

### What it does

OrgWiki is an AI-powered organizational knowledge platform that converts collections of unstructured documents into curated organizational knowledge. A user uploads a ZIP containing company documentation. GPT-5.6 analyzes the entire document collection, discovers knowledge domains, identifies duplicate and conflicting information, and proposes a structured set of knowledge articles. It then generates evidence-backed articles with citations that can be reviewed by a human before publication. Published articles can be organized into Team Spaces, such as Technical, HR, Security, or Leave Policy, making trusted organizational knowledge accessible to employees through simple public links. Every published article can also be downloaded as Markdown for portability and version control. The complete workflow is: Upload → AI Discovery → AI Generation → Human Review → Publish → Team Spaces How I built it OrgWiki was built using a React frontend, an ASP.NET Core (.NET 9) backend, and PostgreSQL for persistence. The application follows a layered architecture with dedicated services for document ingestion, AI orchestration, review workflows, publishing, and public knowledge distribution. The AI pipeline intentionally separates two responsibilities: Knowledge Discovery – GPT-5.6 analyzes the uploaded document collection as a whole to identify topics, relationships, duplicate content, conflicts, and candidate knowledge articles. Knowledge Discovery – GPT-5.6 analyzes the uploaded document collection as a whole to identify topics, relationships, duplicate content, conflicts, and candidate knowledge articles. Knowledge Generation – GPT-5.6 generates structured Markdown articles with summaries, metadata, related articles, confidence scores, and evidence-backed citations. Knowledge Generation – GPT-5.6 generates structured Markdown articles with summaries, metadata, related articles, confidence scores, and evidence-backed citations. Every generated article enters a human review workflow before publication, ensuring AI assists knowledge creation without becoming the final decision maker. How GPT-5.6 was used GPT-5.6 powers the core intelligence of OrgWiki. Rather than acting as a chatbot, it performs structured knowledge transformation by: Discovering organizational knowledge across an entire document collection Identifying duplicate and conflicting documentation Generating structured knowledge articles Producing evidence-backed citations Suggesting relationships between articles Using GPT-5.6 as the reasoning engine allowed the application to move beyond document search into AI-assisted knowledge management. How Codex was used Codex significantly accelerated development throughout the project. It was used to implement and refine backend APIs, database models, authentication, frontend workflows, AI pipeline integration, review workflows, public Team Spaces, and Markdown export while preserving the overall architecture. This allowed me to spend more time designing the product, refining the AI workflow, and improving the end-to-end user experience instead of writing repetitive implementation code. Challenges One of the biggest challenges was balancing AI capability with trust. Generating articles is relatively straightforward; generating articles that people can confidently rely on is much harder. That led to several design decisions: Separating knowledge discovery from knowledge generation Requiring human review before publication Including evidence-backed citations for every generated article Keeping published knowledge as the only public source of truth Another challenge was designing prompts that consistently produced structured JSON outputs suitable for automated processing while remaining efficient enough to keep API usage practical. What I learned Building OrgWiki reinforced that successful AI applications require much more than connecting an LLM to a user interface. Designing reliable AI systems involves prompt engineering, validation, structured outputs, workflow orchestration, human oversight, and thoughtful product design. The project also deepened my understanding of building scalable backend architectures with ASP.NET Core, designing AI-assisted workflows, and creating products where AI augments human decision-making instead of replacing it.

### What's next

Future development will focus on enterprise deployment and integrations, including SharePoint, Google Drive, Confluence, incremental synchronization, organization workspaces, role-based access control, knowledge graph visualization, and support for self-hosted local language models for organizations with strict security requirements. The long-term vision is for OrgWiki to become an AI-powered organizational knowledge platform that helps companies preserve, organize, and continuously improve their collective knowledge while keeping humans in control.

## README (from the GitHub repository)

# OrgWiki

> Transform fragmented organizational documents into trusted, searchable knowledge.

OrgWiki is an AI-assisted organizational knowledge platform. It turns a bounded ZIP archive of PDFs, DOCX files, Markdown, and text documents into a structured knowledge map, citation-backed draft articles, and a human-reviewed knowledge base.

It is not a chat-with-your-files application. OrgWiki refactors the organization’s knowledge before it is published: it discovers domains, identifies duplicate and conflicting guidance, generates grounded articles, and keeps people in control of publication.

## The product story

```text
Source documents
  -> Document ingestion
  -> AI knowledge discovery
  -> Validated knowledge map
  -> AI knowledge generation
  -> Human review
  -> Explicit publishing
  -> Searchable knowledge base and public Team Spaces
```

Published articles may also be curated into **Team Spaces**: public, read-only collections that employees can browse without signing in.

## Key capabilities

- Safe ZIP ingestion for PDF, DOCX, Markdown, and text documents.
- Corpus-level discovery of domains, topics, relationships, duplicates, conflicts, and potentially outdated knowledge.
- Citation-backed Markdown article generation.
- Exact evidence validation against normalized source content.
- Human edit, approve, reject, publish, and republish workflow.
- Private, user-owned workspaces with JWT authentication.
- Published knowledge browsing, keyword filtering, and source evidence.
- Public Team Spaces with scoped search and Markdown downloads.

## Architecture

```text
React + TypeScript (Vite)
  -> ASP.NET Core .NET 8 API
  -> PostgreSQL

API AI provider selection
  -> Replay providers for offline development
  -> OpenAI provider for deliberate Live execution
```

The backend uses Entity Framework Core with PostgreSQL/Npgsql. The frontend uses React, React Router, React Query, Tailwind CSS, and Motion.

## AI design and key technical decisions

### Two controlled GPT-5.6 stages

OrgWiki deliberately avoids per-document, per-topic, or agent-loop AI usage.

1. **Knowledge Discovery** makes exactly one bounded provider call for an eligible upload. It analyzes the complete deterministic corpus and produces a knowledge map.
2. **Knowledge Generation** makes exactly one bounded provider call for an analysis. It generates all proposed articles in a single response.

Review, publishing, search, Team Spaces, and citation display are deterministic application features and make no AI calls.

The configured model is read from `OPENAI_MODEL`; the checked-in default is `gpt-5.6`. Live execution is an explicit opt-in through `OPENAI_MODE=Live` and requires `OPENAI_API_KEY`.

### Why this approach

- **Cost control:** the MVP bounds archive size, document count, normalized corpus size, and output tokens before any Live request.
- **Trust:** discovery and generation responses are validated before persistence. Source document references, cross-references, confidence values, and conflict evidence are checked by the application.
- **Evidence:** conflict and article citations must be exact substrings of normalized source content; fabricated or paraphrased evidence is rejected.
- **Human governance:** generated articles remain Pending Review until a person explicitly approves and publishes them.
- **Safe development:** Replay is the default mode and makes zero OpenAI requests, enabling full workflow and UI development without API spend.

### How Codex accelerated implementation

Codex was used as an implementation partner across the MVP: designing and implementing the phased workflow, focused test coverage, EF Core migration and SQL-script workflow, deterministic Replay support, security hardening, frontend UX polish, and deployment configuration.

Key decisions were made explicitly in code rather than delegated to the model: one provider call per AI stage, no automatic AI retries, strict structured output, exact evidence verification, transactional persistence, manual database migration application, and human approval before publication.

## Prerequisites

- .NET 8 SDK
- Node.js 20 or newer
- PostgreSQL 15+ or a Supabase PostgreSQL database
- A modern browser

Docker is optional for backend deployment. See [backend/Dockerfile](backend/Dockerfile) for the Render-oriented backend image.

## Quick start

### 1. Create a PostgreSQL database and apply the schema

OrgWiki does **not** apply EF migrations at application startup and does **not** use `dotnet ef database update` as its deployment workflow.

For a fresh database, manually review and execute these SQL files in this exact order:

1. [backend/orgwiki-initial-schema.sql](backend/orgwiki-initial-schema.sql)
2. [backend/orgwiki-add-authentication-foundation.sql](backend/orgwiki-add-authentication-foundation.sql)
3. [backend/orgwiki-add-user-owned-workspaces.sql](backend/orgwiki-add-user-owned-workspaces.sql)
4. [backend/orgwiki-add-team-spaces.sql](backend/orgwiki-add-team-spaces.sql)

For Supabase, create the project, open the SQL Editor, confirm the database is empty, review each script, and execute each one once. Verify the matching entries in `__EFMigrationsHistory` before configuring the backend.

### 2. Configure the backend

Set environment variables in your shell, IDE launch profile, or .NET User Secrets. The sample `backend/.env.example` is a reference file; it is not automatically loaded by ASP.NET Core.

PowerShell example:

```powershell
$env:DATABASE_URL = "Host=localhost;Port=5432;Database=orgwiki;Username=postgres;Password=YOUR_PASSWORD"
$env:JWT_SIGNING_KEY = "replace-with-a-random-secret-at-least-32-characters-long"
$env:OPENAI_MODE = "Replay"
$env:OPENAI_MODEL = "gpt-5.6"
$env:CORS__ALLOWEDORIGINS__0 = "http://localhost:5173"
```

Required settings:

| Variable | Purpose |
|---|---|
| `DATABASE_URL` | PostgreSQL/Npgsql connection string. |
| `JWT_SIGNING_KEY` | Random signing secret, at least 32 characters. Never commit it. |
| `OPENAI_MODE` | `Replay` for safe local development, or `Live` for a deliberate model request. |
| `OPENAI_MODEL` | Configured Live model identifier; default configuration is `gpt-5.6`. |
| `OPENAI_API_KEY` | Required only when `OPENAI_MODE=Live`. |
| `CORS__ALLOWEDORIGINS__0` | Frontend origin allowed to call the API. |
| `OPENAI_VERBOSE_LOGGING` | Optional `true` for request metadata and usage diagnostics; defaults to `false`. |

`SUPABASE_URL`, `SUPABASE_KEY`, and `SUPABASE_STORAGE_BUCKET` are reserved configuration placeholders. The current MVP uses direct PostgreSQL through Npgsql and local archive storage; it does not use a Supabase SDK or Supabase Storage client.

Start the API:

```bash
cd backend
dotnet restore
dotnet run --project src/OrgWiki.API
```

The local API health endpoint is available at `http://localhost:5051/health` when using the default launch profile. Swagger is enabled only in Development.

### 3. Configure and start the frontend

```bash
cd frontend
copy .env.example .env.local
npm install
npm run dev
```

On macOS or Linux, use `cp .env.example .env.local` instead of `copy`.

Set `VITE_API_BASE_URL` in `frontend/.env.local` to the backend URL. For local development, the sample value is:

```text
VITE_API_BASE_URL=http://localhost:5051
```

Open the Vite URL shown in the terminal, register an account, and begin importing documents.

## Replay demo data

No ZIP fixture is committed to the repository. Replay works with any small supported archive and never calls OpenAI.

To make a simple local demo archive, create two small files such as:

```text
demo-corpus/
  Engineering/Authentication.txt
  HR/LeavePolicy.md
```

Then create `DemoDocs.zip` from the files. In PowerShell:

```powershell
Compress-Archive -Path .\demo-corpus\* -DestinationPath .\DemoDocs.zip
```

Upload the archive while `OPENAI_MODE=Replay`. The Replay discovery provider maps the first one or two parsed documents into a deterministic fixture-compatible knowledge map, and the Replay g

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 127 recognized source files, 486 KB.
- C# (language) — detected in the code
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- OpenAI (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code
- Supabase (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 150)

```
.gitignore
backend/.dockerignore
backend/.env.example
backend/Dockerfile
backend/orgwiki-add-authentication-foundation.sql
backend/orgwiki-add-team-spaces.sql
backend/orgwiki-add-user-owned-workspaces.sql
backend/orgwiki-initial-schema.sql
backend/OrgWiki.sln
backend/src/OrgWiki.API/appsettings.Development.json
backend/src/OrgWiki.API/appsettings.json
backend/src/OrgWiki.API/Authentication/HttpContextCurrentUser.cs
backend/src/OrgWiki.API/Authentication/JwtAccessTokenService.cs
backend/src/OrgWiki.API/Controllers/AnalysesController.cs
backend/src/OrgWiki.API/Controllers/AuthController.cs
backend/src/OrgWiki.API/Controllers/GenerationsController.cs
backend/src/OrgWiki.API/Controllers/HealthController.cs
backend/src/OrgWiki.API/Controllers/KnowledgeBaseController.cs
backend/src/OrgWiki.API/Controllers/PublicTeamSpacesController.cs
backend/src/OrgWiki.API/Controllers/ReviewController.cs
backend/src/OrgWiki.API/Controllers/TeamSpacesController.cs
backend/src/OrgWiki.API/Controllers/UploadsController.cs
backend/src/OrgWiki.API/Options/JwtOptions.cs
backend/src/OrgWiki.API/Options/OpenAiOptions.cs
backend/src/OrgWiki.API/Options/StorageOptions.cs
backend/src/OrgWiki.API/OrgWiki.API.csproj
backend/src/OrgWiki.API/Program.cs
backend/src/OrgWiki.API/Properties/launchSettings.json
backend/src/OrgWiki.API/replay-knowledge-discovery.json
backend/src/OrgWiki.API/replay-knowledge-generation.json
backend/src/OrgWiki.Application/Analysis/KnowledgeAnalysisOptions.cs
backend/src/OrgWiki.Application/Analysis/KnowledgeDiscoveryContracts.cs
backend/src/OrgWiki.Application/Analysis/KnowledgeGenerationContracts.cs
backend/src/OrgWiki.Application/Authentication/AuthenticationContracts.cs
backend/src/OrgWiki.Application/DependencyInjection.cs
backend/src/OrgWiki.Application/Ingestion/IContentNormalizer.cs
backend/src/OrgWiki.Application/Ingestion/IDocumentParser.cs
backend/src/OrgWiki.Application/Ingestion/IFileStorageService.cs
backend/src/OrgWiki.Application/Ingestion/IIngestionService.cs
backend/src/OrgWiki.Application/Ingestion/IngestionOptions.cs
backend/src/OrgWiki.Application/Ingestion/IZipArchiveExtractor.cs
backend/src/OrgWiki.Application/KnowledgeBase/KnowledgeBaseContracts.cs
backend/src/OrgWiki.Application/OrgWiki.Application.csproj
backend/src/OrgWiki.Application/Review/ReviewContracts.cs
backend/src/OrgWiki.Application/TeamSpaces/TeamSpaceContracts.cs
backend/src/OrgWiki.Domain/Analysis/AiMode.cs
backend/src/OrgWiki.Domain/Analysis/GeneratedArticle.cs
backend/src/OrgWiki.Domain/Analysis/GeneratedArticleCitation.cs
backend/src/OrgWiki.Domain/Analysis/GeneratedArticleStatus.cs
backend/src/OrgWiki.Domain/Analysis/KnowledgeAnalysis.cs
backend/src/OrgWiki.Domain/Analysis/KnowledgeAnalysisStatus.cs
backend/src/OrgWiki.Domain/Analysis/KnowledgeGeneration.cs
backend/src/OrgWiki.Domain/Analysis/KnowledgeGenerationStatus.cs
backend/src/OrgWiki.Domain/Authentication/User.cs
backend/src/OrgWiki.Domain/Ingestion/Document.cs
backend/src/OrgWiki.Domain/Ingestion/DocumentProcessingStatus.cs
backend/src/OrgWiki.Domain/Ingestion/DocumentType.cs
backend/src/OrgWiki.Domain/Ingestion/Upload.cs
backend/src/OrgWiki.Domain/Ingestion/UploadStatus.cs
backend/src/OrgWiki.Domain/OrgWiki.Domain.csproj
backend/src/OrgWiki.Domain/TeamSpaces/TeamSpace.cs
backend/src/OrgWiki.Domain/TeamSpaces/TeamSpaceArticle.cs
backend/src/OrgWiki.Infrastructure/Analysis/DeterministicCorpusBuilder.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeAnalysisService.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeDiscoveryPrompt.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeDiscoverySchema.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeDiscoveryValidator.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeGenerationContextBuilder.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeGenerationPrompt.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeGenerationSchema.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeGenerationService.cs
backend/src/OrgWiki.Infrastructure/Analysis/KnowledgeGenerationValidator.cs
backend/src/OrgWiki.Infrastructure/Analysis/OpenAiKnowledgeDiscoveryProvider.cs
backend/src/OrgWiki.Infrastructure/Analysis/OpenAiKnowledgeGenerationProvider.cs
backend/src/OrgWiki.Infrastructure/Analysis/OpenAiProviderException.cs
backend/src/OrgWiki.Infrastructure/Analysis/OpenAiVerboseLogger.cs
backend/src/OrgWiki.Infrastructure/Analysis/ReplayKnowledgeDiscoveryProvider.cs
backend/src/OrgWiki.Infrastructure/Analysis/ReplayKnowledgeGenerationProvider.cs
backend/src/OrgWiki.Infrastructure/Authentication/AuthenticationService.cs
backend/src/OrgWiki.Infrastructure/DependencyInjection.cs
backend/src/OrgWiki.Infrastructure/Ingestion/ContentNormalizer.cs
backend/src/OrgWiki.Infrastructure/Ingestion/DocumentParser.cs
backend/src/OrgWiki.Infrastructure/Ingestion/DocxDocumentParser.cs
backend/src/OrgWiki.Infrastructure/Ingestion/IngestionService.cs
backend/src/OrgWiki.Infrastructure/Ingestion/MarkdownDocumentParser.cs
backend/src/OrgWiki.Infrastructure/Ingestion/PdfDocumentParser.cs
backend/src/OrgWiki.Infrastructure/Ingestion/SafeZipArchiveExtractor.cs
backend/src/OrgWiki.Infrastructure/Ingestion/TextDocumentParser.cs
backend/src/OrgWiki.Infrastructure/KnowledgeBase/KnowledgeBaseService.cs
backend/src/OrgWiki.Infrastructure/OrgWiki.Infrastructure.csproj
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260715142812_InitialOrgWikiSchema.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260715142812_InitialOrgWikiSchema.Designer.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260716132224_AddAuthenticationFoundation.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260716132224_AddAuthenticationFoundation.Designer.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260716141153_AddUserOwnedWorkspaces.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260716141153_AddUserOwnedWorkspaces.Designer.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260720125850_AddTeamSpaces.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/20260720125850_AddTeamSpaces.Designer.cs
backend/src/OrgWiki.Infrastructure/Persistence/Migrations/OrgWikiDbContextModelSnapshot.cs
backend/src/OrgWiki.Infrastructure/Persistence/OrgWikiDbContext.cs
backend/src/OrgWiki.Infrastructure/Review/ReviewService.cs
backend/src/OrgWiki.Infrastructure/Storage/LocalFileStorageService.cs
backend/src/OrgWiki.Infrastructure/TeamSpaces/PublicTeamSpaceService.cs
backend/src/OrgWiki.Infrastructure/TeamSpaces/TeamSpaceService.cs
backend/tests/OrgWiki.Infrastructure.Tests/AuthenticationTests.cs
backend/tests/OrgWiki.Infrastructure.Tests/IngestionTests.cs
backend/tests/OrgWiki.Infrastructure.Tests/OpenAiVerboseLoggingTests.cs
backend/tests/OrgWiki.Infrastructure.Tests/OrgWiki.Infrastructure.Tests.csproj
backend/tests/OrgWiki.Infrastructure.Tests/TeamSpaceTests.cs
frontend/.env.example
frontend/.gitignore
frontend/.oxlintrc.json
frontend/index.html
frontend/package.json
frontend/src/api/client.ts
frontend/src/App.tsx
frontend/src/auth/AuthContext.tsx
frontend/src/auth/ProtectedRoute.tsx
frontend/src/components/AppFooter.tsx
frontend/src/components/AppLayout.tsx
[30 more files omitted for size]
```

### Dependencies

- frontend/package.json: @tailwindcss/vite@^4.3.2, @tanstack/react-query@^5.101.2, @types/node@^24.13.2, @types/react@^19.2.17, @types/react-dom@^19.2.3, @vitejs/plugin-react@^6.0.3, lucide-react@^1.24.0, oxlint@^1.71.0, react@^19.2.7, react-dom@^19.2.7, react-router-dom@^7.18.1, tailwindcss@^4.3.2, typescript@~6.0.2, vite@^8.1.1

### Recent commits (newest first)

- updated README & added minor fixes
- spaces redirect issue fix
- added docker file
- updated appsettings.json
- security fixes impl
- updated README
- added footer
- new feat: team spaces
- rearranged files
- added UX refinements
- integration and UX fixes
- updated README
- openAI integration impl
- jwt auth impl
- fixed nav issues
- phase 6 impl: publish flow
- phase 5 impl: review workflow
- phase 4 impl: knowledge refactor
- phase 3 impl: knowledge discovery
- phase 2 impl: upload pipeline

## Key source files (fetched from GitHub, selected and truncated for size)

### frontend/package.json

```
{
  "name": "orgwiki-frontend",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "oxlint",
    "preview": "vite preview"
  },
  "dependencies": {
    "@tanstack/react-query": "^5.101.2",
    "lucide-react": "^1.24.0",
    "react": "^19.2.7",
    "react-dom": "^19.2.7",
    "react-router-dom": "^7.18.1"
  },
  "devDependencies": {
    "@tailwindcss/vite": "^4.3.2",
    "@types/node": "^24.13.2",
    "@types/react": "^19.2.17",
    "@types/react-dom": "^19.2.3",
    "@vitejs/plugin-react": "^6.0.3",
    "oxlint": "^1.71.0",
    "tailwindcss": "^4.3.2",
    "typescript": "~6.0.2",
    "vite": "^8.1.1"
  }
}

```

### backend/Dockerfile

```
# Build from the backend directory. Render should use `backend` as the root directory.
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

COPY ["src/OrgWiki.Domain/OrgWiki.Domain.csproj", "src/OrgWiki.Domain/"]
COPY ["src/OrgWiki.Application/OrgWiki.Application.csproj", "src/OrgWiki.Application/"]
COPY ["src/OrgWiki.Infrastructure/OrgWiki.Infrastructure.csproj", "src/OrgWiki.Infrastructure/"]
COPY ["src/OrgWiki.API/OrgWiki.API.csproj", "src/OrgWiki.API/"]

RUN dotnet restore "src/OrgWiki.API/OrgWiki.API.csproj"

COPY . .
WORKDIR /src/src/OrgWiki.API
RUN dotnet publish "OrgWiki.API.csproj" --configuration Release --output /app/publish --no-restore /p:UseAppHost=false

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app

# Render's default web-service port is 10000. Database migrations remain a manual operation.
ENV ASPNETCORE_ENVIRONMENT=Production \
    ASPNETCORE_URLS=http://+:10000 \
    INGESTION__LOCALSTORAGEPATH=/var/orgwiki/storage \
    DOTNET_EnableDiagnostics=0

RUN mkdir -p /var/orgwiki/storage && chown -R app:app /var/orgwiki
COPY --from=build --chown=app:app /app/publish .

USER app
EXPOSE 10000

ENTRYPOINT ["dotnet", "OrgWiki.API.dll"]

```

### frontend/src/main.tsx

```typescript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { BrowserRouter } from 'react-router-dom'
import './index.css'
import App from './App.tsx'
import { AuthProvider } from './auth/AuthContext.tsx'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 1,
      refetchOnWindowFocus: false,
    },
  },
})

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <BrowserRouter>
        <AuthProvider><App /></AuthProvider>
      </BrowserRouter>
    </QueryClientProvider>
  </StrictMode>,
)

```

### frontend/src/App.tsx

```typescript
import { Navigate, Route, Routes } from 'react-router-dom'
import { AppLayout } from './components/AppLayout'
import { ImportPage } from './pages/ImportPage'
import { UploadDetailsPage } from './pages/UploadDetailsPage'
import { UploadsPage } from './pages/UploadsPage'
import { AnalysisPage } from './pages/AnalysisPage'
import { GeneratedArticlesPage } from './pages/GeneratedArticlesPage'
import { ReviewDashboardPage } from './pages/ReviewDashboardPage'
import { ReviewArticlePage } from './pages/ReviewArticlePage'
import { KnowledgeBasePage } from './pages/KnowledgeBasePage'
import { KnowledgeArticlePage } from './pages/KnowledgeArticlePage'
import { LandingPage } from './pages/LandingPage'
import { AuthPage } from './pages/AuthPage'
import { ProtectedRoute } from './auth/ProtectedRoute'
import { TeamSpacesPage } from './pages/TeamSpacesPage'
import { TeamSpacePage } from './pages/TeamSpacePage'
import { TeamSpaceArticlePage } from './pages/TeamSpaceArticlePage'
import { AppFooter } from './components/AppFooter'

function App() {
  return <>
    <Routes>
      <Route path="/" element={<LandingPage />} />
      <Route path="/auth" element={<AuthPage />} />
      <Route path="/spaces" element={<TeamSpacesPage />} />
      <Route path="/spaces/:slug" element={<TeamSpacePage />} />
      <Route path="/spaces/:slug/:articleSlug" element={<TeamSpaceArticlePage />} />
      <Route element={<ProtectedRoute />}>
        <Route element={<AppLayout />}>
          <Route path="dashboard" element={<Navigate to="/import" replace />} />
          {/* <Route path="system" element={<SystemPage />} /> */}
          <Route path="import" element={<ImportPage />} />
          <Route path="uploads" element={<UploadsPage />} />
          <Route path="uploads/:uploadId" element={<UploadDetailsPage />} />
          <Route path="analyses/:analysisId" element={<AnalysisPage />} />
          <Route path="generations/:generationId" element={<GeneratedArticlesPage />} />
          <Route path="review" element={<ReviewDashboardPage />} />
          <Route path="review/articles/:articleId" element={<ReviewArticlePage />} />
          <Route path="knowledge" element={<KnowledgeBasePage />} />
          <Route path="knowledge/articles/:articleKey" element={<KnowledgeArticlePage />} />
        </Route>
      </Route>
    </Routes>
    <AppFooter />
  </>
}

export default App

```

### frontend/vite.config.ts

```typescript
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), tailwindcss()],
})

```

### frontend/index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="theme-color" content="#0f766e" />
    <title>OrgWiki</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

```

### backend/orgwiki-add-user-owned-workspaces.sql

```sql
﻿START TRANSACTION;

DROP INDEX "IX_generated_articles_Key";

ALTER TABLE uploads ADD "UserId" uuid;

CREATE INDEX "IX_uploads_UserId" ON uploads ("UserId");

ALTER TABLE uploads ADD CONSTRAINT "FK_uploads_users_UserId" FOREIGN KEY ("UserId") REFERENCES users ("Id") ON DELETE CASCADE;

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260716141153_AddUserOwnedWorkspaces', '8.0.11');

COMMIT;
```

### backend/orgwiki-add-authentication-foundation.sql

```sql
﻿START TRANSACTION;

ALTER TABLE uploads ADD "UploadedBy" character varying(128);

CREATE TABLE users (
    "Id" uuid NOT NULL,
    "FullName" character varying(256) NOT NULL,
    "Email" character varying(320) NOT NULL,
    "PasswordHash" text NOT NULL,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    "UpdatedAtUtc" timestamp with time zone NOT NULL,
    CONSTRAINT "PK_users" PRIMARY KEY ("Id")
);

CREATE UNIQUE INDEX "IX_users_Email" ON users ("Email");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260716132224_AddAuthenticationFoundation', '8.0.11');

COMMIT;
```

### backend/orgwiki-add-team-spaces.sql

```sql
﻿START TRANSACTION;

CREATE TABLE team_spaces (
    "Id" uuid NOT NULL,
    "Name" character varying(128) NOT NULL,
    "Slug" character varying(128) NOT NULL,
    "Description" character varying(1024) NOT NULL,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    CONSTRAINT "PK_team_spaces" PRIMARY KEY ("Id")
);

CREATE TABLE team_space_articles (
    "TeamSpaceId" uuid NOT NULL,
    "GeneratedArticleId" uuid NOT NULL,
    CONSTRAINT "PK_team_space_articles" PRIMARY KEY ("TeamSpaceId", "GeneratedArticleId"),
    CONSTRAINT "FK_team_space_articles_generated_articles_GeneratedArticleId" FOREIGN KEY ("GeneratedArticleId") REFERENCES generated_articles ("Id") ON DELETE CASCADE,
    CONSTRAINT "FK_team_space_articles_team_spaces_TeamSpaceId" FOREIGN KEY ("TeamSpaceId") REFERENCES team_spaces ("Id") ON DELETE CASCADE
);

CREATE INDEX "IX_team_space_articles_GeneratedArticleId" ON team_space_articles ("GeneratedArticleId");

CREATE UNIQUE INDEX "IX_team_spaces_Slug" ON team_spaces ("Slug");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260720125850_AddTeamSpaces', '8.0.11');

COMMIT;
```

### backend/orgwiki-initial-schema.sql

```sql
﻿CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
    "MigrationId" character varying(150) NOT NULL,
    "ProductVersion" character varying(32) NOT NULL,
    CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

START TRANSACTION;

CREATE TABLE uploads (
    "Id" uuid NOT NULL,
    "OriginalFileName" character varying(255) NOT NULL,
    "StorageKey" character varying(512) NOT NULL,
    "Status" character varying(32) NOT NULL,
    "TotalFiles" integer NOT NULL,
    "SupportedFiles" integer NOT NULL,
    "FailedFiles" integer NOT NULL,
    "TotalCharacterCount" integer NOT NULL,
    "IsEligibleForAnalysis" boolean NOT NULL,
    "AnalysisEligibilityReason" text,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    "CompletedAtUtc" timestamp with time zone,
    CONSTRAINT "PK_uploads" PRIMARY KEY ("Id")
);

CREATE TABLE documents (
    "Id" uuid NOT NULL,
    "UploadId" uuid NOT NULL,
    "FileName" character varying(255) NOT NULL,
    "OriginalPath" character varying(1024) NOT NULL,
    "FileExtension" character varying(16) NOT NULL,
    "DocumentType" character varying(32) NOT NULL,
    "Content" text,
    "CharacterCount" integer NOT NULL,
    "WordCount" integer NOT NULL,
    "ProcessingStatus" character varying(32) NOT NULL,
    "ProcessingError" text,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    CONSTRAINT "PK_documents" PRIMARY KEY ("Id"),
    CONSTRAINT "FK_documents_uploads_UploadId" FOREIGN KEY ("UploadId") REFERENCES uploads ("Id") ON DELETE CASCADE
);

CREATE TABLE knowledge_analyses (
    "Id" uuid NOT NULL,
    "UploadId" uuid NOT NULL,
    "Status" character varying(32) NOT NULL,
    "AiMode" character varying(16) NOT NULL,
    "Model" character varying(128) NOT NULL,
    "StartedAtUtc" timestamp with time zone NOT NULL,
    "CompletedAtUtc" timestamp with time zone,
    "InputTokens" integer,
    "OutputTokens" integer,
    "TotalTokens" integer,
    "DurationMilliseconds" bigint,
    "ErrorMessage" text,
    "ResultJson" text,
    "IsCurrent" boolean NOT NULL,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    CONSTRAINT "PK_knowledge_analyses" PRIMARY KEY ("Id"),
    CONSTRAINT "FK_knowledge_analyses_uploads_UploadId" FOREIGN KEY ("UploadId") REFERENCES uploads ("Id") ON DELETE CASCADE
);

CREATE TABLE knowledge_generations (
    "Id" uuid NOT NULL,
    "AnalysisId" uuid NOT NULL,
    "Status" character varying(32) NOT NULL,
    "AiMode" character varying(16) NOT NULL,
    "Model" character varying(128) NOT NULL,
    "StartedAtUtc" timestamp with time zone NOT NULL,
    "CompletedAtUtc" timestamp with time zone,
    "InputTokens" integer,
    "OutputTokens" integer,
    "TotalTokens" integer,
    "DurationMilliseconds" bigint,
    "ErrorMessage" text,
    "ResultJson" text,
    "IsCurrent" boolean NOT NULL,
    "CreatedAtUtc" timestamp with time zone NOT NULL,
    CONSTRAINT "PK_knowledge_generations" PRIMARY KEY ("Id"),
    CONSTRAINT "FK_knowledge_generations_knowledge_analyses_AnalysisId" FOREIGN KEY ("AnalysisId") REFERENCES knowledge_analyses ("Id") ON DELETE CASCADE
);

CREATE TABLE generated_articles (
    "Id" uuid NOT NULL,
    "GenerationId" uuid NOT NULL,
    "Key" character varying(128) NOT NULL,
    "Title" character varying(512) NOT NULL,
    "Summary" text NOT NULL,
    "MarkdownContent" text NOT NULL,
    "Difficulty" character varying(32) NOT NULL,
    "EstimatedReadingMinutes" integer NOT NULL,
    "TagsJson" text NOT NULL,
    "RelatedArticleKeysJson" text NOT NULL,
    "Confidence" double precision NOT NULL,
    "Status" character varying(32) NOT NULL,
    "GeneratedAtUtc" timestamp with time zone NOT NULL,
    "ReviewedBy" character varying(128),
    "ReviewedAtUtc" timestamp with time zone,
    "ReviewNotes" text,
    "LastEditedAtUtc" timestamp with time zone,
    "LastEditedBy" character varying(128),
    "PublishedAtUtc" timestamp with time zone,
    "PublishedBy" character varying(128),
    CONSTRAINT "PK_generated_articles" PRIMARY KEY ("Id"),
    CONSTRAINT "FK_generated_articles_knowledge_generations_GenerationId" FOREIGN KEY ("GenerationId") REFERENCES knowledge_generations ("Id") ON DELETE CASCADE
);

CREATE TABLE generated_article_citations (
    "Id" uuid NOT NULL,
    "GeneratedArticleId" uuid NOT NULL,
    "SourceDocumentId" uuid NOT NULL,
    "EvidenceSnippet" text NOT NULL,
    CONSTRAINT "PK_generated_article_citations" PRIMARY KEY ("Id"),
    CONSTRAINT "FK_generated_article_citations_documents_SourceDocumentId" FOREIGN KEY ("SourceDocumentId") REFERENCES documents ("Id") ON DELETE RESTRICT,
    CONSTRAINT "FK_generated_article_citations_generated_articles_GeneratedArt~" FOREIGN KEY ("GeneratedArticleId") REFERENCES generated_articles ("Id") ON DELETE CASCADE
);

CREATE INDEX "IX_documents_UploadId" ON documents ("UploadId");

CREATE INDEX "IX_generated_article_citations_GeneratedArticleId" ON generated_article_citations ("GeneratedArticleId");

CREATE INDEX "IX_generated_article_citations_SourceDocumentId" ON generated_article_citations ("SourceDocumentId");

CREATE UNIQUE INDEX "IX_generated_articles_GenerationId_Key" ON generated_articles ("GenerationId", "Key");

CREATE UNIQUE INDEX "IX_generated_articles_Key" ON generated_articles ("Key") WHERE "Status" = 'Published';

CREATE UNIQUE INDEX "IX_knowledge_analyses_UploadId" ON knowledge_analyses ("UploadId") WHERE "IsCurrent" = TRUE;

CREATE INDEX "IX_knowledge_analyses_UploadId_Status" ON knowledge_analyses ("UploadId", "Status");

CREATE UNIQUE INDEX "IX_knowledge_generations_AnalysisId" ON knowledge_generations ("AnalysisId") WHERE "IsCurrent" = TRUE;

CREATE INDEX "IX_uploads_CreatedAtUtc" ON uploads ("CreatedAtUtc");

CREATE INDEX "IX_uploads_Status" ON uploads ("Status");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260715142812_InitialOrgWikiSchema', '8.0.11');

COMMIT;


```

[118 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]