diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..6d06885 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/harshmathurx/OpenNotes/security/advisories/new + about: Report vulnerabilities privately. Do not open a public issue for security reports. + - name: Questions and support + url: https://github.com/harshmathurx/OpenNotes/blob/main/SUPPORT.md + about: Check the support guide before opening an issue. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a014b6..ed1237e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,54 @@ # Changelog -All notable changes to this project will be documented in this file. +All notable changes to this project are documented here. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Added a public architecture map for contributors. +- Added support and governance docs. +- Added issue-template contact links for security reports and support. + +### Changed + +- Reworked the README for OSS visitors: current status, download caveat, project map, extension entry points, and contribution paths are now easier to scan. +- Expanded contributor guidance around architecture boundaries and extension work. +- Tightened the security policy around local-first risks, native bridge scope, and disclosure expectations. + +## [0.1.2] - 2026-08-06 + +### Fixed + +- `Report a bug` now opens a prefilled GitHub issue in the system browser from the Mac app. +- The web build keeps its existing browser fallback. +- Package, Tauri config, and Rust crate versions are aligned at `0.1.2`. + +## [0.1.1] - 2026-08-05 + +### Added + +- Published the first downloadable Mac build of OpenNotes v2 as an Apple Silicon DMG. +- Added release assets and a SHA-256 checksum on GitHub Releases. +- Shipped the v2 workspace surface: markdown editing, workspace home, export, backlinks, templates, AI Co-Writer, and Git Sync. + ## [0.1.0] - 2026-08-05 First public-ready state of the workspace. ### Added -- **Editor** — Tiptap live-markdown editing with slash menu, wikilinks, bubble menu, zen mode, command palette (`Cmd+K`), and light/dark themes. -- **Workspace Home** (`Cmd+Shift+H`) — daily journal, scratchpad, kanban, and recent notes. -- **Styling Studio** — font, size, leading, and canvas width controls, applied instantly and persisted locally. -- **Local-first storage** — every keystroke lands in IndexedDB first; fully offline-capable; no account. -- **Extension system** — stable manifest + `activate(ctx)` contract for commands, slash items, and panels (see `docs/extensions.md`). Bundled extensions: Templates, Export (md/html/zip), Backlinks, AI Co-Writer (opt-in, off by default), Git Sync. -- **Mac app (in active development)** — Tauri v2 desktop app with real `.md` files in a user-picked notes folder, Git Sync via the local git binary and the user's own SSH/agent credentials (VS Code-style, no token custody), and secrets in the macOS Keychain. -- **AI Co-Writer** — opt-in, bring-your-own Anthropic/OpenAI key or local Ollama; keys encrypted on device with AES-GCM-256. - -[Unreleased]: https://github.com/harshmathurx/OpenNotes/compare/v0.1.0...HEAD +- Tiptap live-markdown editing with slash menu, wikilinks, bubble menu, zen mode, command palette (`Cmd+K`), and light/dark themes. +- Workspace Home (`Cmd+Shift+H`) with daily journal, scratchpad, kanban, and recent notes. +- Styling Studio with font, size, leading, and canvas width controls, applied instantly and persisted locally. +- Local-first storage: every keystroke lands in IndexedDB first; fully offline-capable; no account. +- Extension system with a stable manifest plus `activate(ctx)` contract for commands, slash items, and panels. Bundled extensions include Templates, Export, Backlinks, AI Co-Writer, and Git Sync. +- Tauri v2 desktop app with real `.md` files in a user-picked notes folder, Git Sync through the local git binary and the user's own SSH/agent credentials, and secrets in the macOS Keychain. +- AI Co-Writer: opt-in, bring-your-own Anthropic/OpenAI key or local Ollama; keys encrypted on device with AES-GCM-256. + +[Unreleased]: https://github.com/harshmathurx/OpenNotes/compare/v0.1.2...HEAD +[0.1.2]: https://github.com/harshmathurx/OpenNotes/releases/tag/v0.1.2 +[0.1.1]: https://github.com/harshmathurx/OpenNotes/releases/tag/v0.1.1 [0.1.0]: https://github.com/harshmathurx/OpenNotes/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4448a98..75e2ee5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to OpenNotes -Thanks for wanting to help. OpenNotes is small on purpose: local-first notes, real files, user-owned sync, opt-in AI, no telemetry. +Thanks for helping. OpenNotes is small on purpose: local-first notes, real files, user-owned sync, opt-in AI, no telemetry. Good contributions make that promise sharper. @@ -20,6 +20,17 @@ Good contributions make that promise sharper. - Documentation that helps users understand where their data lives. - UI polish that makes the app calmer without making it louder. +## Project orientation + +Start with the map in [docs/architecture.md](docs/architecture.md). The short version: + +- `components/` is the app surface. +- `core/` holds editor, vault, git, AI, registry, and bridge logic. +- `extensions/` holds bundled extensions and the starter template. +- `src-tauri/` holds the Mac desktop shell. + +Browser-safe code should not call native APIs directly. Use the bridge modules in `core/bridge/*` and handle the browser fallback clearly. + ## Local setup ```bash @@ -34,6 +45,18 @@ For the Mac app: pnpm tauri:dev ``` +## Working on extensions + +Extensions are the friendliest contribution path. Use [`extensions/_starter`](extensions/_starter) and read [docs/extensions.md](docs/extensions.md). + +A good extension PR usually includes: + +- A small manifest and `activate(ctx)` entry point. +- Pure logic in an `engine.ts` or similar module. +- Tests for the logic. +- Honest empty/error states if it adds UI. +- No secret storage, telemetry, unexpected network calls, or remote code execution. + ## Validation Run the checks that match your change. For most PRs: @@ -51,6 +74,8 @@ For desktop/Tauri changes, also run: cargo check --manifest-path src-tauri/Cargo.toml ``` +For extension-only changes, at minimum run the focused test file plus typecheck and lint for the touched paths. + ## Writing the PR The PR should explain: @@ -64,4 +89,11 @@ Public PRs are not internal status notes. Write for the next contributor who lan ## Release notes -If your change ships to users, add a short public-facing release note in the PR. Use `docs/release-writing.md` for the project style. +If your change ships to users, add a short public-facing release note in the PR. Use [docs/release-writing.md](docs/release-writing.md) for the project style. + +## Community + +- Use [SUPPORT.md](SUPPORT.md) for help paths. +- Use [SECURITY.md](SECURITY.md) for private vulnerability reports. +- Follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). +- Maintainer expectations live in [GOVERNANCE.md](GOVERNANCE.md). diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..5bbae0d --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,45 @@ +# Governance + +OpenNotes is maintained by [Harsh Mathur](https://github.com/harshmathurx). + +The project is small by design. Governance is lightweight until the contributor base needs more structure. + +## Maintainer responsibilities + +The maintainer is responsible for: + +- Reviewing issues and pull requests. +- Protecting the local-first promise: no account requirement, no telemetry, no hidden custody of notes or tokens. +- Deciding what belongs in core and what belongs as an extension. +- Cutting releases and publishing release notes. +- Handling security reports privately before public disclosure. + +## Contribution path + +Most changes should start as one of these: + +- A bug report with a reproduction. +- A feature request that explains the workflow. +- An extension idea. +- A small pull request with tests or a clear manual validation note. + +Large rewrites, hosted services, analytics, cloud sync, token custody, and breaking extension API changes should start as an issue before code is written. + +## Decision principles + +OpenNotes favors: + +- Plain files over proprietary storage. +- Local git over hosted sync custody. +- Opt-in AI over ambient AI features. +- Extensions over core expansion. +- Honest limitation notes over polished marketing copy. +- Small, reviewable changes over broad rewrites. + +## Becoming a regular contributor + +There is no formal role system yet. Contributors who repeatedly ship thoughtful, tested changes may be invited to help triage issues or review extension submissions. + +## Security and conduct + +Security reports follow [SECURITY.md](SECURITY.md). Community behavior follows [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index 0a752c8..c9e95c5 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,87 @@ # OpenNotes -**Your notes. Real files. Your storage. Your AI.** +**A Mac-first markdown notes app for people who want real files, local git sync, and opt-in AI.** -OpenNotes is a calm, open-source, local-first markdown workspace. Your notes stay plain `.md` files, sync runs through infrastructure you already own, and AI is opt-in on your own keys. No account, no backend, no telemetry. +OpenNotes is a local-first workspace for plain `.md` notes. The Mac app writes to a folder you choose, syncs through your own git setup, and keeps AI optional and under your keys. There is no OpenNotes account, backend, telemetry, or token custody. +[![CI](https://github.com/harshmathurx/OpenNotes/actions/workflows/ci.yml/badge.svg)](https://github.com/harshmathurx/OpenNotes/actions/workflows/ci.yml) +[![Latest release](https://img.shields.io/github/v/release/harshmathurx/OpenNotes?label=latest%20release)](https://github.com/harshmathurx/OpenNotes/releases/latest) [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) -[![Local-first](https://img.shields.io/badge/made%20with-local--first-informational.svg)](https://www.inkandswitch.com/local-first/) -[![Download](https://img.shields.io/github/v/release/harshmathurx/OpenNotes?include_prereleases&label=download)](https://github.com/harshmathurx/OpenNotes/releases) OpenNotes Mac app: a markdown note in the editor beside the Git Sync panel with the sync status banner +## Status + +OpenNotes is usable, pre-1.0 software. The core editor, local storage, bundled extensions, and Mac desktop shell work today. The app is still unsigned and not notarized, so macOS shows a first-open warning. Expect sharp edges around packaging, the extension directory, and broader distribution. + ## Download -**OpenNotes is a Mac app.** Get it (Apple Silicon or Intel) from the [Releases page](https://github.com/harshmathurx/OpenNotes/releases). +Get the latest Mac build from [GitHub Releases](https://github.com/harshmathurx/OpenNotes/releases/latest). -The Mac app is not yet signed with an Apple certificate, so macOS will warn on first open — right-click → Open → Open to proceed. Signing is on the roadmap (see RELEASE.md). +Current releases ship as DMGs: -The same codebase also runs in a browser (`pnpm dev`) for development and as a tech preview, but the Mac app is the product: it is where real files on disk and git sync live. +- Apple Silicon: `OpenNotes__aarch64.dmg` +- Intel: planned in the release workflow, not always attached to early releases -## Why OpenNotes +After installing, drag `OpenNotes.app` into Applications. Because the app is not yet Apple-notarized, first launch requires **right-click → Open → Open**. See [RELEASE.md](RELEASE.md) for the safe install path and signing status. -Most note tools ask you to give up at least one of three things: your files, your sync, or your AI. OpenNotes is built on the position that you shouldn't have to give up any of them. +The browser build (`pnpm dev`) is useful for development and preview. The Mac app is the product surface for real files on disk, git sync, and Keychain-backed secrets. -- **Files** — notes are plain markdown. Obsidian gets this right but is closed source; Notion holds content on its servers. -- **Sync** — git, through your own local git and credentials. No hosted sync service, no subscription. -- **AI** — opt-in, on your own Anthropic/OpenAI key or a local Ollama model. Keys are encrypted on device and never touch a server. +## Why OpenNotes exists -The bet: a small, excellent core plus a clean extension API beats a bloated app. +Most note apps ask you to compromise on at least one layer: -## What works now +- Your notes are not normal files. +- Sync depends on a vendor account. +- AI requires sending content through someone else's product path. +- Extensions are powerful but opaque, or safe but too limited. -- **Editor** — Tiptap live-markdown editing, slash menu, wikilinks, bubble menu, zen mode, command palette (`Cmd+K`), light/dark themes. -- **Workspace Home** (`Cmd+Shift+H`) — daily journal, scratchpad, kanban, recent notes. -- **Styling Studio** — font, size, leading, and canvas width, applied instantly and persisted locally. -- **Local-first storage** — every keystroke lands in IndexedDB first; works offline; no account required. -- **Extensions** — bundled: Templates, Export (md/html/zip), Backlinks, AI Co-Writer (opt-in, off by default), and Git Sync (Mac app). +OpenNotes takes the boring position: notes should be files, sync should use tools you already trust, and AI should be off until you choose otherwise. -## The Mac app +## What works now + +| Area | Current behavior | +| -------------- | ------------------------------------------------------------------------------------------------------------------------ | +| Editor | Tiptap live-markdown editing, slash menu, wikilinks, bubble menu, zen mode, command palette (`Cmd+K`), light/dark themes | +| Workspace home | Daily journal, scratchpad, kanban, recent notes (`Cmd+Shift+H`) | +| Styling | Font, size, leading, and canvas width controls, persisted locally | +| Local storage | IndexedDB in the web build; real `.md` files in the Mac app | +| Extensions | Templates, Export, Backlinks, AI Co-Writer, Git Sync | +| Git sync | Uses the local git binary and your existing SSH/agent credentials in the Mac app | +| AI | Bring your own Anthropic/OpenAI key or local Ollama; off by default | -OpenNotes is a Mac app (`src-tauri`, Tauri v2). It is the home of everything that makes the product sovereign: +## Where data lives -- **Real `.md` files** in a notes folder you pick — grep them, back them up, open them in any editor. -- **Git Sync** through your local git binary with your own SSH/agent credentials — VS Code-style sync, no tokens, we never see a secret. -- **AI keys and other secrets** live in the macOS Keychain, not in browser storage. +- Notes: IndexedDB in the browser build; a folder you choose in the Mac app. +- Git credentials: your local git and SSH/agent setup. OpenNotes does not hold a GitHub token. +- AI keys: encrypted on device. The Mac app stores secrets in the macOS Keychain. +- Telemetry: none. -The web build is the same codebase for development and preview, but the Mac app is the product. It is in active development; expect rough edges. +Clearing browser site data removes browser-stored notes from that profile. If the notes matter, use the Mac app with a real folder or keep an independent backup. ## Extensions -The app ships minimal on purpose; capabilities are extensions. Each one is a plain TypeScript object (a manifest plus `activate(ctx)`) that registers commands, slash items, and panels — no `eval`, no remote code. Third-party developers build against the same stable contract the bundled extensions use. See [docs/extensions.md](docs/extensions.md). +OpenNotes keeps the center small. Capabilities live as extensions: a manifest plus `activate(ctx)` that registers commands, slash items, and panels. Bundled extensions use the same public contract contributors use. -## Where data lives +Start here: -- **Notes**: IndexedDB in your browser profile on web; real files on disk in the Mac app. There is no OpenNotes backend — note content is never uploaded anywhere by us. -- **AI keys**: encrypted on device (AES-GCM-256 via WebCrypto on web, Keychain on Mac), never in plaintext, never on a server. -- **Telemetry**: none. Accounts: none. Token custody: none. +- [Extension guide](docs/extensions.md) +- Starter template: [`extensions/_starter`](extensions/_starter) +- Built-in references: [`extensions/templates`](extensions/templates), [`extensions/backlinks`](extensions/backlinks), [`extensions/export`](extensions/export), [`extensions/gitSync`](extensions/gitSync) -Clearing browser site data removes locally stored notes from that profile — if your notes matter, keep them in a synced folder or an independent copy. +Extensions are statically imported today. A curated community extension directory is on the roadmap. -## Roadmap +## Project map + +- `app/` and `components/`: Next.js app shell and UI +- `core/`: editor, vault, storage, git, AI, registry, and bridge logic +- `extensions/`: bundled extensions and starter template +- `src-tauri/`: macOS desktop shell and native commands +- `tests/`: unit and end-to-end coverage +- `.github/`: CI, release workflow, issue templates, CODEOWNERS, Dependabot -1. Mac app + git sync, hardened end to end. -2. Community extension directory. -3. Dropbox / folder-based storage providers. -4. PWA polish and offline installability. +For a fuller maintainer map, see [docs/architecture.md](docs/architecture.md). ## Local development @@ -74,20 +91,49 @@ pnpm install pnpm dev ``` -Then open http://localhost:3000. For the Mac app (once the Tauri toolchain is set up): `pnpm tauri:dev`. +Open http://localhost:3000. -## Validation commands +For the Mac app: ```bash -pnpm exec eslint . -pnpm exec tsc --noEmit +pnpm tauri:dev +``` + +You will need the Tauri macOS toolchain installed. The desktop app is the only surface that can use real folders, local git, and Keychain secrets. + +## Validation + +Run the checks that match your change: + +```bash +pnpm run typecheck +pnpm run lint pnpm exec vitest run -pnpm exec next build +pnpm run build +``` + +For desktop changes: + +```bash +cargo check --manifest-path src-tauri/Cargo.toml ``` ## Contributing -Contributions welcome — extensions most of all. See [CONTRIBUTING.md](CONTRIBUTING.md); new extension ideas have their own friendly issue template ("Extension idea"). +Contributions are welcome, especially small fixes, extension ideas, and reliability work around files, sync, export, and desktop behavior. + +- Start with [CONTRIBUTING.md](CONTRIBUTING.md). +- Report security issues privately via [SECURITY.md](SECURITY.md). +- For general help, see [SUPPORT.md](SUPPORT.md). +- Maintainer expectations live in [GOVERNANCE.md](GOVERNANCE.md). + +## Roadmap + +1. Harden Mac app packaging, signing, and notarization. +2. Ship a curated community extension directory. +3. Improve import/export and folder-backed workflows. +4. Add optional storage providers only where users keep control. +5. Polish the browser build as a preview/PWA surface. ## License diff --git a/RELEASE.md b/RELEASE.md index 5d611fd..a5ecc51 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,86 +1,81 @@ # Releasing OpenNotes -OpenNotes desktop (macOS) is distributed as a DMG via -[GitHub Releases](https://github.com/harshmathurx/OpenNotes/releases). Builds are -produced by the [`release.yml`](.github/workflows/release.yml) GitHub Actions -workflow — never by hand. +OpenNotes desktop for macOS is distributed as a DMG through [GitHub Releases](https://github.com/harshmathurx/OpenNotes/releases). Builds are produced by the [`release.yml`](.github/workflows/release.yml) GitHub Actions workflow. -## Download (for users) +## Downloading OpenNotes -1. Go to **https://github.com/harshmathurx/OpenNotes/releases** and open the - latest release. +1. Go to the [latest release](https://github.com/harshmathurx/OpenNotes/releases/latest). 2. Download the DMG that matches your Mac: - - **Apple Silicon** (M1/M2/M3/M4): `OpenNotes__aarch64.dmg` - - **Intel**: `OpenNotes__x64.dmg` + - Apple Silicon (M1/M2/M3/M4): `OpenNotes__aarch64.dmg` + - Intel: `OpenNotes__x64.dmg`, when attached for that release - Not sure which? Apple menu → About This Mac → "Chip" means Apple Silicon, - "Processor" means Intel. -3. Open the DMG and drag **OpenNotes.app** into **Applications**. + Not sure which? Apple menu → About This Mac. "Chip" means Apple Silicon; "Processor" usually means Intel. -### Unsigned app — first-open warning (read this) +3. Open the DMG and drag `OpenNotes.app` into Applications. -OpenNotes is **not yet code-signed or notarized** with an Apple Developer ID -certificate, so macOS Gatekeeper will say the app is from an "unidentified -developer" (or "cannot be checked for malicious software") the first time you -open it. This is expected — the app is safe to run; it just isn't stamped by -Apple yet. +### Unsigned app first-open warning -The safe way to open it: +OpenNotes is not yet code-signed with an Apple Developer ID certificate or notarized by Apple. On first launch, macOS may say the app is from an unidentified developer or cannot be checked for malicious software. -- **Right-click (or Control-click) `OpenNotes.app` in Applications → Open → - click Open** in the dialog. -- Or: try to open it once, let it fail, then go to **System Settings → - Privacy & Security** and click **Open Anyway** next to the OpenNotes message. +Use the per-app path: -You only need to do this once. Do **not** bypass Gatekeeper globally -(`spctl --master-disable` etc.) — the per-app steps above are the correct path. +- Right-click or Control-click `OpenNotes.app` in Applications. +- Click **Open**. +- Click **Open** again in the dialog. -Signed + notarized builds are planned. What's needed: an Apple Developer -Program membership, a *Developer ID Application* certificate, and the -`APPLE_*` repository secrets listed in the comment block at the top of -[`.github/workflows/release.yml`](.github/workflows/release.yml) — flip -`ENABLE_SIGNING` there once the secrets exist. +Or try to open it once, let macOS block it, then go to **System Settings → Privacy & Security** and click **Open Anyway** next to the OpenNotes message. -## Cutting a release (for maintainers) +You only need to do this once per installed build. Do not disable Gatekeeper globally (`spctl --master-disable` etc.). -1. **Bump the version in both places — they must match:** +Signed and notarized builds require Apple Developer Program membership, a Developer ID Application certificate, and the `APPLE_*` repository secrets listed in the comment block at the top of [`.github/workflows/release.yml`](.github/workflows/release.yml). Once those exist, enable signing in the workflow. + +## Cutting a release + +1. Bump the version in both places. They must match: - `package.json` → `"version"` - `src-tauri/tauri.conf.json` → `"version"` - (Both are currently `0.1.0`. The DMG filename and the app bundle version - come from these, so a mismatch produces a misnamed/ mismarked artifact.) -2. Commit the bump, e.g.: + The DMG filename and app bundle version come from these values, so a mismatch produces confusing artifacts. + +2. Update `CHANGELOG.md`. +3. Commit the bump: ```sh git commit -am "chore: bump version to 0.2.0" ``` -3. **Tag and push:** +4. Tag and push: + ```sh git tag v0.2.0 - git push origin main --tags # or: git push origin v0.2.0 + git push origin main --tags ``` - Pushing a `v*` tag triggers the release workflow. You can also run it - manually: **Actions → Release → Run workflow**, entering the tag - (e.g. `v0.2.0`). -4. The workflow builds two DMGs in parallel — Apple Silicon on `macos-14`, - Intel on `macos-13` — then publishes a GitHub Release named - `OpenNotes v0.2.0` with both DMGs attached and auto-generated notes. - 0.x versions are published as **prereleases** automatically. -5. Watch the run: **Actions → Release**. Total time is roughly 20–40 min on a - cold Rust cache, much less warm. + + Pushing a `v*` tag triggers the release workflow. You can also run it manually from **Actions → Release → Run workflow** with a tag such as `v0.2.0`. + +5. The workflow builds DMGs and publishes a GitHub Release named `OpenNotes v0.2.0` with assets attached. +6. Watch the run under **Actions → Release**. Cold Rust caches can make this slow. + +Releases are normal GitHub releases by default, including `0.x` releases. Mark a release as prerelease only when it is explicitly a preview, beta, or otherwise not meant to be treated as the current download. ## Release checklist -- [ ] Gates green locally and in CI: `pnpm exec tsc --noEmit`, - `pnpm exec eslint .`, `pnpm exec vitest run`, plus the full build - (`TAURI_BUILD=1 pnpm build`) and e2e (`pnpm test:e2e`). -- [ ] Version bumped in **both** `package.json` and - `src-tauri/tauri.conf.json` (identical values). -- [ ] Tag pushed: `git tag vX.Y.Z && git push origin vX.Y.Z`. -- [ ] Workflow run completed; the Release page shows **both** DMGs - (`aarch64` and `x64`) attached to the release. -- [ ] Downloaded one DMG on a real Mac and confirmed it opens (after the - unsigned-app steps above). -- [ ] README / landing page download links still match the actual asset - names — update them if the URL or naming pattern changed. -- [ ] CHANGELOG.md entry for the version (the release notes are - auto-generated, but the changelog is the curated record). +- [ ] Local gates are green: `pnpm run typecheck`, `pnpm run lint`, `pnpm exec vitest run`, `pnpm run build`. +- [ ] Desktop changes pass `cargo check --manifest-path src-tauri/Cargo.toml`. +- [ ] Version is bumped in both `package.json` and `src-tauri/tauri.conf.json`. +- [ ] `CHANGELOG.md` has an entry for the release. +- [ ] Tag is pushed: `git tag vX.Y.Z && git push origin vX.Y.Z`. +- [ ] Release workflow completes successfully. +- [ ] Release page shows the expected DMG assets and checksums. +- [ ] At least one DMG is downloaded back and checksum-verified. +- [ ] A real Mac install/open check passes using the first-open warning flow above, unless the build is signed and notarized. +- [ ] README download copy and asset names still match the release. + +## Release notes + +Keep release notes short and user-facing. Mention: + +- What changed. +- Which DMGs are available. +- Signing/notarization status. +- Any migration, compatibility, or known limitation users need before installing. + +Use [docs/release-writing.md](docs/release-writing.md) for the project style. diff --git a/SECURITY.md b/SECURITY.md index 832e996..77ad14e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,20 +2,42 @@ ## Reporting a vulnerability -If you believe you have found a security vulnerability in OpenNotes, please report it privately — do not open a public issue. +If you believe you have found a security vulnerability in OpenNotes, please report it privately. Do not open a public issue. -- Use [GitHub private vulnerability reporting](https://github.com/harshmathurx/OpenNotes/security/advisories/new), or -- Open a [security advisory discussion](https://github.com/harshmathurx/OpenNotes/security) if the form is unavailable. +Use [GitHub private vulnerability reporting](https://github.com/harshmathurx/OpenNotes/security/advisories/new). If that flow is unavailable, contact the maintainer through the profile linked from the repository. -Include: affected version/commit, steps to reproduce, impact, and whether any user data (notes, keys) is at risk. We aim to acknowledge reports within 72 hours and will keep you updated as we investigate and fix. +Please include: -## Scope notes +- Affected version or commit. +- Surface: Mac app or browser build. +- Steps to reproduce. +- Impact: note disclosure, note loss, credential exposure, code execution, or another category. +- Whether any user data, AI key, git credential, or local file may be at risk. -OpenNotes is local-first by design, which shapes its threat model: +The maintainer aims to acknowledge valid reports within 72 hours. -- **We never custody a secret.** Git sync uses your local git and SSH/agent credentials; AI keys are entered by you and stored encrypted on device (AES-GCM-256 via WebCrypto on web, macOS Keychain in the desktop app). There is no OpenNotes backend, account system, or telemetry pipeline to breach. -- The highest-impact issues for this project are: anything that could exfiltrate note content or keys from a user's device, XSS in the markdown rendering path, unsafe extension execution (the extension API must never allow remote code execution), and mishandling of credentials in the git sync path. +## Scope + +OpenNotes is local-first, which shapes its threat model: + +- OpenNotes has no backend, account system, telemetry pipeline, or hosted note storage. +- Git sync uses the user's local git binary and existing SSH/agent credentials. +- AI keys are supplied by the user and stored on device: AES-GCM-256 via WebCrypto on web, macOS Keychain in the desktop app. +- The extension API must not allow remote code execution, secret access, or unexpected access to notes outside its declared host capabilities. + +High-impact reports include: + +- Exfiltration of note content or local files. +- Exposure or mishandling of AI keys, git credentials, or Keychain data. +- XSS or unsafe markdown rendering. +- Remote code execution through the extension or registry path. +- Git sync behavior that can corrupt, delete, or push user notes unexpectedly. +- Desktop bridge commands callable from the wrong surface or with unsafe arguments. ## Supported versions -OpenNotes is pre-1.0. Security fixes are applied to the latest commit on the main branch; keep your checkout or app current. +OpenNotes is pre-1.0. Security fixes are applied to the latest commit on `main` and shipped in the next release when a user-facing build is affected. Keep your checkout or app current. + +## Public disclosure + +Please give the maintainer time to investigate and release a fix before public disclosure. Security advisories will credit reporters unless they prefer to stay anonymous. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..f9d3dde --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,29 @@ +# Support + +OpenNotes is early, community-supported software. The fastest way to get help is to file the right kind of GitHub issue with enough detail for someone else to reproduce the problem. + +## Where to go + +- Bugs: use the [bug report template](https://github.com/harshmathurx/OpenNotes/issues/new?template=bug_report.md). +- Feature requests: use the [feature request template](https://github.com/harshmathurx/OpenNotes/issues/new?template=feature_request.md). +- Extension ideas: use the [extension idea template](https://github.com/harshmathurx/OpenNotes/issues/new?template=extension_idea.md). +- Security issues: do not open a public issue. Follow [SECURITY.md](SECURITY.md). + +## Before filing + +Please include: + +- OpenNotes version. +- Surface: Mac app or browser build. +- macOS version, and browser version if relevant. +- Steps to reproduce. +- Whether any note content, sync state, or secrets may be affected. +- Logs or screenshots, with private note content and keys removed. + +## Common Mac install issue + +OpenNotes is not yet signed with an Apple Developer ID certificate or notarized by Apple. macOS may warn on first launch. + +Use the per-app path: **right-click OpenNotes.app → Open → Open**. Do not disable Gatekeeper globally. + +See [RELEASE.md](RELEASE.md) for the full install note. diff --git a/docs/README.md b/docs/README.md index 539829b..0f74b0a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,8 @@ ## Current -- [extensions.md](extensions.md) — how to build an OpenNotes extension: the manifest + `activate(ctx)` contract, available APIs, and the bundled reference extensions. Start here if you want to contribute. +- [architecture.md](architecture.md) — maintainer map of the app shell, core services, extensions, and Tauri boundary. Start here before changing code. +- [extensions.md](extensions.md) — how to build an OpenNotes extension: the manifest + `activate(ctx)` contract, available APIs, and the bundled reference extensions. - [prd-opennotes-next.md](prd-opennotes-next.md) — the product north star: what OpenNotes is, what it refuses to be, and where it's going. - [design/](design/) — design explorations: research, structure, principles, visual language, voice and tone, components, and ship criteria. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..d5f9ad4 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,74 @@ +# Architecture + +OpenNotes has four layers: + +1. The Next.js app shell. +2. Core local-first services. +3. Extensions. +4. The Tauri desktop shell for Mac-only capabilities. + +The same repository serves the browser build and the Mac app. The Mac app is the primary product surface because it can write real files, use local git, and store secrets in the macOS Keychain. + +## Repository map + +| Path | Purpose | +| ------------------ | -------------------------------------------------------------------------- | +| `app/` | Next.js routes, global styles, and the landing page | +| `components/` | App shell, editor UI, dialogs, command palette, and shared UI components | +| `core/editor/` | Markdown/editor conversion logic | +| `core/vault/` | Notes folder actions, disk mirror, save queue, folder store, and mutations | +| `core/db/` | IndexedDB schema and persistence setup | +| `core/git/` | Git sync state, parsing, errors, and execution model | +| `core/bridge/` | Runtime boundary between browser-safe code and Tauri-native commands | +| `core/crypto/` | Browser encryption helpers for local secrets | +| `core/ai/` | AI provider presets and streaming helpers | +| `core/extensions/` | Extension API, loader, registry, and store | +| `core/registry/` | Community registry schema, fetch, install, and validation logic | +| `extensions/` | Bundled extensions and the starter template | +| `src-tauri/` | Tauri v2 app, native commands, capabilities, icons, and macOS build config | +| `tests/` | Unit and e2e tests | + +## Runtime boundaries + +Browser-safe code must not assume native capabilities. Anything that touches local folders, git, dialogs, or Keychain should go through `core/bridge/*` and degrade clearly when the app is running in a browser. + +The desktop shell owns: + +- Folder picking and disk writes. +- Local git command execution. +- Keychain-backed secret storage. +- OS-native actions such as opening external URLs. + +The browser build owns: + +- IndexedDB-backed notes for development and preview. +- Browser-local encrypted settings. +- The same editor and extension surfaces where native bridges are not required. + +## Extension model + +An extension exports a manifest and `activate(ctx)`. During activation it can register: + +- Commands for the command palette. +- Slash items for the editor menu. +- Panels for docked UI. + +Extensions should keep pure logic in small modules and leave React components as thin shells. They must not store secrets, make unexpected network calls, or bypass the local-first model. See [docs/extensions.md](extensions.md). + +## Local-first constraints + +Changes should preserve these defaults: + +- No OpenNotes account. +- No OpenNotes backend for note content. +- No telemetry. +- No hidden custody of git tokens or AI keys. +- Notes stay usable as plain markdown outside the app. + +If a proposed feature needs hosted infrastructure, token custody, analytics, or remote code execution, open an issue before implementation. + +## Release shape + +The Mac app ships as a DMG from GitHub Releases. Release automation lives in `.github/workflows/release.yml`; release instructions live in [RELEASE.md](../RELEASE.md). + +Current builds are ad-hoc signed but not notarized. Developer ID signing and Apple notarization are the next distribution hardening step. diff --git a/docs/plan.md b/docs/plan.md index e67aa8e..1bf0f49 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -145,8 +145,8 @@ Each phase is designed to be picked up and executed by an agent independently. P ### Step 1.1: Initialize Next.js ```bash -mkdir -p /Users/harsh.rajmathur/Desktop/harsh-builds/personal-editor-thoughts -# Already exists, just scaffold inside it +mkdir -p opennotes +cd opennotes echo "my-app" | npx shadcn@latest init --yes --template next --base-color stone ``` @@ -155,7 +155,6 @@ This creates `src/app/page.tsx`, `src/components/ui/`, `tailwind.config.ts`, `co ### Step 1.2: Install core dependencies ```bash -cd /Users/harsh.rajmathur/Desktop/harsh-builds/personal-editor-thoughts pnpm add dexie @codemirror/view @codemirror/state @codemirror/lang-markdown \ @codemirror/commands @codemirror/language @octokit/rest dropbox \ lucide-react cmdk