public
anord
read
Ledger
Why work hard when you can work easier?
Languages
Repository composition by tracked source files.
TypeScript
86%
CSS
10%
SQL
3%
Shell
1%
HTML
0%
Trace
README.md
Trace helps you understand code history line by line. See who changed each line, when it changed, and which commit introduced it.
Author
Date
Commit
Line
Code
1
# Ledger
3
Ledger is a production-minded monorepo for a secure knowledge base platform with public and internal content on the same foundation.
5
This repository currently ships a real MVP foundation:
7
- React frontend with public browsing, sign-in, search, page viewing, feedback, dashboard, and basic branding settings
8
- 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
9
- PostgreSQL schema and seed data for the core entities
10
- Redis-backed worker for async jobs
11
- Docker Compose for local development
12
- Basic tests for permission logic, markdown sanitization, auth helpers, search matching, webhook signing, and key HTTP flows
14
## Fresh install behavior
16
Ledger starts with real setup, not demo accounts.
18
- `docker compose up` now runs a single `bootstrap` container that installs dependencies once into a shared Docker volume
19
- PostgreSQL and Redis stay internal to the Compose network by default
20
- The first browser visit takes you to a setup screen where you create:
21
- the initial owner account
22
- the site name and brand color
23
- the footer text
24
- the initial public knowledge base toggle
25
- After setup, the instance is ready for real configuration, integrations, and content
27
## Monorepo layout
29
- `apps/web`: React frontend
30
- `apps/api`: Express API, migrations, seed data, tests
31
- `apps/worker`: Redis/BullMQ worker
32
- `packages/shared`: shared contracts and RBAC helpers
33
- `infra/postgres`: database bootstrap
34
- `storage/uploads`: local-first attachment storage
36
## MVP scope implemented
38
Working vertical slices:
40
- Public and internal spaces/pages
41
- Secure backend permission checks for page reads and search results
42
- Local email/password auth with HTTP-only cookies
43
- Built-in roles and group-aware restricted pages
44
- Revisioned Markdown pages with sanitized HTML rendering and table of contents
45
- Feedback capture with analytics visibility
46
- Search logging and no-result webhook event generation
47
- Basic admin settings for branding
48
- Webhook configuration and queued delivery records
49
- Local attachment upload metadata + file persistence
50
- MCP endpoint for search, page read, space listing, metadata lookup, and draft creation
52
Large areas intentionally left at foundation level for follow-up work:
54
- OIDC and optional OAuth provider handlers
55
- SMTP delivery workflows and branded email templates
56
- Full import/sync pipelines for GitHub, Google Docs, and bulk Markdown
57
- External AI provider adapters
58
- Full webhook delivery execution and retries
59
- Rich editor UX, revision diff UI, and attachment browser UI
61
Those features already have schema support and API/config footholds where appropriate, but the MVP prioritizes a secure core over placeholder-heavy surface area.
63
## Local development
65
1. Copy `.env.example` to `.env`
66
2. Start the stack:
68
```bash
69
docker compose up
70
```
72
Services:
74
- Frontend: [http://localhost:5173](http://localhost:5173)
75
- API: [http://localhost:4000](http://localhost:4000)
76
- Postgres: internal-only in Docker Compose
77
- Redis: internal-only in Docker Compose
79
On first boot, open the frontend and complete the setup wizard.
81
## Updating a VM install
83
Ledger now includes an in-place updater so you do not need to reflash the VM for every change.
85
Directly on the VM:
87
```bash
88
cd /opt/ledger
89
./infra/scripts/vm-update.sh
90
```
92
Optional flags:
94
- `APP_DIR=/opt/ledger`
95
- `BRANCH=main`
96
- `REPO_URL=https://github.com/Anord-cc/ledger.git`
97
- `FORCE_RESET=1`
99
What the updater does:
101
- Clones Ledger if the VM does not have the repo yet
102
- Pulls the selected Git branch
103
- Preserves `.env`, uploads, and Docker volumes
104
- Pulls base container images
105
- Runs the shared dependency bootstrap once
106
- Restarts Postgres, Redis, API, web, and worker services
108
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`.
110
### Optional VM command install
112
If you want a single server command instead of changing into the repo first:
114
```bash
115
cd /opt/ledger
116
./infra/scripts/install-vm-updater.sh
117
ledger-update
118
```
120
That installs `/usr/local/bin/ledger-update`, which runs the same in-place update flow with sensible defaults.
122
## Without Docker
124
```bash
125
npm install
126
npm run db:migrate
127
npm run db:seed
128
npm run dev:api
129
npm run dev:web
130
npm run dev:worker
131
```
133
## Important endpoints
135
- `POST /api/auth/login`
136
- `GET /api/auth/session`
137
- `GET /api/spaces`
138
- `GET /api/pages/space/:spaceKey`
139
- `GET /api/pages/slug/:slug`
140
- `POST /api/pages`
141
- `GET /api/search?q=...`
142
- `POST /api/feedback`
143
- `GET /api/settings/public`
144
- `GET /api/settings/admin`
145
- `PUT /api/settings/branding`
146
- `GET /api/admin/search-analytics`
147
- `GET /api/admin/feedback`
148
- `POST /api/attachments`
149
- `GET /api/webhooks`
150
- `POST /api/webhooks`
151
- `GET /api/integrations`
152
- `POST /api/integrations`
153
- `POST /api/ai/answers`
154
- `POST /api/mcp`
156
## Tests
158
```bash
159
npm test
160
```
162
## Security defaults in this foundation
164
- Backend-enforced permission checks
165
- Sanitized Markdown rendering
166
- Secure password hashing with bcrypt
167
- HTTP-only session cookies
168
- Rate limiting on auth and search endpoints
169
- Audit log records for key admin/editor actions
170
- Secrets sourced from environment variables
172
## Next recommended steps
174
1. Add OIDC and optional OAuth callback flows.
175
2. Replace the MVP AI fallback with a provider adapter interface and citation-aware answer generation.
176
3. Execute real webhook deliveries with retry and signing headers.
177
4. Add multipart attachment uploads and an attachment picker in the editor.
178
5. Expand admin UI for users, groups, roles, webhooks, and integrations.