WrengleWrengle
Architecture overview

Architecture overview

Beta

Wrengle is a local-first desktop app. A native desktop workspace runs on top of a local application core, with an explicit plugin surface for trusted extensions.

Major parts

PartStatusResponsibility
Desktop workspaceAvailableShell, file tree, command palette, editor, chart documents, meetings, terminal, settings, search, integrations, workflows, agent surfaces, and stores.
Desktop account identityAvailableOptional system-browser sign-in with PKCE. Rust owns the OAuth exchange, refresh lifecycle, OS-keychain credentials, and the sanitized account snapshot exposed to the renderer. Local workspace use remains available while signed out.
Local application coreAvailableOwns vault files, chart persistence, search, local models, jobs, terminal, and desktop orchestration. Provider-backed AI or speech, connected services, optional accounts, sync/backup, model downloads, and updates cross the network at their documented boundaries.
Website and accounts platformAvailablePublic marketing and downloads plus Clerk-backed individual sign-up, sign-in, account dashboard, profile/security management, deletion, server-side authorization, and account webhooks at wrengle.com.
Public documentationAvailableStatic public documentation served by the website at wrengle.com/docs. Every page is public and never gated.
Plugin APIBetaShared plugin and action contract types, Rust SDK DTOs, and host helper shapes for local WASM action plugins. No public stability guarantee yet.
Plugin hostBetaLocal plugin discovery, manifest validation, sandboxed WASM action execution, grant-gated host functions, app-mediated write proposals, view registration, and diagnostics.
Plugin viewsBetaSandboxed plugin-view hosting, view registration, and first-party reference views such as JSON Compare.
Durable workflow effect serviceInternal seamA single-writer desktop service over dedicated workflow.db: immutable revisions, approvals, encrypted effect intents, receipts, and retention. The existing Workflows builder uses this service only for manual Gmail draft approvals and dispatch; it remains the sole authoring surface and keeps its established runner and scheduler.
Jira OAuth brokerInternal foundationA separate account- and supplied-device-identifier-bound service for Atlassian confidential code and refresh exchange only. Desktop identity does not expose this broker as a user-facing connection or workflow target. The broker stores short-lived encrypted handoffs, not workflows, vault content, effects, or run history.

Feature surfaces

The workspace is organized by feature:

  • App frame, file tree, command palette, utility rail, status/update surfaces, and session restore.
  • The editor with serialization, tabs, pane splits, formatting, media assets, semantic workflow blocks, AI, and integration action UI.
  • Chart document surfaces for local vault diagrams and flows, including a theme-aware diagram editor, shape and connector editing, arrange and zoom controls, page and context menus, and split-pane realtime editing for the same local document.
  • Local stores for vault, workspace, panes, settings, search, meetings, terminal, integrations, plugin actions, workflows, agents, local models, and UI state.
  • Meetings, search, terminal, settings, integrations, workflows, agents, and history feature surfaces.

The application core exposes capability groups to the workspace covering vault/files, workspace/session, search/backlinks, AI, local model downloads, ACP agents, integrations/configured actions, plugins, transcription/live transcription, calendar, terminal, settings, updater, models, orchestration, and jobs.

Meeting pipeline

Meetings have one canonical pipeline: live transcript → saved final transcript → one six-field final report. Automatic and Manual are scheduling modes for that same report command, not separate implementations. After Stop is the clean-install preparation default and does no report-provider work during capture. Independent, local rolling final transcription is default-on when the device has enough decode capacity and is not coupled to report mode.

Committed captions immediately feed a bounded, correction-aware extractive preview; a refinement updates the same caption ID. That process-memory-only preview remains available through Stop and can be republished after a UI reload while the active desktop process retains the session. It is never placed in recovery, another disk file, logs, or telemetry. The opt-in Report preparation Auto path may supersede it with validated provider-backed state from completed final-quality transcript chunks.

The canonical final transcript display state also has a separate, bounded 30-second process-memory handoff after runtime teardown, closing the save-cleanup/reload race without extending recovery-file retention. The handoff is fenced to the exact vault-open epoch and revoked on vault retirement.

Physical Stop closes ordinary rolling dispatch. A request admitted before Stop may settle. If complete final coverage is still missing—and only when the provider was prewarmed and the entire bounded remainder fits—at most one exact full-report canonical tail may then start. Stop accepts prepared state only when its frontier, revision, schema, route, destination, note target, and note identity all match.

If no tail started, an invalid or oversized remainder uses bounded saved-transcript context: complete through 32,000 transcript characters, then five windows spanning the beginning, interior, and end. User-owned note text is complete through 8,000 characters and uses the same five-window strategy above that cap. The context is Condensed whenever either cap applies.

If the canonical tail started, Wrengle never sends a second automatic request; an ambiguous exposure or later note-context change requires manual review and retry. Final report synthesis uses native six-field structured output on compatible OpenAI and Anthropic models and Wrengle Local, with the strict prompt/parser fallback retained for legacy, custom, and other routes. Live automatic publication acknowledges the durable note and recovery metadata before a best-effort whole-vault Git snapshot, so repository size is outside the report-ready critical path.

Strict versioned recovery lives under .app/live/. It stores completed transcript records, exact save/report bindings, contiguous report-attempt revisions, and content-free provider-exposure claims, but no raw audio or prepared report content. A claim is durable before each during-recording cloud dispatch and completed after the request settles. An unproven completion blocks automatic provider work at manual retry rather than allowing an ambiguous replay.

Plugin manifest capability declarations are not grants. Plugin grants are stored as local app-install decisions and resolved before a WASM action receives host APIs. noteWrite and blockWrite requests create write proposals for the app to approve, not direct note or block mutations from plugin code.

Durable Gmail action seam

The existing Workflows builder remains the only authoring experience. When Dry run reaches Gmail → Create draft, orchestration freezes the exact recipient, subject, and upstream-produced body into encrypted effect intents. It also encrypts the complete runtime snapshot—workflow definition and configuration, objective, accumulated artifact bodies and structured output paths, manager review, and audit state—so the same approval can be reconstructed after restart. The internal immutable revision contains only safe bridge IDs, provider and operation bindings, and opaque keychain-keyed request fingerprints—never the message content. Narrow approval APIs let the same builder reopen and resolve that batch after restart; the removed V3 authoring commands and general run dashboard are not public surfaces.

The local Gmail path is:

manual dry run → freeze exact Gmail batch → encrypted durable prepare → 24-hour approval → token-fenced atomic effect claim → dispatch revalidation → Gmail draft commit → receipt

The stable logical effect key uses revision, run, node, input lineage, and effect index; it deliberately excludes attempt ID. One approval gate covers the exact prepared Gmail batch for one run. Terminalizing a run atomically cancels every intent that has not crossed the provider boundary; a committing intent becomes Unknown outcome rather than being guessed or replayed. The complete recovery snapshot and per-run provider payloads have a seven-day encrypted retention window; only the new bridge's content-safe plaintext metadata, keyed request bindings, and receipts have a 90-day window. Unreferenced new internal bridge revisions are collected after that metadata window. Recipient and subject remain part of the existing builder's normal local workflow definition until edited or deleted; their exact prepared copy, the upstream-produced body, and the rest of the runtime snapshot are encrypted and expire with the prepared payload. Legacy preview-authored definitions and revisions can contain plaintext names, descriptions, and action configuration and can remain until explicit app-data cleanup or uninstall; they are not covered by the seven-day payload retention rule.

This bridge creates drafts only and never sends messages. Gmail actions remain manual, so the existing unattended runner and scheduler reject them. The service does not yet provide general durable history or broad migration from the editable workflow store.

MCP core defines a narrow client-session adapter contract intended for a future official Rust SDK integration over local stdio or remote Streamable HTTP. Connection policy separately validates command configuration or public-network URLs, and an opaque approved session is the only planned tool-call surface. Server identity and the exact tool schema can be pinned to reviewed workflow revisions. Tool annotations are never treated as grants. No SDK-backed desktop adapter or connection UI is wired in this release. Jira workflow handoff and execution also remain dormant.

workflow.db is app-global, but vault-owned records carry a scope derived from the durable random UUID in the attested .app/crdt-identity.v2.json index plus the live filesystem identity of the opened root. Every renderer call also presents the opaque capability for that exact vault_open epoch. This prevents stale windows, root replacement, inode reuse, or a copied identity file at a different root from inheriting another vault's records. The unreleased inode-only preview namespace is not auto-migrated because it cannot prove durable ownership. The Tauri process is the initial single writer. The later opt-in local worker is intended to take over that unchanged service through authenticated local IPC; it is not part of the current hosting model. The /app Jira broker is deliberately not reusable as workflow ingress or execution.

Local-first boundary

The vault is the center of durable user data. The rebuildable search/RAG index lives per vault in Wrengle's private OS app-data directory rather than inside a user-selected or synced vault. It can contain derived note text and is safe to delete and rebuild from vault notes; local-only index preferences and workspace layout metadata stored with it reset when it is deleted. Index database aliases are rejected before open. Rebuildable indexes and generated state should not be confused with user-owned notes and metadata.

Local editor and chart recovery state is stored in vault app data under .app/crdt.db. It is a Yjs-backed local durability layer for the desktop workspace, not a hosted sync backend or cross-device collaboration service. Chart documents also keep projection files in the vault so diagrams and flows remain normal local vault documents while recent unsaved or recovered edits can be reconstructed from local CRDT state when needed.

Account boundary

Clerk is the authority for account credentials, authentication methods, and sessions. The website validates browser session tokens server-side. The desktop uses a separate public OAuth client with system-browser PKCE and loopback callback; access and refresh credentials remain in the operating-system keychain and are never returned through Tauri IPC. Debug and release builds use separate stable credential slots. Earlier unbound account slots are deliberately never inferred, moved, or deleted because their Clerk environment cannot be proven.

The account service mirrors only the profile data needed for Wrengle account features. Webhook delivery and authenticated-request provisioning are idempotent, ordered, and deletion-aware. Deleting an account removes the active profile and dependent server records while retaining only a keyed, pseudonymous tombstone needed to reject delayed recreation. This lifecycle does not read, upload, delete, or otherwise mutate a local vault.

Public docs boundary

This documentation is part of the public website: the same service builds it, serves it, and serves the marketing pages. It does not reuse the desktop app's build, internal commands, or runtime state. Every documentation page is public, rendered ahead of time, and readable without an account.

When a publishable key is supplied at build time, the website exposes that value to the browser and renders the account menu inline. Production builds accept only a syntactically valid pk_live_ value from the existing production instance; an unset value preserves the public fallback. The build also carries the website's own origin — localhost in development and the production Wrengle domain everywhere else — and fails closed to production if that value is unrecognized. Without the publishable key, or when the account provider is unreachable, the site keeps rendering and falls back to a normal website sign-in link.

The service does hold server-side credentials — the account secret key, the webhook signing secret, and the database URL. The boundary is that none of them ever reach the browser: only the publishable key and the public origin are exposed to the client bundle, and every secret stays server-side.

The production server answers the retired documentation subdomain with a permanent redirect to this site, and adds X-Frame-Options: DENY, HSTS, content-type sniffing protection, a strict referrer policy, and a restricted permissions policy to every response — including the pages that were rendered ahead of time.

docs / developers/architectureAll documentation