WrengleWrengle
Local development

Local development

Available

Use the repository root for desktop app development and app/ for website (and documentation) development.

Clerk development environments

Reuse the existing production Clerk instance and users; do not replace or migrate production identities. Keep a separate Clerk development instance. Local website runs use the development instance's publishable key; production DNS, OAuth applications, redirects, and webhooks belong only to the existing production instance.

The website reads its browser publishable key and server-only credentials from its environment files under app/. Because the website also renders the documentation you are reading, there is no separate documentation process, key, or origin to keep in sync — the same dev server and the same publishable key cover both.

Do not add Clerk server secrets, webhook signing secrets, session tokens, or desktop OAuth credentials anywhere public content is generated from. Development startup accepts only a syntactically valid Clerk publishable key beginning with pk_test_ or pk_live_. A production build accepts only the valid pk_live_ key whose Frontend API is exactly clerk.wrengle.com. Railway's deployed production build requires that exact key. A malformed or whitespace-padded value aborts before any credential can be serialized into the public build.

The website serves both the marketing pages and the documentation from a single origin, so there is no separate documentation origin to configure.

All local surfaces

bash
bun install
bun run dev:all

This starts the desktop app and the website — which also serves this documentation — at http://localhost:3000. Press Ctrl-C in that terminal to stop both.

For native account testing, create the public, PKCE-required desktop OAuth Application in that same development instance. Root WRENGLE_CLERK_ISSUER_URL must match the instance encoded in app's VITE_CLERK_PUBLISHABLE_KEY; root WRENGLE_CLERK_DESKTOP_CLIENT_ID must equal app's CLERK_DESKTOP_OAUTH_CLIENT_ID; and root WRENGLE_ACCOUNT_API_URL must be exactly http://localhost:3000. Copy that opaque Client ID from the OAuth Application's Application credentials section. Current Clerk Client IDs are 16 alphanumeric characters with no prefix; do not use a key, secret, token, or current oa_.../legacy oauthapp_... application resource ID. dev:all validates those public values before launch without forwarding server secrets. Debug and release builds use separate stable OS-keychain account slots.

The desktop app launched through bun run tauri dev uses an amber development icon so it is visually distinct from production builds in the Dock or taskbar. Release builds keep the production Wrengle icon.

Internal Jira OAuth broker

The accounts app contains a dormant Jira Cloud OAuth exchange foundation. The desktop has optional account identity, but it has no Jira device-enrollment bridge, broker call site, or executable Jira workflow target. Every Jira broker route returns the same non-cacheable 404 in production and by default in development. To test only this internal foundation, opt in explicitly:

text
JIRA_OAUTH_BROKER_ENABLED=1
ATLASSIAN_OAUTH_CLIENT_ID=...
ATLASSIAN_OAUTH_CLIENT_SECRET=...
ATLASSIAN_OAUTH_CALLBACK_URL=https://your-dev-host/api/workflows/jira/oauth/callback
JIRA_OAUTH_DESKTOP_REDIRECT_URI=wrengle://oauth/jira
JIRA_OAUTH_BROKER_ENCRYPTION_KEY=... # base64-encoded 32-byte key

The flag works only with NODE_ENV=development; production ignores it even if it is accidentally configured. Run the Drizzle migration before testing. The Atlassian console callback must exactly match ATLASSIAN_OAUTH_CALLBACK_URL. Broker logs and tests must never print codes, handoffs, access tokens, refresh tokens, or decrypted bundles. This developer opt-in is not a release smoke gate and does not make Jira a shipped connection.

macOS Keychain prompts

Startup uses a non-secret catalog to enumerate every currently configured, allowlisted app-owned secure item, then reads those items one at a time before mounting the workspace. Provider and speech keys, connected-service OAuth tokens, the current build's account bundle, configured-action and current-plugin secrets, and required workflow secure state can each trigger an item-specific macOS dialog for com.wrengle.app. Startup does not contact a provider, refresh OAuth, verify an account, run an action, or grant a capability while doing this.

The requested password is the current Mac login password. Allow approves that item access once and is sufficient for the current session because ordinary feature paths use the sealed native cache. Always Allow remembers access for the current app identity. Deny puts only dependent capabilities in Limited mode. Opening Settings or using a feature cannot fall through to a new Keychain dialog.

The tauri dev app is ad-hoc signed, so a rebuild can change its code identity and cause macOS to prompt again even after Always Allow. Do not rewrite Wrengle keychain items with an allow-all access list: that would let unrelated local processes read the credentials. Use separate development/test provider keys and approve access only for the current app build.

If you previously ran the removed just dev-keychain-trust helper, removing the helper does not repair the permissive access lists it wrote. Quit Wrengle, open Keychain Access, select the login keychain, search for com.wrengle.app, and delete only the Wrengle development credential items you intend to replace. Then relaunch Wrengle and add replacement development keys or reconnect the affected OAuth integration through the app so macOS creates new restricted items. Rotate old development keys if other local processes could have read them. This recovery intentionally uses no terminal command that reads or prints secret values.

When testing provider keys after startup, an explicit Save key, Replace, or Remove action made while Wrengle is focused may show the item-specific macOS dialog. This is expected when a development rebuild has a different ad-hoc identity; approve the change only for the Wrengle build you are running. Canceling or denying it fails closed and revokes the affected session authority. Background rotations, automatic cleanup, and ordinary feature use keep authentication UI disabled. A restart retries only entries still authorized by non-secret startup metadata; broker failed-mutation tombstones deliberately cannot rediscover an old physical value. The native cache is zeroizing process memory and is never exposed through generated bindings, logs, telemetry, or frontend storage.

Build and tests

just ci is the canonical local approximation of CI. It runs logic tests, lints, the frontend build, unit tests, version checks, and bindings drift.

bash
just ci

Before release work, also run:

bash
just release-preflight

Website and documentation

The documentation you are reading lives as content under app/content/docs, rendered by the same website that serves the marketing pages. There is no separate documentation project, dependency install, or build.

bash
bun install --cwd app --frozen-lockfile
bun run --cwd app typecheck
bun run --cwd app test
bun run --cwd app dev

Typechecking and tests need no account or database environment. The production build does: prerendering renders real routes through a preview server and fails with DATABASE_URL is required before writing a page when deploy-shaped inputs are absent. Run the repository-root just ci command for the canonical build validation; it supplies the current throwaway values defined by the root justfile's app_ci_env. If you need only the app build, use those exact current values with bun run --cwd app build rather than treating a plain, environment-free build failure as a product failure.

Run the website's tests once without a publishable key to verify the public fallback, then repeat a browser smoke test with the development publishable key to verify sign-in return URLs, Dashboard/Manage account/Sign out actions, continued access when Clerk requests are blocked, and that signing in on a marketing page leaves you signed in on a documentation page.

Internal development routes

The desktop app may include /dev/* routes during development. /dev/job-demo is a non-blocking job UI demo for validating local job/status behavior; it is an internal development surface, not a public product workflow.

docs / developers/local-developmentAll documentation