2026-08-06 01:44:58 -05:00
2026-09-21 10:23:09 -05:00

Productivity Suite

This workspace is the implementation and integration home for a private, self-hostable productivity suite. The intended suite includes a Greenfield React productivity experience, Daymark's calendar work, Baïkal, SuperSync, and the existing Super Productivity MCP tooling.

Phases 0 through 8 are complete, including live Google federation qualification for Phase 3. The runnable self-hosted suite includes secure single-owner authentication, encrypted Baïkal planning, a durable browser-local task cache, replay-safe queued task writes, explicit two-client conflicts, daily-use task organization, and one server-authoritative focus/break session with follower and takeover behavior, plus separately scoped automation credentials, a stable preview/confirm API, content-safe audit records, a catalog-driven local MCP stdio adapter, quick-add through the same confirmed API, and a separate Template Library with inert templates, ordered Template Sets, explicit-project instantiation, immutable provenance, sync snapshots, and confirmed MCP instantiation. Google calendar-list/event read scopes, encrypted refresh grants, incremental projection, explicit freshness, and calm daily planning are present and were qualified against a real Google OAuth grant on 2026-08-07. It does not claim offline calendar/focus mutation, closed-application background sync, recurrence editing beyond read-only Google instances, or hosted MCP.

Calendar migration accepts either a generic ICS payload or an explicit Google Calendar ICS/Takeout export. Preview reports recurrence, attendees, alarms, vendor/unknown properties, duplicates, and malformed components without writing to Baïkal. Apply is a one-time, replay-safe copy with stable CalDAV resource identities. Authenticated exports and opaque capability feeds preserve the original VEVENT fields; capability URLs support GET/HEAD only and can be revoked immediately. This is migration and read-only publication, not Google OAuth, CalDAV write access, or background mirroring.

Phase 8 adds a packaged Linux Electron client that displays the same Suite origin without Node integration or a second data authority. Release operations use immutable version/revision/image-digest manifests, explicit promotion and rollback history, coherent backup/restore, and content-free Prometheus metrics at /api/metrics. Android/iOS, PostgreSQL, and multi-user mode are deliberately not shipped because their conditional roadmap prerequisites are not met.

Run the Suite

Requirements: Docker with Compose, or Node.js 24+ and pnpm 11.15.1 for local development.

docker compose up --detach --build --wait
./deploy/smoke.sh

The React first-run application is available at http://127.0.0.1:18080. Baïkal's installer/admin interface is available at http://127.0.0.1:18086/admin/ until the first-run owner flow connects it. Change either loopback port with SUITE_PORT or BAIKAL_PORT; public TLS and routing belong at the edge and are intentionally not embedded in this local Compose file.

On first load, create the single Suite owner, sign in, and enter the credentials for the Baïkal user you created in Baïkal's admin interface. The Suite connects only to its server-configured http://baikal/dav.php/ endpoint, verifies the credentials through CalDAV, encrypts the password, and displays discovered calendar collections with separate Events and Todos capabilities. A server administrator may point BAIKAL_ENDPOINT at a different CalDAV deployment; arbitrary browser-entered connector origins are intentionally unsupported.

After Baïkal is connected, the owner sees supported non-recurring UTC-timed events in the current seven-day window. They can capture, rename, annotate, complete, reopen, soft-delete, and recover Suite-owned tasks, then choose an event-capable calendar, start, and duration for one task time block. A move uses the previously observed strong DAV ETag; if the event changed elsewhere, the UI shows a conflict and does not overwrite it. Removing a time block likewise uses its stored ETag; a task with an active block must be cleaned up before it can be soft-deleted.

Each authenticated browser registers a separate owner-scoped client and keeps its raw client proof, canonical task cache, immutable outbox, cursor, conflicts, and content-free diagnostic metadata in IndexedDB. Core task create/edit, complete/reopen, delete/restore, and estimates can be queued temporarily offline; the foreground app synchronizes on load, explicit activity, and the browser online event. Project, tag, subtask, calendar, connector, and focus commands remain online-only. A focus session has one controller; another client observes it read-only and must explicitly take over before controlling it.

For the public HTTPS deployment, set SUITE_SECURE_COOKIES=true so the opaque session cookie is sent only over TLS. Preserve the original public Host header at the reverse proxy; unsafe API requests compare it with the browser's Origin in addition to requiring the session CSRF token.

Persistent data lives in three named volumes:

  • suite-data: Suite SQLite database and backups
  • baikal-specific: authoritative Baïkal DAV database/resources
  • baikal-config: Baïkal configuration

Create a Suite-only online SQLite and connector-key backup pair with ./deploy/backup.sh. Restore one with ./deploy/restore.sh <database-backup-basename>; restore stops only the Suite service and retains pre-restore database and key copies.

For a coherent Phase 1 recovery point containing all three volumes, use:

./deploy/backup-stack.sh /absolute/new/backup-directory
./deploy/restore-stack.sh /absolute/backup-directory

The full-stack backup stops both SQLite writers briefly, copies Suite data and Baïkal's authoritative database/configuration, records SHA-256 checksums, then restarts and waits for both services. restore-stack.sh verifies every checksum before intentionally replacing the selected Compose project's volumes. Select the project with COMPOSE_PROJECT_NAME when it is not the default. Protect the backup directory as a secret: it contains the mode-0600 Suite credential key, encrypted connector material, Baïkal users, and calendar resources.

Develop and verify

pnpm install --frozen-lockfile
pnpm dev
pnpm verify
./deploy/verify-compose.sh
pnpm verify:phase1
pnpm verify:phase2
pnpm verify:phase4
pnpm verify:phase5
pnpm verify:phase6
pnpm verify:phase7
pnpm verify:phase8
pnpm verify:phase9
pnpm verify:phase10
pnpm verify:phase11

pnpm verify is the canonical local code gate. The Compose verification is a slower disposable deployment check: it builds both services, validates rendered HTTP/API output, proves installation identity across restart, replaces the database and credential key, restores the matched backup pair, and removes its test volumes. pnpm verify:phase1 additionally requires Docker Compose and a Chromium binary at /usr/bin/chromium (override with PLAYWRIGHT_CHROMIUM_PATH). It provisions only synthetic data in a disposable Baïkal instance, drives the real UI, proves conditional VEVENT CRUD and visible conflict handling, restarts the Suite, restores all state into fresh volumes, repeats task placement, and removes the verification volumes.

pnpm verify:phase2 uses two disposable persistent Chromium profiles. It proves offline task create/edit across profile close/reopen, reconnect without a duplicate task, visible same-field conflict handling, follower takeover, and the same authoritative focus session after a Suite restart. Lease expiry and the no-duplicate-interval transition matrix use an injected clock in server tests; no test clock endpoint exists in the Compose runtime.

pnpm verify:phase5 qualifies only reusable Task Templates and Template Sets: inert template records, explicit existing-project instantiation, independent subtask snapshots with provenance, exact-once retry across a restart, a real local stdio MCP preview/confirmation, and paired Suite backup/restore. Choice Pools and Planning Placeholders are Phase 6 work and are not asserted by this gate.

pnpm verify:phase6 qualifies dedicated Choice Pools and ordered candidates, logical-time cooldown/cycle/one-shot eligibility explanations, editable history- preserving pools, template pool slots, two-client placeholder resolution, catalog-derived local MCP preview/confirmation, restart replay, and SQLite backup/restore. Suggestions are read-only; only confirmation creates ordinary subtasks and append-only selection history.

pnpm verify:phase7 provisions a synthetic owner and real disposable Baïkal calendar, previews and applies a recurring Google-export fixture, proves a retry and Suite restart leave exactly one remote resource, performs a coherent full-stack backup/restore, checks preserved ICS export, and finally revokes the GET-only capability feed.

pnpm verify:phase8 runs the canonical gate, release-channel and metrics tests, creates an actual Linux x64 Electron directory bundle, starts its executable in non-graphical smoke mode, and qualifies a versioned production Compose image through readiness, metrics, restart, backup/restore, and candidate promotion. Production rollout and rollback procedures are in docs/operations/release-and-rollback.md.

pnpm verify:phase11 qualifies the durable occurrence/kind notification ledger, calm-day suppression, explicit transient retry, ambiguous-response fail-closed behavior, redacted owner health APIs, Settings controls, scheduler restart replay, and the disposable recovery image. Live ntfy acceptance uses a dedicated write-only publisher on NUC's private management network as documented in docs/operations/tadooer-production.md.

Build the desktop bundle with pnpm package:desktop. Its default authority is http://127.0.0.1:18080; set SUITE_SERVER_URL to an HTTPS origin for a remote deployment. The shell rejects non-loopback plaintext HTTP, URL credentials, paths, queries, fragments, cross-origin navigation, embedded webviews, and renderer Node access.

The Phase 0 contract and authority decisions are recorded in docs/adr/0008-phase-0-identities-api-and-authority.md. The bounded Phase 1 projection, write, and recovery rules are recorded in docs/adr/0009-phase-1-planning-and-caldav.md. The Phase 2 task-sync and active-session authority rules are recorded in docs/adr/0010-phase-2-local-sync-and-active-session.md. The Phase 4 automation authority and local-only transport decision are recorded in docs/adr/0011-phase-4-automation-authority.md. The Phase 5 reusable-work identities, snapshot, and exact-once decisions are recorded in docs/adr/0012-phase-5-reusable-work.md. The Phase 6 logical-time policy, placeholder, conflict, and history authority is recorded in docs/adr/0013-phase-6-choice-pool-authority.md. The Phase 7 preserved-import, stable-identity, and read-only publication rules are recorded in docs/adr/0014-phase-7-import-publication.md. The Phase 8 desktop authority, release channel, observability, and conditional platform decisions are recorded in docs/adr/0015-phase-8-packaged-operations.md.

An owner issues, inventories, and revokes automation credentials through /api/automation/tokens; the raw suite_at_... credential is returned only at creation. Store it in a regular file owned by the current user with mode 0600. The local clients are:

node apps/mcp-stdio/dist/main.mjs \
  --url http://127.0.0.1:18080 --token-file /absolute/path/suite.token

node apps/quick-add/dist/main.mjs \
  --url http://127.0.0.1:18080 --token-file /absolute/path/suite.token \
  --idempotency-key quick-add-20260806-001 "Capture this task"

Both clients reject non-loopback plaintext HTTP, reject token files that are not owner-only, and use only the cataloged automation API. The MCP adapter is newline-delimited JSON-RPC over stdio; no hosted MCP route, Super Productivity plugin IPC, or environment bearer-token shortcut is shipped. Google Calendar operator setup and the completed live qualification record are documented in docs/operations/google-calendar.md. Run pnpm verify:phase3:foundation without credentials for deterministic protocol coverage; the dated runbook record separately captures the real grant and provider evidence. The disposable phase gates are local verification, not a production deployment or a universal provider compatibility claim.

Existing systems under consideration

  • Super Productivity fork: /home/onnwee/Projects/forks/super-productivity
  • Daymark calendar: /home/onnwee/Projects/tools/calendar-app
  • Super Productivity MCP suite: /home/onnwee/Projects/tools/super-productivity-mcp
  • Baikal: deployed service; source repository or deployment definition still to be identified during discovery
  • SuperSync: currently developed and shipped from the Super Productivity repository

Discovery

The active requirements interview is recorded in docs/discovery/requirements-interview.md.

Candidate product requirements and their implementation boundaries live under docs/product/candidate-features/. The Task Templates and Choice Pools record now distinguishes the completed Phase 5 template slice from the remaining Phase 6 Choice Pool work.

Implementation order is governed by the Feature Prioritization rules and the Roadmap, not by feature parity with Super Productivity.

https://www2.onnwee.me

S
Description
Personal productivity suite
Readme
2.3 MiB
Languages
TypeScript 91.5%
JavaScript 4.7%
CSS 1.7%
Shell 1.4%
Python 0.6%
Other 0.1%