diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index bc8cb38b99..fe218e298f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,5 +1,5 @@ # Thank you for considering to contribute! -I love Super Productivity. It's my favorite side project and I use it every day to plan my tasks and to track my time. But my skill set and also my perspective after using it for over two years are limited. I need your help! +I love Super Productivity. It's my favorite side project and I use it every day to plan my tasks and to track my time. I need your help! ## Things that would help @@ -16,13 +16,25 @@ I am not a designer. So there is probably a lot not to like. It would be absolut * Providing better icons ### Features/Coding -* Implementing GitLab support -* Implementing support for private GitHub repositories -* Improved data syncing, - * syncing smaller chunks instead of the complete data - * support to save the data to your own cloud storage (own cloud, Dropbox, etc.) - * I am a fan of owning your data. The ideal would be to achieve a completely syncable [unhosted web app](https://unhosted.org/) +* Improving existing issue provider integrations (Jira, GitHub, GitLab, Gitea, OpenProject, Linear, ClickUp, Azure DevOps, etc.) +* Improved data syncing +* Bug fixes and performance improvements ### Translations -* I ran the app through google translate. So there is at least one reason why they suck... +* See our [translation guide](../docs/TRANSLATING.md) for how to contribute translations + +## Commit Message Format + +We use the Angular commit message format: `type(scope): description` + +**Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore` + +**Examples:** +* `feat(tasks): add recurring task support` +* `fix(sync): handle network timeout gracefully` +* `test(e2e): fix flaky sync tests` + +**Note:** Use `test:` (not `fix(test):`) for test-related changes. The `fix` type is reserved for actual code/bug fixes. + +Include the issue number in your commit message if fixing a particular issue (e.g.: `feat: add nice feature #31`). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d3795b3e12..308f5a052b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,23 @@ ## Problem - + -## Solution: What PR does +## Solution - + + +## Type of Change + +- [ ] Bug fix +- [ ] New feature +- [ ] Breaking change +- [ ] Refactoring +- [ ] Documentation +- [ ] Other (please describe) + +## Checklist + +- [ ] I have run `npm run checkFile` on changed `.ts`/`.scss` files +- [ ] I have added tests for my changes (if applicable) +- [ ] Existing tests still pass +- [ ] My commit messages follow the Angular format (`type(scope): description`) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eae9b85065..e85eeb6a18 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ In case you want to contribute, but you wouldn't know how, here are some suggest 1. **Spread the word:** More users means more people testing and contributing to the app which in turn means better stability and possibly more and better features. You can vote for Super Productivity on [Slant](https://www.slant.co/topics/14021/viewpoints/7/~productivity-tools-for-linux~super-productivity), [Product Hunt](https://www.producthunt.com/posts/super-productivity), [Softpedia](https://www.softpedia.com/get/Office-tools/Diary-Organizers-Calendar/Super-Productivity.shtml) or on [AlternativeTo](https://alternativeto.net/software/super-productivity/), you can [tweet about it](https://twitter.com/intent/tweet?text=I%20like%20Super%20Productivity%20%20https%3A%2F%2Fsuper-productivity.com), share it on [LinkedIn](http://www.linkedin.com/shareArticle?mini=true&url=https://super-productivity.com&title=I%20like%20Super%20Productivity&), [reddit](http://www.reddit.com/submit?url=https%3A%2F%2Fsuper-productivity.com&title=I%20like%20Super%20Productivity) or any of your favorite social media platforms. Every little bit helps! 2. **Provide a Pull Request:** Here is a list of [the most popular community requests](https://github.com/super-productivity/super-productivity/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc) and here some info on [how to run the development build](https://github.com/super-productivity/super-productivity?tab=readme-ov-file#running-the-development-server). - Please make sure that you're following the [angular commit guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits) and to also include the issue number in your commit message, if you're fixing a particular issue (e.g.: `feat: add nice feature with the number #31`). + Please make sure that you're following the commit message format documented in [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md#commit-message-format) and to also include the issue number in your commit message, if you're fixing a particular issue (e.g.: `feat: add nice feature #31`). 3. **[Answer questions](https://github.com/super-productivity/super-productivity/discussions)**: You know the answer to another user's problem? Share your knowledge! diff --git a/README.md b/README.md index 4d3acac007..e018fbfa90 100644 --- a/README.md +++ b/README.md @@ -345,7 +345,7 @@ There are several ways to help. 1. **Spread the word:** More users mean more people testing and contributing to the app which in turn means better stability and possibly more and better features. You can vote for Super Productivity on [Slant](https://www.slant.co/topics/14021/viewpoints/7/~productivity-tools-for-linux~super-productivity), [Product Hunt](https://www.producthunt.com/posts/super-productivity), [Softpedia](https://www.softpedia.com/get/Office-tools/Diary-Organizers-Calendar/Super-Productivity.shtml) or on [AlternativeTo](https://alternativeto.net/software/super-productivity/), you can [tweet about it](https://twitter.com/intent/tweet?text=I%20like%20Super%20Productivity%20%20https%3A%2F%2Fsuper-productivity.com), share it on [LinkedIn](http://www.linkedin.com/shareArticle?mini=true&url=https://super-productivity.com&title=I%20like%20Super%20Productivity&), [reddit](http://www.reddit.com/submit?url=https%3A%2F%2Fsuper-productivity.com&title=I%20like%20Super%20Productivity) or any of your favorite social media platforms. Every little bit helps! 2. **Provide a Pull Request:** Here is a list of [the most popular community requests](https://github.com/super-productivity/super-productivity/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc) and here some info on [how to run the development build](https://github.com/super-productivity/super-productivity?tab=readme-ov-file#running-the-development-server). - Please make sure that you're following the [angular commit guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits) and to also include the issue number in your commit message, if you're fixing a particular issue (e.g.: `feat: add nice feature with the number #31`). + Please make sure that you're following the [commit message format](.github/CONTRIBUTING.md#commit-message-format) and to also include the issue number in your commit message, if you're fixing a particular issue (e.g.: `feat: add nice feature #31`). 3. **[Answer questions](https://github.com/super-productivity/super-productivity/discussions)**: You know the answer to another user's problem? Share your knowledge! diff --git a/docs/TRANSLATING.md b/docs/TRANSLATING.md index 2756daee53..2f86c58f0b 100644 --- a/docs/TRANSLATING.md +++ b/docs/TRANSLATING.md @@ -4,8 +4,10 @@ Super Productivity uses JSON files for translations, located in `src/assets/i18n ## How to Contribute -1. Find your language file in `src/assets/i18n/` (e.g., `de.json` for German) -2. Edit the JSON file directly +> **Important:** When adding or changing translation keys, **only edit `en.json` directly**. Other locale files are managed via the i18n script workflow described in [i18n-script-usage.md](i18n-script-usage.md). Editing other locale files by hand may cause your changes to be overwritten. + +1. Add or update translation keys in `src/assets/i18n/en.json` +2. Run the i18n script to propagate changes to other locales (see [i18n-script-usage.md](i18n-script-usage.md)) 3. Submit a pull request ## Important Notes diff --git a/docs/add-new-integration.md b/docs/add-new-integration.md index 4c956a9d23..971bd9ee39 100644 --- a/docs/add-new-integration.md +++ b/docs/add-new-integration.md @@ -4,7 +4,7 @@ This guide explains how to add a new issue tracker integration to Super Producti ## Overview -Super Productivity supports multiple issue tracker integrations (called "Issue Providers" in the codebase), including GitHub, GitLab, Jira, and others. Adding a new integration requires implementing specific interfaces and services to communicate with the external service. +Super Productivity supports multiple issue tracker integrations (called "Issue Providers" in the codebase), including Jira, GitLab, Gitea, Redmine, Open Project, CalDAV, Calendar (iCal), Trello, ClickUp, Linear, Azure DevOps, and Nextcloud Deck. GitHub has been migrated to a plugin-based provider. Adding a new integration requires implementing specific interfaces and services to communicate with the external service. ## Integration Architecture @@ -146,18 +146,22 @@ You'll need to update several core files to register your new integration: #### 1. Update `issue.model.ts` -Add your provider to the `IssueProviderKey` type: +Add your provider to the `BuiltInIssueProviderKey` type: ```typescript -export type IssueProviderKey = +export type BuiltInIssueProviderKey = | 'JIRA' - | 'GITHUB' | 'GITLAB' | 'CALDAV' | 'ICAL' | 'OPEN_PROJECT' | 'GITEA' + | 'TRELLO' | 'REDMINE' + | 'LINEAR' + | 'CLICKUP' + | 'AZURE_DEVOPS' + | 'NEXTCLOUD_DECK' | 'MY_PROVIDER'; // Add your provider here ``` @@ -219,15 +223,19 @@ export const MY_PROVIDER_TYPE: IssueProviderKey = 'MY_PROVIDER'; Add your provider to `ISSUE_PROVIDER_TYPES`: ```typescript -export const ISSUE_PROVIDER_TYPES: IssueProviderKey[] = [ +export const ISSUE_PROVIDER_TYPES: BuiltInIssueProviderKey[] = [ GITLAB_TYPE, - GITHUB_TYPE, JIRA_TYPE, CALDAV_TYPE, ICAL_TYPE, OPEN_PROJECT_TYPE, GITEA_TYPE, + TRELLO_TYPE, REDMINE_TYPE, + LINEAR_TYPE, + CLICKUP_TYPE, + AZURE_DEVOPS_TYPE, + NEXTCLOUD_DECK_TYPE, MY_PROVIDER_TYPE, // Add your provider here ]; ``` diff --git a/docs/build-and-publish-notes.md b/docs/build-and-publish-notes.md index 7b09a9ef6b..35a85efc36 100644 --- a/docs/build-and-publish-notes.md +++ b/docs/build-and-publish-notes.md @@ -1,5 +1,9 @@ # Publish notes +> **Related macOS docs:** +> - [mac-app-store-code-signing-guide.md](./mac-app-store-code-signing-guide.md) -- Code signing setup and troubleshooting +> - [update-mac-certificates.md](./update-mac-certificates.md) -- Annual certificate renewal + Look for AppDataForScreenshots.json ## Mac Store Screenshots diff --git a/docs/github-access-token-instructions.md b/docs/github-access-token-instructions.md index 8978d81118..46dd8f90fa 100644 --- a/docs/github-access-token-instructions.md +++ b/docs/github-access-token-instructions.md @@ -3,7 +3,7 @@ To generate a GitHub Personal Access Token: 1. Navigate to GitHub's [Personal Access Tokens (Classic)](https://github.com/settings/tokens) page - - Note: Fine-grained tokens are not currently supported + - Note: Fine-grained tokens may work but classic tokens are recommended and tested 2. Click "Generate new token (classic)" 3. Select the `repo` scope to grant access to private repositories 4. Click "Generate token" and securely store the token value diff --git a/docs/gitlab-access-token-instructions.md b/docs/gitlab-access-token-instructions.md index 3ec6f5b540..648e04787a 100644 --- a/docs/gitlab-access-token-instructions.md +++ b/docs/gitlab-access-token-instructions.md @@ -16,5 +16,4 @@ The scope is similar to the Personal Access token, but you also set a role. To l ![Project Token](https://github.com/user-attachments/assets/f008f114-3d3e-450d-9301-7825222f9812) -For GitHub Personal Access Token instructions, please visit the following link: -[GitHub Access Token Instructions](https://github.com/super-productivity/super-productivity/blob/master/docs/github-access-token-instructions.md) +For GitHub Personal Access Token instructions, see [GitHub Access Token Instructions](./github-access-token-instructions.md). diff --git a/docs/howto-refresh-snap-credentials.md b/docs/howto-refresh-snap-credentials.md index d5abac8146..d5195e0489 100644 --- a/docs/howto-refresh-snap-credentials.md +++ b/docs/howto-refresh-snap-credentials.md @@ -1,4 +1,6 @@ -# Howto refresh snap credentials +# How to refresh Snap Store credentials -1. exec `snapcraft export-login --snaps superproductivity -` -2. Copy value to SNAPCRAFT_STORE_CREDENTIALS in GitHub action settings. +The Snap Store credentials used by GitHub Actions to publish new releases expire periodically. When they expire, the CI publish step will fail. Follow these steps to generate fresh credentials and update the GitHub Actions secret. + +1. Run `snapcraft export-login --snaps superproductivity -` +2. Copy the output value to `SNAPCRAFT_STORE_CREDENTIALS` in GitHub Actions settings (Settings > Secrets and variables > Actions). diff --git a/docs/i18n-script-usage.md b/docs/i18n-script-usage.md index 9ae62d62e8..0542a5f22d 100644 --- a/docs/i18n-script-usage.md +++ b/docs/i18n-script-usage.md @@ -88,4 +88,4 @@ This updates all `{lang}.json` files to include any new keys from `en.json`, pla - The script preserves the order of keys to match `en.json`. - Empty strings in translation files trigger English fallback. -- WIP files are temporary and it would be deleted via the merge command. +- WIP files are temporary and will be deleted by the merge command. diff --git a/docs/long-term-plans/caldav-vevent-expansion-design.md b/docs/long-term-plans/caldav-vevent-expansion-design.md index 3beba4865b..5239325958 100644 --- a/docs/long-term-plans/caldav-vevent-expansion-design.md +++ b/docs/long-term-plans/caldav-vevent-expansion-design.md @@ -1,5 +1,7 @@ # CalDAV VEVENT Expansion — Design Document +> **Status: Planned** + ## Overview Extend the existing CalDAV provider to support VEVENT (calendar events) alongside VTODO (tasks). This gives self-hosted calendar users (Nextcloud, Radicale, Baikal, Fastmail) two-way event sync with no new auth infrastructure — the same basic auth that already works for VTODOs. diff --git a/docs/long-term-plans/calendar-two-way-sync-technical-analysis.md b/docs/long-term-plans/calendar-two-way-sync-technical-analysis.md index e8520c73d9..1e79cb0d0d 100644 --- a/docs/long-term-plans/calendar-two-way-sync-technical-analysis.md +++ b/docs/long-term-plans/calendar-two-way-sync-technical-analysis.md @@ -1,5 +1,7 @@ # Technical Hurdles for True Two-Way Calendar Sync +> **Status: Planned** + ## Executive Summary Based on my exploration of Super Productivity's codebase, implementing true two-way calendar sync faces several significant technical challenges that go beyond the robust sync infrastructure already in place. While the app has sophisticated Operation Log-based sync for its own data and read-only iCal polling for calendars, bridging these systems to enable bidirectional calendar sync requires solving authentication, API integration, conflict resolution, and architectural challenges. diff --git a/docs/long-term-plans/e2e-encryption-CRITICAL-ISSUES.md b/docs/long-term-plans/e2e-encryption-CRITICAL-ISSUES.md index 4fc055235b..41c103ade9 100644 --- a/docs/long-term-plans/e2e-encryption-CRITICAL-ISSUES.md +++ b/docs/long-term-plans/e2e-encryption-CRITICAL-ISSUES.md @@ -1,5 +1,9 @@ # E2E Encryption Implementation - Critical Issues Summary +> **Status: Archived — Reference Only** +> +> Documents blockers in the rejected device-key approach. Kept for historical context. + ## ⚠️ DO NOT IMPLEMENT WITHOUT ADDRESSING THESE ISSUES This document summarizes the **critical blockers** identified by 5 independent agent reviews of the device-generated key encryption plan. diff --git a/docs/long-term-plans/e2e-encryption-architecture-diagrams.md b/docs/long-term-plans/e2e-encryption-architecture-diagrams.md index a313692baf..bc92276a0b 100644 --- a/docs/long-term-plans/e2e-encryption-architecture-diagrams.md +++ b/docs/long-term-plans/e2e-encryption-architecture-diagrams.md @@ -1,5 +1,9 @@ # E2E Encryption Architecture Diagrams +> **Status: Archived — Reference Only** +> +> Comparative analysis of encryption approaches. Password-based encryption was chosen and implemented December 2025. + This document provides visual architecture diagrams comparing the current password-based encryption, the proposed device-key approach, and the recommended improvements. --- diff --git a/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md b/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md index 33f99d8b24..54a5b1d292 100644 --- a/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md +++ b/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md @@ -1,5 +1,9 @@ # Progressive E2E Encryption for SuperSync - REVISED PLAN +> **Status: Archived — Rejected** +> +> Rejected due to 4 critical blockers. See `e2e-encryption-CRITICAL-ISSUES.md`. The implemented approach uses password-based encryption — see `../sync-and-op-log/supersync-encryption-architecture.md`. + ## Executive Summary **ORIGINAL PLAN REJECTED** after comprehensive agent review identified fatal flaws: diff --git a/docs/long-term-plans/electron-upgrade-to-v40.md b/docs/long-term-plans/electron-upgrade-to-v40.md index f1ab144b19..11b4476f41 100644 --- a/docs/long-term-plans/electron-upgrade-to-v40.md +++ b/docs/long-term-plans/electron-upgrade-to-v40.md @@ -1,5 +1,7 @@ # Plan: Upgrade Electron from 37.10.3 to 40 +> **Status: Planned** + ## Context Super Productivity ships on Linux as AppImage, deb, snap, rpm, and has a community Flatpak on Flathub. Two previous upgrade attempts (Electron 38 in Oct 2025, Electron 39 in Dec 2025) both failed and were reverted due to **Snap crashes on Wayland**. diff --git a/docs/long-term-plans/google-calendar-provider-design.md b/docs/long-term-plans/google-calendar-provider-design.md index 5ee876ce6e..f03d2dce93 100644 --- a/docs/long-term-plans/google-calendar-provider-design.md +++ b/docs/long-term-plans/google-calendar-provider-design.md @@ -1,5 +1,7 @@ # Google Calendar Provider — Design Document +> **Status: Planned** + ## Overview Add a Google Calendar provider (`GOOGLE_CALENDAR`) to Super Productivity with two-way event sync via the Google Calendar REST API. Authentication uses a hybrid approach: an auth proxy by default with an option for user-provided OAuth credentials. diff --git a/docs/long-term-plans/ios-dropbox-sync-reliability.md b/docs/long-term-plans/ios-dropbox-sync-reliability.md index 09ffe8da48..08c53c71c7 100644 --- a/docs/long-term-plans/ios-dropbox-sync-reliability.md +++ b/docs/long-term-plans/ios-dropbox-sync-reliability.md @@ -1,6 +1,7 @@ # iOS Dropbox Sync Reliability -**Status:** Investigation complete, fixes pending +> **Status: Investigation Complete — Fixes Pending** + **Issue:** [#6333](https://github.com/super-productivity/super-productivity/issues/6333) **Severity:** High — Dropbox sync is completely broken for some iOS users diff --git a/docs/long-term-plans/jwt-derived-encryption.md b/docs/long-term-plans/jwt-derived-encryption.md index 73846a7085..4ecc70685d 100644 --- a/docs/long-term-plans/jwt-derived-encryption.md +++ b/docs/long-term-plans/jwt-derived-encryption.md @@ -1,5 +1,9 @@ # JWT-Derived Encryption for SuperSync +> **Status: Archived — Superseded** +> +> JWT-derived keys are unsuitable due to token refresh invalidating encryption keys. Password-based encryption was implemented instead — see `../sync-and-op-log/supersync-encryption-architecture.md`. + ## Goal Provide automatic "encryption at rest" for lazy users who don't want to enter a passphrase. This protects against database leaks while maintaining zero UX friction. diff --git a/docs/long-term-plans/multi-client-file-sync-reliability.md b/docs/long-term-plans/multi-client-file-sync-reliability.md index c387f71d06..3a1d0a91cc 100644 --- a/docs/long-term-plans/multi-client-file-sync-reliability.md +++ b/docs/long-term-plans/multi-client-file-sync-reliability.md @@ -1,5 +1,7 @@ # Making File-Based Sync Reliable with Multiple Concurrent Clients +> **Status: Planned** + ## Current Vulnerabilities The single-file approach (`sync-data.json`) has these specific weaknesses when multiple clients sync simultaneously: diff --git a/docs/long-term-plans/plugin-view-adapter-api.md b/docs/long-term-plans/plugin-view-adapter-api.md index b5efb8e634..368560ca3a 100644 --- a/docs/long-term-plans/plugin-view-adapter-api.md +++ b/docs/long-term-plans/plugin-view-adapter-api.md @@ -1,5 +1,7 @@ # Plugin System: View-Adapter API for Task Grouping +> **Status: Planned** + **Date:** 2026-01-20 **Approach:** Option B - Simpler view-adapter API (not full wrapping system) **Estimated Complexity:** ~500 lines of code diff --git a/docs/long-term-plans/secure-storage.md b/docs/long-term-plans/secure-storage.md index a4118c251b..0e33cbf0d5 100644 --- a/docs/long-term-plans/secure-storage.md +++ b/docs/long-term-plans/secure-storage.md @@ -1,5 +1,7 @@ # Secure Credential Storage Implementation Plan +> **Status: Planned** + ## Overview Implement platform-specific secure storage for all sync provider credentials (SuperSync, WebDAV, Dropbox) with automatic silent migration from plaintext IndexedDB storage. diff --git a/docs/long-term-plans/server-side-entity-versioning.md b/docs/long-term-plans/server-side-entity-versioning.md index e4b65f3929..0bde9674d6 100644 --- a/docs/long-term-plans/server-side-entity-versioning.md +++ b/docs/long-term-plans/server-side-entity-versioning.md @@ -1,6 +1,6 @@ # Plan: Server-Side Entity Versioning (Optimistic Concurrency Control) -> **STATUS: PROPOSED** +> **Status: Planned** > > Long-term architectural change to eliminate vector clock pruning as a source of sync conflicts. diff --git a/docs/long-term-plans/supersync-encryption-at-rest.md b/docs/long-term-plans/supersync-encryption-at-rest.md index 98b0ef4532..9d8c3de0e1 100644 --- a/docs/long-term-plans/supersync-encryption-at-rest.md +++ b/docs/long-term-plans/supersync-encryption-at-rest.md @@ -1,5 +1,7 @@ # SuperSync Encryption at Rest Implementation Plan +> **Status: Planned** + ## Overview Implement full database encryption at rest for SuperSync using LUKS volume encryption to protect against database compromise and meet GDPR compliance requirements. diff --git a/docs/long-term-plans/sync-core-simplification-roadmap.md b/docs/long-term-plans/sync-core-simplification-roadmap.md index 283d40e7f8..8f736446db 100644 --- a/docs/long-term-plans/sync-core-simplification-roadmap.md +++ b/docs/long-term-plans/sync-core-simplification-roadmap.md @@ -1,5 +1,7 @@ # Sync Core Simplification Roadmap +> **Status: Planned** + **Goal:** Reduce cognitive load and architectural coupling in the sync stack without destabilizing behavior. **Primary focus:** Client-side sync orchestration. diff --git a/docs/long-term-plans/sync-provider-plugins.md b/docs/long-term-plans/sync-provider-plugins.md index 1e31a7fce1..6fb8f6865c 100644 --- a/docs/long-term-plans/sync-provider-plugins.md +++ b/docs/long-term-plans/sync-provider-plugins.md @@ -1,5 +1,7 @@ # Design: Sync Provider Plugins +> **Status: Planned** + ## Goal Enable community developers to build sync providers (Google Drive, OneDrive, S3, etc.) as plugins, using the existing plugin system's runtime loading and sandboxed execution. diff --git a/docs/mac-app-store-code-signing-guide.md b/docs/mac-app-store-code-signing-guide.md index 29f5151e01..86cf8d6211 100644 --- a/docs/mac-app-store-code-signing-guide.md +++ b/docs/mac-app-store-code-signing-guide.md @@ -1,5 +1,9 @@ # Mac App Store Code Signing Guide +> **Related macOS docs:** +> - [build-and-publish-notes.md](./build-and-publish-notes.md) -- Build/publish workflow (screenshots, iOS, Windows signing) +> - [update-mac-certificates.md](./update-mac-certificates.md) -- Annual certificate renewal + This document explains the Mac App Store (MAS) code signing setup and troubleshooting for Super Productivity. It covers the complete solution to certificate/provisioning profile mismatches. ## Overview diff --git a/docs/sync-and-op-log/background-info/vector-clock-pruning-research.md b/docs/sync-and-op-log/background-info/vector-clock-history-and-alternatives.md similarity index 100% rename from docs/sync-and-op-log/background-info/vector-clock-pruning-research.md rename to docs/sync-and-op-log/background-info/vector-clock-history-and-alternatives.md diff --git a/docs/sync-and-op-log/long-term-plans/e2e-encryption-plan.md b/docs/sync-and-op-log/long-term-plans/e2e-encryption-plan.md index 60addd3741..03e7d3956d 100644 --- a/docs/sync-and-op-log/long-term-plans/e2e-encryption-plan.md +++ b/docs/sync-and-op-log/long-term-plans/e2e-encryption-plan.md @@ -1,6 +1,6 @@ # E2E Encryption for SuperSync Server -> **Status:** ✅ **Implemented** (December 2025) +> **Status: Completed** (December 2025) > > This plan has been fully implemented. For the current implementation details, see: > diff --git a/docs/sync-and-op-log/long-term-plans/hybrid-manifest-architecture.md b/docs/sync-and-op-log/long-term-plans/hybrid-manifest-architecture.md index e42e98ef90..6320bcfac0 100644 --- a/docs/sync-and-op-log/long-term-plans/hybrid-manifest-architecture.md +++ b/docs/sync-and-op-log/long-term-plans/hybrid-manifest-architecture.md @@ -1,8 +1,9 @@ # Hybrid Manifest & Snapshot Architecture for File-Based Sync -**Status:** ✅ Implemented (December 2025) +> **Status: Completed** (December 2025) + **Context:** Optimizing WebDAV/Dropbox sync for the Operation Log architecture. -**Related:** [Operation Log Architecture](./operation-log-architecture.md) +**Related:** [Operation Log Architecture](../operation-log-architecture.md) > **Implementation Note:** This architecture is fully implemented in `OperationLogManifestService`, `OperationLogUploadService`, and `OperationLogDownloadService`. The embedded operations buffer, overflow file creation, and snapshot support are all operational. diff --git a/docs/sync-and-op-log/long-term-plans/replace-pfapi-with-oplog-plan.md b/docs/sync-and-op-log/long-term-plans/replace-pfapi-with-oplog-plan.md index 102dd0f793..e274146a84 100644 --- a/docs/sync-and-op-log/long-term-plans/replace-pfapi-with-oplog-plan.md +++ b/docs/sync-and-op-log/long-term-plans/replace-pfapi-with-oplog-plan.md @@ -1,6 +1,6 @@ # Plan: Replace PFAPI with Operation Log Sync for All Providers -> **STATUS: COMPLETED (January 2026)** +> **Status: Completed** (January 2026) > > This plan has been fully implemented. The entire `src/app/pfapi/` directory has been deleted. > All sync providers now use the unified operation log system via `FileBasedSyncAdapter`. diff --git a/docs/sync-and-op-log/supersync-scenarios-simplified.md b/docs/sync-and-op-log/supersync-scenarios-simplified.md deleted file mode 100644 index 337f016ac5..0000000000 --- a/docs/sync-and-op-log/supersync-scenarios-simplified.md +++ /dev/null @@ -1,94 +0,0 @@ -# SuperSync Scenarios — Simplified - -Condensed reference for all SuperSync synchronization scenarios. For full details see [supersync-scenarios.md](./supersync-scenarios.md). - ---- - -## A. Normal Sync - -- **Incremental sync**: Download remote ops → detect conflicts → apply → upload local ops → done -- **Piggybacked ops**: Upload response includes other clients' ops, processed inline -- **No changes**: Quick round-trip, seq updated, status IN_SYNC - -## B. Conflicts - -- **Concurrent edits**: Auto-resolved via Last-Writer-Wins (timestamp comparison). No dialog. -- **Server rejects (CONFLICT_CONCURRENT)**: Re-download, auto-resolve, retry next sync -- **Validation error**: Op permanently rejected, status ERROR -- **Payload too large**: Alert dialog, sync stops -- **Infinite loop**: After max retries, op permanently rejected - -## C. Fresh Client - -- **No local data**: Confirm dialog → download all remote ops -- **Has local data (pre-op-log)**: Full conflict dialog (USE_LOCAL / USE_REMOTE / CANCEL) -- **Has meaningful pending ops (file-based only)**: Conflict dialog if real user data at risk - -## D. SYNC_IMPORT (full state replacement) - -- **No local pending, has meaningful data**: Conflict dialog with import reason shown, "Use Server Data" recommended -- **No local pending, no meaningful data**: Apply silently (no dialog) -- **Has local pending**: Conflict dialog before processing (regardless of meaningful data) -- **Piggybacked SYNC_IMPORT**: Same conflict dialog as download path — prevents silent state replacement -- **Local import filters remote ops**: Conflict dialog (local created the import) -- **Remote import filters remote ops**: Silent filter (import already accepted) -- **Same-client pruning artifact**: Ops kept (can't conflict with own import) - -## E. Encryption - -- **Enable**: Delete server → upload encrypted snapshot. Other clients get password prompt. -- **Disable**: Delete server → upload unencrypted. Other clients auto-detect. -- **Change password**: Clean slate → new SYNC_IMPORT encrypted with new key -- **Wrong password**: Error → password dialog (Save & Sync / Use Local Data) -- **Mismatch (remote disabled)**: Auto-disable local encryption + snackbar -- **Mandatory prompt**: After every unencrypted SuperSync sync until password set or sync disabled -- **Blocks concurrent sync**: Encryption ops lock out sync until complete -- **File import**: Preserves encryption state - -## F. Server Migration - -- **Empty server detected**: Auto-create SYNC_IMPORT from local state -- **Race condition**: If server no longer empty, abort migration, sync normally - -## G. Errors - -- Network timeout → retry next sync -- CORS → snackbar with details -- Auth failure → clear creds, prompt reconfigure -- Server error → silent retry -- Duplicate op → mark synced silently -- Storage quota → alert dialog -- Schema too new → log warning, HANDLED_ERROR -- Migration failure → skip failed ops, snackbar -- Concurrent sync → second attempt blocked -- App closes mid-sync → pending ops survive in IndexedDB - -## H. Multi-Client - -- **A encrypts, B has pending**: B gets conflict dialog (was previously broken — silent discard) -- **A changes password, B has old**: B gets password dialog -- **A imports file, B has changes**: B gets conflict dialog -- **Both force-upload**: Last-write-wins at server level -- **Three clients, normal edits**: LWW for same entity, clean merge for different entities - -## I. Setup & Provider Switching - -- **New user, empty server**: Setup → probe server (empty) → create-password prompt → done -- **Existing local data, empty server**: Auto-create SYNC_IMPORT from local state (pre-op-log client fix) -- **Second client, server has encrypted data**: Setup → probe server → enter-password prompt → download all -- **Second client, server has unencrypted data**: Setup → probe server → create-password prompt → download all -- **Second client with local data**: Full conflict dialog -- **Re-enable after disable**: Seamless resume from stored lastServerSeq -- **Switch accounts**: New lastServerSeq=0, server migration if empty server -- **File-based → SuperSync**: Server migration uploads SYNC_IMPORT -- **SuperSync → File-based**: Full state snapshot written to file -- **Encrypted SuperSync → File-based**: Encryption is per-provider, WebDAV starts unencrypted -- **Rapid switching**: Op log + vector clocks + client ID preserved across all switches - ---- - -## Known Issues - -1. `syncedAt` is per-operation, not per-provider — ops won't re-upload after switching -2. Encryption state may show misleading global config after provider switch -3. No "skip encryption" for SuperSync — Cancel disables sync entirely diff --git a/docs/update-android-app.md b/docs/update-android-app.md index 620e479cb5..e06b6790ca 100644 --- a/docs/update-android-app.md +++ b/docs/update-android-app.md @@ -1,34 +1,29 @@ -# How to release a new version of the android app +# How to release a new version of the Android app -1. `npm version ...` +1. `npm version patch` (or `minor`/`major` as appropriate) 2. `npm run dist:android:prod` -3. Go to android studio -4. Go to build/generate signed bundle apk -5. (sup.jks) -6. Choose playRelease +3. Go to Android Studio +4. Go to Build > Generate Signed Bundle / APK +5. Select keystore (`sup.jks`) +6. Choose `playRelease` 7. Select APK -8. Select playRelease +8. Select `playRelease` 9. Locate files after build -10. Go to google play console: https://play.google.com/console/u/0/developers/?pli=1 and login. -11. Go to Release/Produktion and hit "Neuen Release erstellen" -12. Upload apk from $project/app/play/release/release/app-play-release.apk -13. Add release notes and hit "Release überprüfen" +10. Go to [Google Play Console](https://play.google.com/console/u/0/developers/?pli=1) and log in +11. Go to Release > Production and click "Create new release" +12. Upload APK from `$project/app/play/release/release/app-play-release.apk` +13. Add release notes and submit for review -# OLD way +--- -1. Go to android studio -2. Update app/build.gradle versionCode and versionName - (To trigger F-Droid) - Add `fastlane/metadata/android//changelogs/.txt` -3. git commit -4. git tag (To trigger F-Droid), e.g.: `git tag -a "v21.0" -m"Release 21"` -5. Go to build/generate signed bundle apk -6. (sup.jks) -7. Choose playRelease -8. Select APK -9. Select playRelease -10. Locate files after build -11. Go to google play console: https://play.google.com/console/u/0/developers/?pli=1 and login. -12. Go to Release/Produktion and hit "Neuen Release erstellen" -13. Upload apk from $project/app/play/release/release/app-play-release.apk -14. Add release notes and hit "Release überprüfen" +
+Deprecated: OLD workflow (no longer used) + +1. Go to Android Studio +2. Update `app/build.gradle` `versionCode` and `versionName` + (To trigger F-Droid) Add `fastlane/metadata/android//changelogs/.txt` +3. `git commit` +4. `git tag` (to trigger F-Droid), e.g.: `git tag -a "v21.0" -m "Release 21"` +5. Continue from step 4 of the current workflow above + +
diff --git a/docs/update-mac-certificates.md b/docs/update-mac-certificates.md index 59a971161d..01d2fd3413 100644 --- a/docs/update-mac-certificates.md +++ b/docs/update-mac-certificates.md @@ -1,5 +1,9 @@ # Update macOS certificates for electron-builder +> **Related macOS docs:** +> - [build-and-publish-notes.md](./build-and-publish-notes.md) -- Build/publish workflow (screenshots, iOS, Windows signing) +> - [mac-app-store-code-signing-guide.md](./mac-app-store-code-signing-guide.md) -- Code signing setup and troubleshooting + Mac access required! The instructions below refresh every asset used by the GitHub Actions/macOS runners for Mac App Store (MAS) and direct-download (DMG) builds. ## Certificates @@ -86,242 +90,3 @@ See also: ``` 4. The script signs, notarizes (via `notarytool`), and staples the DMG using the new certificates and provisioning profiles. Validate with `spctl --assess -vv --type install path/to/app`. ---- - -# macOS App Store Certificates Guide - -_(Local + CI workflow with electron-builder — 2025 edition)_ - ---- - -## 1) Overview - -To build and publish your Electron app to the **Mac App Store (MAS)**, you need these **certificates** and a **provisioning profile**: - -| Item | Purpose | Used in | -| -------------------------------------- | ---------------------------------------- | ---------- | -| **Apple Development** | Sign local debug/test builds | Local only | -| **Apple Distribution** | Sign the App Store `.app` | Local + CI | -| **Mac Installer Distribution** | Sign the `.pkg` uploaded via Transporter | Local + CI | -| **Mac App Store provisioning profile** | Ties the App ID to Apple Distribution | Local + CI | - -> You **do not** need Developer ID certificates or notarization for MAS-only distribution. - ---- - -## 2) Generate a new CSR (Certificate Signing Request) - -1. On your Mac, open **Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority…** -2. Fill in: - -- **User Email Address:** your Apple ID for the developer team -- **Common Name:** e.g. `Super Productivity MAS Signing Key` -- **CA Email Address:** _leave blank_ -- **Request is:** _Saved to disk_ - -3. Save as `mac-mas.csr`. - - > This also creates a **private key** in your login keychain. - ---- - -## 3) Create the MAS certificates in the Apple Developer Portal - -1. Go to [https://developer.apple.com/account/resources/certificates/list](https://developer.apple.com/account/resources/certificates/list) → **➕ Add** -2. Create each certificate using **`mac-mas.csr`**: - -- **Apple Development** (for local testing) -- **Apple Distribution** (replaces “Mac App Distribution”) -- **Mac Installer Distribution** (required for `.pkg` upload) - -3. Download each resulting **`.cer`** file. - ---- - -## 4) Install and export the identities (for local and CI) - -1. **Install:** Double-click each `.cer` to add it under **Keychain Access → My Certificates**. - -- Each entry must show a **disclosure triangle** with a **private key**. -- If the private key is missing, regenerate the CSR and certificate. - -2. **Export:** Select the relevant identities → **right-click → Export …** - -- Format: **Personal Information Exchange (.p12)** -- Name: `mas-certs.p12` -- Set a strong password (→ `MAC_CERTS_PASSWORD`). - -3. **Verify on a second Mac (optional but recommended):** - - ```bash - security import mas-certs.p12 -k login.keychain-db -P "$MAC_CERTS_PASSWORD" - security find-identity -v -p codesigning - ``` - - You should see **Apple Distribution** and **Mac Installer Distribution**. - ---- - -## 5) Create / refresh the Mac App Store provisioning profile - -1. Go to [https://developer.apple.com/account/resources/profiles/list](https://developer.apple.com/account/resources/profiles/list) → **➕ Add Profile** -2. Profile type: **Mac App Store** -3. Select: - -- **Apple Distribution** certificate -- Your **App ID** - -4. Download as `mas.provisionprofile`. -5. Place it in your repo, e.g.: - - ``` - tools/mac-profiles/mas.provisionprofile - ``` - ---- - -## 6) Configure electron-builder - -In `electron-builder.yml` or `package.json > build`: - -```yaml -mac: - category: public.app-category.productivity - hardenedRuntime: true - provisioningProfile: tools/mac-profiles/mas.provisionprofile - entitlements: build/entitlements.mas.plist - entitlementsInherit: build/entitlements.mas.inherit.plist - target: - - mas -``` - -> Ensure your MAS entitlements files are correct and compatible with App Store requirements. - ---- - -## 7) Local build (MAS) - -With the identities installed in your keychain: - -```bash -npm run build && npm run dist:mac:mas -``` - -**Result:** `dist/mac/YourApp.pkg` — signed and ready for App Store upload. - ---- - -## 8) Prepare CI secrets - -Base64-encode the cert bundle and profile: - -```bash -base64 -i mas-certs.p12 -o mas-certs.b64 -base64 -i tools/mac-profiles/mas.provisionprofile -o mas-profile.b64 -``` - -Create **GitHub Actions** secrets (Repo → _Settings → Secrets and variables → Actions_): - -| Secret | Value | -| ------------------------- | --------------------------------------------------- | -| `MAC_CERTS` | contents of `mas-certs.b64` | -| `MAC_CERTS_PASSWORD` | the `.p12` export password | -| `MAS_PROVISION_PROFILE` | contents of `mas-profile.b64` | -| `APPLE_APP_SPECIFIC_PASS` | Apple ID app-specific password (for upload tooling) | - ---- - -## 9) GitHub Actions workflow (example) - -```yaml -name: Build macOS MAS -on: - workflow_dispatch: - push: - tags: - - 'v*' - -jobs: - build-mas: - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: Decode certificates - run: echo "${{ secrets.MAC_CERTS }}" | base64 --decode > mas-certs.p12 - - - name: Create and unlock keychain - run: | - security create-keychain -p "" build.keychain - security import mas-certs.p12 -k build.keychain -P "${{ secrets.MAC_CERTS_PASSWORD }}" -T /usr/bin/codesign -T /usr/bin/security - security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain - security list-keychains -s build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "" build.keychain - security find-identity -v -p codesigning build.keychain - - - name: Write provisioning profile - run: echo "${{ secrets.MAS_PROVISION_PROFILE }}" | base64 --decode > tools/mac-profiles/mas.provisionprofile - - - name: Install dependencies - run: npm ci - - - name: Build & sign for MAS - env: - CSC_LINK: ${{ secrets.MAC_CERTS }} - CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }} - CSC_IDENTITY_AUTO_DISCOVERY: true - APPLEID: you@example.com - APPLEIDPASS: ${{ secrets.APPLE_APP_SPECIFIC_PASS }} - run: npm run build && npm run dist:mac:mas -``` - -> The `set-key-partition-list` step grants non-interactive access to the private keys for `codesign` during CI. - ---- - -## 10) Upload to App Store Connect - -1. Find the generated `.pkg` in `dist/`. -2. Upload with **Transporter** (Apple’s tool): - -- Open Transporter, sign in with your Apple ID -- Drag the `.pkg` and click **Deliver** - -3. Optional verification: - - ```bash - pkgutil --check-signature path/to/YourApp.pkg - ``` - - Expect: - - ``` - Signed by "Apple Mac Installer Distribution: " - Status: signed Apple Software - ``` - ---- - -## 11) Maintenance & rotation - -- Certificates typically expire after **1 year** (some teams may have 3-year certs). -- Before expiry, repeat this guide: - - - Revoke/replace **Apple Distribution** and **Mac Installer Distribution** - - Recreate the **Mac App Store** provisioning profile - - Export a **new** `mas-certs.p12`, update **CI secrets**, and (if needed) reimport locally - -- Keep your **App-Specific Password** valid for uploads. - ---- - -### Quick Reference (What you actually need for MAS) - -- **Certificates:** Apple Development (local), Apple Distribution, Mac Installer Distribution -- **Profile:** Mac App Store provisioning profile -- **No** Developer ID / notarization needed for MAS-only -- **Build target:** `mas` -- **Upload:** `.pkg` via Transporter - ----