Ledger is a production-minded monorepo for a secure knowledge base platform with public and internal content on the same foundation.
This repository currently ships a real MVP foundation:
- React frontend with public browsing, sign-in, search, page viewing, feedback, dashboard, and basic branding settings
- Node.js API with local auth, HTTP-only cookie sessions, RBAC-aware page visibility, revisioned Markdown pages, search logging, feedback, webhooks, integrations config, MCP tools, and local attachment storage
- PostgreSQL schema and seed data for the core entities
- Redis-backed worker for async jobs
- Docker Compose for local development
- Basic tests for permission logic, markdown sanitization, auth helpers, search matching, webhook signing, and key HTTP flows
Ledger starts with real setup, not demo accounts.
docker compose upnow runs a singlebootstrapcontainer that installs dependencies once into a shared Docker volume- PostgreSQL and Redis stay internal to the Compose network by default
- The first browser visit takes you to a setup screen where you create:
- the initial owner account
- the site name and brand color
- the footer text
- the initial public knowledge base toggle
- After setup, the instance is ready for real configuration, integrations, and content
apps/web: React frontendapps/api: Express API, migrations, seed data, testsapps/worker: Redis/BullMQ workerpackages/shared: shared contracts and RBAC helpersinfra/postgres: database bootstrapstorage/uploads: local-first attachment storage
Working vertical slices:
- Public and internal spaces/pages
- Secure backend permission checks for page reads and search results
- Local email/password auth with HTTP-only cookies
- Built-in roles and group-aware restricted pages
- Revisioned Markdown pages with sanitized HTML rendering and table of contents
- Feedback capture with analytics visibility
- Search logging and no-result webhook event generation
- Basic admin settings for branding
- Webhook configuration and queued delivery records
- Local attachment upload metadata + file persistence
- MCP endpoint for search, page read, space listing, metadata lookup, and draft creation
Large areas intentionally left at foundation level for follow-up work:
- OIDC and optional OAuth provider handlers
- SMTP delivery workflows and branded email templates
- Full import/sync pipelines for GitHub, Google Docs, and bulk Markdown
- External AI provider adapters
- Full webhook delivery execution and retries
- Rich editor UX, revision diff UI, and attachment browser UI
Those features already have schema support and API/config footholds where appropriate, but the MVP prioritizes a secure core over placeholder-heavy surface area.
- Copy
.env.exampleto.env - Start the stack:
docker compose upServices:
- Frontend: http://localhost:5173
- API: http://localhost:4000
- Postgres: internal-only in Docker Compose
- Redis: internal-only in Docker Compose
On first boot, open the frontend and complete the setup wizard.
Ledger now includes an in-place updater so you do not need to reflash the VM for every change.
Directly on the VM:
cd /opt/ledger
./infra/scripts/vm-update.shOptional flags:
APP_DIR=/opt/ledgerBRANCH=mainREPO_URL=https://github.com/Anord-cc/ledger.gitFORCE_RESET=1
What the updater does:
- Clones Ledger if the VM does not have the repo yet
- Pulls the selected Git branch
- Preserves
.env, uploads, and Docker volumes - Pulls base container images
- Runs the shared dependency bootstrap once
- Restarts Postgres, Redis, API, web, and worker services
By default the Linux updater refuses to overwrite local repo changes on the VM. If you intentionally want the VM to match Git exactly, rerun with FORCE_RESET=1.
If you want a single server command instead of changing into the repo first:
cd /opt/ledger
./infra/scripts/install-vm-updater.sh
ledger-updateThat installs /usr/local/bin/ledger-update, which runs the same in-place update flow with sensible defaults.
npm install
npm run db:migrate
npm run db:seed
npm run dev:api
npm run dev:web
npm run dev:workerPOST /api/auth/loginGET /api/auth/sessionGET /api/spacesGET /api/pages/space/:spaceKeyGET /api/pages/slug/:slugPOST /api/pagesGET /api/search?q=...POST /api/feedbackGET /api/settings/publicGET /api/settings/adminPUT /api/settings/brandingGET /api/admin/search-analyticsGET /api/admin/feedbackPOST /api/attachmentsGET /api/webhooksPOST /api/webhooksGET /api/integrationsPOST /api/integrationsPOST /api/ai/answersPOST /api/mcp
npm test- Backend-enforced permission checks
- Sanitized Markdown rendering
- Secure password hashing with bcrypt
- HTTP-only session cookies
- Rate limiting on auth and search endpoints
- Audit log records for key admin/editor actions
- Secrets sourced from environment variables
- Add OIDC and optional OAuth callback flows.
- Replace the MVP AI fallback with a provider adapter interface and citation-aware answer generation.
- Execute real webhook deliveries with retry and signing headers.
- Add multipart attachment uploads and an attachment picker in the editor.
- Expand admin UI for users, groups, roles, webhooks, and integrations.