From 3b3cb57aa22ed4f82308d569e2de42e28cd2266f Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Tue, 28 Apr 2026 23:20:20 +0200 Subject: [PATCH] Add CHANGELOG and launch validation checklist CHANGELOG.md follows Keep-a-Changelog. The Unreleased section sits at the top; the v0.1.0 entry summarises every commit on the path from the empty fork to a hosted multi-tenant build: fork + restructure, storage/auth/tenant/httpapi packages, the serve command, full frontend (landing, login, verify, app shell, PWA, sync), Docker + deploy + backup tooling, docs, and the community infrastructure. Two known-incomplete items called out explicitly: the upstream Notesium UI is not yet wired into the multi-tenant shell, and SMTP delivery has only been exercised against the LogMailer. docs/launch-checklist.md is the manual QA pass for v0.1.0: environment prerequisites, the full sign-up to first-note flow on Chrome / Firefox / iOS Safari / Android Chrome (with explicit PWA-install and offline-shell verifications), documentation accuracy spot-checks, the community-infra render checks, and a backup-and-restore round-trip on the staging host. The QA performer signs off at the bottom; failures are filed as separate bugs against the milestone. The actual v0.1.0 tag will be cut by a maintainer; tagging is not part of this commit. Refs #30 and #33. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 86 +++++++++++++++++++++++++++++++++++++++ docs/launch-checklist.md | 88 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 docs/launch-checklist.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..274cc3d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,86 @@ +# 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] — TBD + +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=`), + `/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 diff --git a/docs/launch-checklist.md b/docs/launch-checklist.md new file mode 100644 index 0000000..5f05941 --- /dev/null +++ b/docs/launch-checklist.md @@ -0,0 +1,88 @@ +# Launch validation checklist + +Manual QA pass for v0.1.0. Performed on a staging environment +that mirrors production (Docker Compose with the prod overrides, +real SMTP, public DNS + TLS termination). + +The goal is to convince yourself a brand-new user can go from +landing page to first note without confusion, and that a +contributor can file an issue or open a PR through the templates. + +## Environment + +- [ ] Staging URL reachable over HTTPS. +- [ ] `LIBRENOTES_BASE_URL` matches the staging URL exactly. +- [ ] SMTP credentials valid; test send to a real inbox succeeds. +- [ ] `/healthz` returns 200 from outside the Docker network. + +## End-user flow + +### Desktop — Chrome + +- [ ] Landing page (`/`) loads and renders correctly. +- [ ] All links in the header and footer work. +- [ ] "Sign in with email" → `/login.html`. +- [ ] Submit a never-before-seen address → success state shows. +- [ ] Magic-link email arrives within 30s. +- [ ] Click link → `/verify.html` → "Go to your notes". +- [ ] Token is stripped from the address bar after verification. +- [ ] App shell shows email + sync badge transitions to + "synced" within a few seconds. +- [ ] Onboarding dialog appears. +- [ ] Welcome note exists in the notebook. +- [ ] Dismissing the dialog does not reopen on reload. +- [ ] Theme toggle persists across reload. +- [ ] Sign out clears session and tenant store; signing back + in does NOT show onboarding again (same device, same + tenant). + +### Desktop — Firefox + +- [ ] Repeat the same flow with no console errors specific to + Firefox. + +### Mobile — iOS Safari + +- [ ] Layout has no horizontal scroll on iPhone SE (320px). +- [ ] Touch handles for any interactive controls respond + without ghost clicks. +- [ ] PWA installable via "Add to Home Screen". + +### Mobile — Android Chrome + +- [ ] beforeinstallprompt surfaces the install button. +- [ ] Installed PWA opens in standalone mode. +- [ ] Offline: open the app with airplane mode on; the shell + renders and the welcome note loads from IndexedDB. + +## Documentation + +- [ ] User guide accurate (reflects current behaviour). +- [ ] Self-hosting guide produces a working stack on a fresh + Debian box (re-run quick-start). +- [ ] API reference matches actual responses for /auth and + /api/notes. +- [ ] CONTRIBUTING dev-setup section runs to a green + `make test` from a fresh clone. + +## Community infrastructure + +- [ ] "New issue" page shows two templates (bug, feature). +- [ ] Bug template's required fields actually require input. +- [ ] PR template renders on the new-PR form. +- [ ] CoC reachable from the README. + +## Backup & restore + +- [ ] `scripts/backup.sh` produces an archive on the staging + host. +- [ ] `scripts/backup-restore-test.sh` passes against that + archive. +- [ ] Retention prune leaves the right number of files. + +## Sign-off + +- [ ] All checked. Any failures filed as separate bug reports + against the v0.1.0 milestone. +- [ ] QA performer: ____________________ +- [ ] Date (UTC): ____________________