diff --git a/.gitignore b/.gitignore index a3d7f3a..e839729 100644 --- a/.gitignore +++ b/.gitignore @@ -209,5 +209,5 @@ android/local.properties # The Android client CI bakes into the server image. Fetched fresh on every image # build, so it is never worth 55 MiB of git history. client/.keep IS tracked, so # the Dockerfile's COPY always has a directory to copy. -client/thoughtsync.apk -client/thoughtsync-android.json +client/inkwell.apk +client/inkwell-android.json diff --git a/README.md b/README.md index 60ad5a2..a0d9c52 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ThoughtSync +# Inkwell Self-hosted personal thought-capture web app in the **FabledSword** family — a Google-Keep-style **masonry post-it board** for capturing disparate thoughts in @@ -23,7 +23,7 @@ docker-compose.yml local app + Postgres stack ## Development -Backend (needs a Postgres reachable at `THOUGHTSYNC_DATABASE_URL`): +Backend (needs a Postgres reachable at `INKWELL_DATABASE_URL`): ```sh pip install -e ".[dev]" @@ -64,40 +64,40 @@ services: image: postgres:16-alpine restart: unless-stopped environment: - POSTGRES_USER: thoughtsync + POSTGRES_USER: inkwell POSTGRES_PASSWORD: CHANGE_ME # change this - POSTGRES_DB: thoughtsync + POSTGRES_DB: inkwell volumes: - - thoughtsync-db:/var/lib/postgresql/data + - inkwell-db:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U thoughtsync"] + test: ["CMD-SHELL", "pg_isready -U inkwell"] interval: 5s timeout: 5s retries: 10 app: - image: git.fabledsword.com/bvandeusen/thoughtsync:latest # :dev for the current dev build + image: git.fabledsword.com/bvandeusen/inkwell:latest # :dev for the current dev build restart: unless-stopped depends_on: db: condition: service_healthy environment: - THOUGHTSYNC_DATABASE_URL: postgresql+asyncpg://thoughtsync:CHANGE_ME@db:5432/thoughtsync + INKWELL_DATABASE_URL: postgresql+asyncpg://inkwell:CHANGE_ME@db:5432/inkwell volumes: - - thoughtsync-data:/var/thoughtsync # uploaded images; omit if you don't use attachments + - inkwell-data:/var/inkwell # uploaded images; omit if you don't use attachments ports: - "5000:5000" volumes: - thoughtsync-db: - thoughtsync-data: + inkwell-db: + inkwell-data: ``` Then open `http://:5000` and register — **the first account becomes the admin**. -- **Only `THOUGHTSYNC_DATABASE_URL` is required.** `THOUGHTSYNC_SECRET_KEY` is optional; if +- **Only `INKWELL_DATABASE_URL` is required.** `INKWELL_SECRET_KEY` is optional; if unset, a signing key is generated and persisted in the database (sessions survive restarts). -- Uploaded images live under the `thoughtsync-data` volume at `/var/thoughtsync`. +- Uploaded images live under the `inkwell-data` volume at `/var/inkwell`. - The app waits for the database and runs migrations (`alembic upgrade head`) automatically on start. - **Image tags:** `:latest` (stable, built from `main`) · `:dev` (latest `dev` build) · `:` on `main` only (immutable, the rollback unit). There are @@ -108,7 +108,7 @@ Then open `http://:5000` and register — **the first account becomes the port, and back up the attachment volume as well as the database. See [docs/public-hosting.md](docs/public-hosting.md), which also lists what the app hardens on its own and what it deliberately doesn't. -- **Install as an app (PWA):** ThoughtSync is installable ("Add to Home Screen" / the +- **Install as an app (PWA):** Inkwell is installable ("Add to Home Screen" / the browser's install button) for an app-like window. Browsers only offer install over a **secure context**, so put the app behind a reverse proxy terminating **HTTPS** (or reach it via `localhost`) — plain `http://:5000` won't show the install prompt. diff --git a/alembic.ini b/alembic.ini index f1f261c..4ad4574 100644 --- a/alembic.ini +++ b/alembic.ini @@ -1,4 +1,4 @@ -# Alembic single-database async configuration for ThoughtSync. +# Alembic single-database async configuration for Inkwell. [alembic] script_location = %(here)s/alembic diff --git a/ci-requirements.md b/ci-requirements.md index 99daebb..fbe3f95 100644 --- a/ci-requirements.md +++ b/ci-requirements.md @@ -1,4 +1,4 @@ -# CI Requirements — ThoughtSync +# CI Requirements — Inkwell > Spec lives in [`docs/process.md`](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md) > in the CI-Runner repo. @@ -39,7 +39,7 @@ entirely on `ci-python:3.14`. install` cold cost is a non-blocker. - Build gates on `typecheck` + `lint` only. The `test` job runs in parallel for visibility but does not block the dev image push. DB-backed / integration tests - run against the dev image manually — ThoughtSync's unit tests are DB-free (no + run against the dev image manually — Inkwell's unit tests are DB-free (no Postgres service lane in CI yet). - `dev` push -> `:dev` + `:`; `v*` tag -> `:latest` + `:` + `:` (family rule 46). @@ -87,7 +87,7 @@ parts. Three of them are family rules for a reason: `docker ps` by it. A spaced or underscored name breaks the filter. - **Service hostnames are not routable** on this runner (rule 79), so the step resolves the Postgres container's bridge IP with `docker ps --filter` + `docker inspect` and - builds `THOUGHTSYNC_DATABASE_URL` from it. `postgres:5432` will not connect. + builds `INKWELL_DATABASE_URL` from it. `postgres:5432` will not connect. - **`run:` is busybox sh** (rule 81) — no `/dev/tcp` — so the readiness wait is a small Python heredoc. Its terminator must dedent to column 0 after YAML strips the block indent; check with `yaml.safe_load` and print the `run` string if you edit it. @@ -205,7 +205,7 @@ backend/frontend push. ## Android lane — being rebuilt (M12) The Tauri-mobile Android lane is gone. Android is a native Kotlin/Compose client -over the shared `thoughtsync-core` crate instead — see Scribe note 2730 for the +over the shared `inkwell-core` crate instead — see Scribe note 2730 for the decision and milestone M12 for the arc. The image it will run on already exists: **`ci-rust-android:1.97`**, repurposed @@ -218,7 +218,7 @@ second image, and JDK 25 (which requires **Gradle 9.1+** in this repo's wrapper the old JDK 17 pin existed only because Tauri generated a Gradle 8.x project). The Rust pin is in LOCKSTEP with `ci-tauri` and `ci-tauri-win`. All three build -`thoughtsync-core` from one workspace `Cargo.lock` under `--locked`, so a +`inkwell-core` from one workspace `Cargo.lock` under `--locked`, so a mismatched Rust minor across the lanes would mean divergent resolution for no reason. Bump the three together or not at all. @@ -333,8 +333,9 @@ differs from CI is worse than none. **This reproduces CI exactly, not approximately.** On the 2026-08-18 run the local test binary hashes (`thoughtsync_core-bbaae79723888ad1`, -`thoughtsync_desktop_lib-9d162263f8d0aca3`, `thoughtsync_ffi-fc557b96dc795e27`) -matched CI run 3931's byte for byte. Same image, same lockfile, same units. +`thoughtsync_desktop_lib-9d162263f8d0aca3`, `thoughtsync_ffi-fc557b96dc795e27`, +named for the crates as they were before the rename to Inkwell) matched CI run +3931's byte for byte. Same image, same lockfile, same units. `target/` persists on the host between runs, so after the first cold build these take seconds (~30s for clippy). It is gitignored and reaches ~1.4 GB; delete it diff --git a/desktop/README.md b/desktop/README.md index 08544d7..c28893e 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -1,9 +1,9 @@ -# ThoughtSync desktop (Tauri v2) +# Inkwell desktop (Tauri v2) Local-first desktop client. The window loads the shared **Vue 3 frontend** from `../frontend`; the Rust core (`src-tauri`) owns the on-device store and the opt-in sync engine (built out across the M10 milestone). Works fully offline; optionally -syncs to a self-hosted ThoughtSync server. +syncs to a self-hosted Inkwell server. ## Layout diff --git a/desktop/packaging/arch/README.md b/desktop/packaging/arch/README.md index 03a6982..b7eb6ea 100644 --- a/desktop/packaging/arch/README.md +++ b/desktop/packaging/arch/README.md @@ -1,6 +1,6 @@ -# ThoughtSync desktop — Arch package +# Inkwell desktop — Arch package -A **prebuilt** native pacman package, published as an asset on every ThoughtSync +A **prebuilt** native pacman package, published as an asset on every Inkwell release. Nothing to compile, no toolchain to install. Installing natively on Arch matters for more than tidiness: pacman pulls @@ -15,22 +15,22 @@ Easiest — the one-command installer picks this package automatically on any pacman system: ```sh -curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/dev/desktop/packaging/install.sh | sh +curl -fsSL https://git.fabledsword.com/bvandeusen/inkwell/raw/branch/dev/desktop/packaging/install.sh | sh ``` That installs the newest build from `main`. To follow the rolling development channel instead, pass the flag through the pipe: ```sh -curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/dev/desktop/packaging/install.sh | sh -s -- --channel dev +curl -fsSL https://git.fabledsword.com/bvandeusen/inkwell/raw/branch/dev/desktop/packaging/install.sh | sh -s -- --channel dev ``` Or grab the `.pkg.tar.*` from the -[releases page](https://git.fabledsword.com/bvandeusen/thoughtsync/releases) +[releases page](https://git.fabledsword.com/bvandeusen/inkwell/releases) and install it directly: ```sh -sudo pacman -U thoughtsync-*-x86_64.pkg.tar.* +sudo pacman -U inkwell-*-x86_64.pkg.tar.* ``` The compression suffix depends on what the build image provides — `.zst` when @@ -39,17 +39,18 @@ all of them; only the filename differs. Either way you get: -- `/usr/bin/thoughtsync` — the app -- `/usr/share/applications/thoughtsync.desktop` — the menu entry -- `/usr/share/icons/hicolor/*/apps/thoughtsync.png` — themed icons +- `/usr/bin/inkwell` — the app +- `/usr/share/applications/inkwell.desktop` — the menu entry +- `/usr/share/icons/hicolor/*/apps/inkwell.png` — themed icons -Launch **ThoughtSync** from your app menu, or run `thoughtsync`. +Launch **Inkwell** from your app menu, or run `inkwell`. -Uninstall: `sudo pacman -R thoughtsync`. +Uninstall: `sudo pacman -R inkwell`. -The package was called `thoughtsync-desktop` before; it declares `replaces`/ -`conflicts` on that name, so an upgrade from it is a normal `pacman -U` and -leaves nothing behind. +The package was called `thoughtsync` until the app was renamed Inkwell, and +`thoughtsync-desktop` before that. It declares `replaces`/`conflicts` on both +names, so an upgrade from either is a normal `pacman -U` and leaves nothing +behind. ## How the package is built diff --git a/desktop/packaging/publish-release.sh b/desktop/packaging/publish-release.sh index b6bbb66..9a8e370 100755 --- a/desktop/packaging/publish-release.sh +++ b/desktop/packaging/publish-release.sh @@ -149,7 +149,7 @@ fi echo "==> Creating release for $TAG" BODY=$(cat < notes.sql -docker run --rm -v thoughtsync-data:/d -v "$PWD":/out alpine tar czf /out/media.tgz -C /d . +docker compose exec -T db pg_dump -U inkwell inkwell > notes.sql +docker run --rm -v inkwell-data:/d -v "$PWD":/out alpine tar czf /out/media.tgz -C /d . ``` ## What the app already does @@ -132,7 +132,7 @@ know. They are the reason not to hand out open registration to strangers. The app allows plain HTTP so a self-hosted server on a LAN is usable at all — Android blocks cleartext by default from API 28, and `http://192.168.1.10:8000` is exactly the -case ThoughtSync is built for. Over the public internet, link the phone to the +case Inkwell is built for. Over the public internet, link the phone to the **HTTPS** hostname. The sync screen shows a warning before any credential field whenever the address it probed was `http://`; on a public network that warning means what it says. diff --git a/docs/sync.md b/docs/sync.md index 2a2476e..9f6fc98 100644 --- a/docs/sync.md +++ b/docs/sync.md @@ -1,4 +1,4 @@ -# ThoughtSync sync protocol +# Inkwell sync protocol The contract the local-first native clients (Tauri desktop, Android) implement against. The server is the **sync hub**: each client keeps a full local store @@ -38,8 +38,8 @@ token, or even has an account: ``` The client identifies itself on every request with -`X-ThoughtSync-Client: thoughtsync-desktop/` and -`X-ThoughtSync-Protocol: `. +`X-Inkwell-Client: inkwell-desktop/` and +`X-Inkwell-Protocol: `. ### `sync_features` — why versions alone aren't enough diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d8889dc..c057770 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "thoughtsync-frontend", + "name": "inkwell-frontend", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "thoughtsync-frontend", + "name": "inkwell-frontend", "version": "0.1.0", "dependencies": { "pinia": "^2.2.0", diff --git a/frontend/package.json b/frontend/package.json index eb276f4..1e1a49e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "thoughtsync-frontend", + "name": "inkwell-frontend", "version": "0.1.0", "private": true, "type": "module", diff --git a/frontend/public/sw.js b/frontend/public/sw.js index c4a1ecf..503da01 100644 --- a/frontend/public/sw.js +++ b/frontend/public/sw.js @@ -6,7 +6,7 @@ // and avoid deploy staleness, this SW does NOT cache the app shell, hashed build // assets, or any /api response — everything but the offline fallback goes // straight to the network. -const CACHE = "thoughtsync-shell-v1"; +const CACHE = "inkwell-shell-v1"; const OFFLINE_URL = "/offline.html"; self.addEventListener("install", (event) => {