Add user guide, self-hosting, API, and contributing docs
docs/user-guide.md — magic-link sign-in, note basics, wikilink syntax, keyboard shortcuts, offline behaviour, and privacy notes (sessionStorage for tokens, tenant-scoped localStorage). docs/self-hosting.md — system requirements, Docker Compose quick-start, the full LIBRENOTES_* env-var matrix (which are required, which conditional), reverse proxy snippets for Caddy and nginx, volume layout, the in-binary healthcheck, and update/rollback procedure. docs/api.md — every public endpoint: auth (login/verify), notes CRUD, /api/whoami, /healthz. Status codes per endpoint, the optimistic-locking ?base=<unix> contract for PUT/DELETE, note-ID regex, and the rate-limit policy. CONTRIBUTING.md — dev setup (Nix flake .#dev, plain Go, Docker), package layout overview, coding standards (one-way dep flow, tenant FS gateway requirement), branch naming, commit format, and the PR process. Also points security reports at security@librete.ch rather than public issues. Closes #29. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+115
@@ -0,0 +1,115 @@
|
||||
# Contributing
|
||||
|
||||
Thank you for your interest in librenotes. This document covers
|
||||
the developer workflow: setup, conventions, commit messages, and
|
||||
how to land a pull request.
|
||||
|
||||
## Code of conduct
|
||||
|
||||
Participation in this project is governed by the
|
||||
[Contributor Covenant 2.1](./CODE_OF_CONDUCT.md). Please read it
|
||||
before opening issues or PRs.
|
||||
|
||||
## Development setup
|
||||
|
||||
The fastest path is the Nix flake. The `dev` shell drops you
|
||||
into a working Go toolchain without any sandbox wrapping:
|
||||
|
||||
```sh
|
||||
git clone https://git.librete.ch/public/librenotes.git
|
||||
cd librenotes
|
||||
nix develop .#dev
|
||||
make build && make test
|
||||
```
|
||||
|
||||
If you don't use Nix:
|
||||
|
||||
- Install Go 1.22 or later.
|
||||
- Install `make`, `git`.
|
||||
- Optional: `staticcheck` (Go), `sqlite3` (for backup tooling).
|
||||
|
||||
A Docker-based dev environment also exists:
|
||||
|
||||
```sh
|
||||
docker build -f Dockerfile.dev -t librenotes-dev .
|
||||
docker run --rm -it -v "$PWD:/workspace" librenotes-dev
|
||||
```
|
||||
|
||||
See the [README](./README.md) for the full layout. In short:
|
||||
|
||||
```
|
||||
cmd/librenotes/ Binary entry + serve cmd + frontend assets
|
||||
internal/auth/ Magic-link auth + JWT
|
||||
internal/storage/ SQLite + user model
|
||||
internal/tenant/ Per-user filesystem sandbox
|
||||
internal/httpapi/ Routes, middleware, notes CRUD
|
||||
internal/notesium/ Forked Notesium core (notes engine)
|
||||
docs/ User-facing docs (this guide, ops, api, ...)
|
||||
scripts/ Backup, prune, restore tools
|
||||
```
|
||||
|
||||
## Coding standards
|
||||
|
||||
- Match the existing style. We don't have a custom linter beyond
|
||||
`go vet`; `gofmt` and `goimports` are enforced via the
|
||||
toolchain. Run `make lint` before pushing.
|
||||
- Keep packages focused. Cross-package dependencies should flow
|
||||
one way: `httpapi -> auth/storage/tenant`, never the reverse.
|
||||
- Tests live next to the code they exercise (`*_test.go`). Aim
|
||||
for table-driven tests for input parsing and behavioural tests
|
||||
with `httptest.NewRecorder` for handlers.
|
||||
- New runtime configuration goes through `LIBRENOTES_*` env vars
|
||||
with a corresponding `--flag` on `librenotes serve`.
|
||||
- All filesystem operations on tenant data must go through
|
||||
`internal/tenant`. Never `os.Open` a path containing a user ID.
|
||||
|
||||
## Branch naming
|
||||
|
||||
- `feat/<short-slug>` for new features
|
||||
- `fix/<short-slug>` for bug fixes
|
||||
- `docs/<short-slug>` for documentation
|
||||
- `chore/<short-slug>` for tooling, CI, refactors
|
||||
- `phase-N/<topic>` for issues belonging to a roadmap phase
|
||||
|
||||
## Commit messages
|
||||
|
||||
Imperative mood, present tense. First line ≤72 characters. Body
|
||||
explains the *why*, references the issue with `Closes #N` or
|
||||
`Refs #N` so Gitea can auto-link. Example:
|
||||
|
||||
```
|
||||
Add tenant-scoped notes REST API
|
||||
|
||||
Backed by tenant.FS so all reads/writes go through the per-user
|
||||
sandbox. ?base=<unix> drives optimistic-locking conflict
|
||||
detection for PUT/DELETE.
|
||||
|
||||
Closes #11.
|
||||
```
|
||||
|
||||
## Pull request process
|
||||
|
||||
1. Open an issue first for anything non-trivial. Reference it
|
||||
from the PR.
|
||||
2. Branch off `main`, push, open a PR against `main`.
|
||||
3. CI must pass (`make lint && make test`). Failed CI blocks
|
||||
review.
|
||||
4. Fill out the PR template — at minimum: what changed, why, how
|
||||
it was tested.
|
||||
5. Squash on merge unless the history is genuinely useful.
|
||||
|
||||
## Reporting issues
|
||||
|
||||
Use the bug-report or feature-request templates from the *New
|
||||
issue* page on Gitea. The templates ask for the right things;
|
||||
filling them out gets faster responses.
|
||||
|
||||
For security issues please **do not** open a public issue. Email
|
||||
`security@librete.ch` with details.
|
||||
|
||||
## Releases
|
||||
|
||||
Tagged releases follow [SemVer](https://semver.org). The
|
||||
maintainer creates the tag and the deploy workflow handles the
|
||||
build and registry push automatically. Individual contributors
|
||||
are not expected to tag releases.
|
||||
Reference in New Issue
Block a user