87 lines
4.1 KiB
Markdown
87 lines
4.1 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to librenotes are recorded here. The format
|
|
loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
and the project follows [Semantic Versioning](https://semver.org/).
|
|
|
|
## [Unreleased]
|
|
|
|
## [0.1.0] — 2026-04-29
|
|
|
|
The initial public release: a fork of Notesium turned into a
|
|
multi-tenant SaaS, plus the surrounding infrastructure.
|
|
|
|
### Added
|
|
|
|
- **Fork.** Forked [alonswartz/notesium](https://github.com/alonswartz/notesium)
|
|
at `aff9f460c2d864112db7f0935b4168b107289d91`, restructured into
|
|
the standard Go layout (`cmd/`, `internal/`), renamed the
|
|
module to `git.librete.ch/public/librenotes`, preserved the MIT
|
|
license alongside librenotes copyright, documented the upstream
|
|
remote and cherry-pick workflow.
|
|
- **User model + SQLite storage** (`internal/storage`). UUIDv4
|
|
IDs, email uniqueness, WAL mode, embedded migrations.
|
|
- **Magic-link authentication** (`internal/auth`). 32-byte
|
|
cryptographically random tokens, SHA-256-hashed at rest,
|
|
single-use, 15-minute expiry. HS256 JWT sessions with 24-hour
|
|
lifetime, `jwt.WithValidMethods` to reject `alg=none`. Pluggable
|
|
`Mailer` interface with `SMTPMailer` and dev-friendly
|
|
`LogMailer`. DB-backed per-email rate limiting.
|
|
- **Per-tenant filesystem isolation** (`internal/tenant`). Each
|
|
user gets a sandboxed directory; all reads and writes go
|
|
through `os.Root` so path traversal and symlink escapes are
|
|
rejected at the syscall layer.
|
|
- **Tenant-aware HTTP API** (`internal/httpapi`). JWT middleware,
|
|
tenant context, `/api/whoami`, `/api/notes` CRUD with
|
|
optimistic-locking conflict detection (`?base=<unix>`),
|
|
`/healthz`.
|
|
- **`librenotes serve`** command wires storage, auth, tenants,
|
|
notes, and a static frontend into one binary. Configuration
|
|
via `LIBRENOTES_*` env vars or flags. Background goroutine
|
|
purges expired magic tokens.
|
|
- **Frontend** (`cmd/librenotes/web/public/`): mobile-first
|
|
landing page, login + verify pages, app shell with sync
|
|
badge and conflict dialog. Vanilla JS, no build step.
|
|
- **JWT session client** with sessionStorage + automatic
|
|
`Authorization: Bearer` injection and 401-redirects-to-login.
|
|
- **Tenant-scoped localStorage** wrapper so two users on the
|
|
same browser have isolated UI state; cleared on logout.
|
|
- **Offline cache** in IndexedDB (`notes-cache.js`) with dirty
|
|
tracking and tombstones for deletes.
|
|
- **Background sync** (`sync.js`) — pushes dirty rows on
|
|
reconnect, pulls remote changes, surfaces conflicts to the UI
|
|
via custom events.
|
|
- **PWA support**: manifest, service worker (cache-first shell,
|
|
network-first API), 192/512/maskable icons, install prompt.
|
|
- **Responsive CSS** with explicit breakpoints from 320px to
|
|
2560px, including a 3-column ultrawide layout primitive.
|
|
- **Pointer events** on the resize handle so touch and pen work
|
|
identically to mouse, including pointer capture for drag.
|
|
- **Containerised deployment**: multi-stage Dockerfile producing
|
|
a distroless `nonroot` image, dev + prod Compose stacks,
|
|
in-binary `librenotes healthcheck` for distroless HEALTHCHECK.
|
|
- **CI**: Gitea Actions workflow runs `make lint`, `make build`,
|
|
`make test` on every push and PR.
|
|
- **Deploy workflow** (gated on `DEPLOY_ENABLED=true`) builds
|
|
and pushes images, SSHes to the host, runs `compose pull && up
|
|
-d`, polls `/healthz`.
|
|
- **Backup tooling** (`scripts/`): SQLite online snapshot + tar
|
|
of notes, optional rclone off-site copy, retention pruning,
|
|
weekly automated restore-test, systemd timer units.
|
|
- **Documentation**: user guide, self-hosting, API reference,
|
|
operations, contributing.
|
|
- **Community infrastructure**: bug-report and feature-request
|
|
Gitea issue templates, PR template, Code of Conduct.
|
|
- **First-run onboarding**: welcome dialog + seeded sample note,
|
|
dismissal persisted per tenant.
|
|
|
|
### Notes
|
|
|
|
- The bundled notes engine (the original Notesium UI under
|
|
`internal/notesium/web/app/`) is not yet wired into the
|
|
multi-tenant frontend. Phase 7 will replace or wrap it.
|
|
- SMTP delivery has been exercised against the LogMailer only;
|
|
real-provider integration is part of self-hosting validation.
|
|
|
|
[0.1.0]: https://git.librete.ch/public/librenotes/releases/tag/v0.1.0
|