Locara

01 — Architecture

The three products

Locara is three products designed together but distributed apart:

  1. Website (locara.app) — discovery surface. Static. Catalog of apps, blog, docs, downloads.
  2. Framework — Rust crates + TS packages that each Locara app links into itself. Capability enforcement, model loader, SDK, sandbox, components.
  3. Registry + CI — small backend that signs published apps, hosts artifacts, serves manifests, maintains the kill-switch list.

Notably absent: there is no “Locara client” application. Each Locara app is a standalone signed Mac app downloaded directly from the website. The website is just HTML.

High-level flow

┌──────────────────────────────────────────────────────────────┐
│  WEBSITE (locara.app)                                        │
│  ─ Static site (Cloudflare Pages)                            │
│  ─ Catalog browse, search, app pages                         │
│  ─ Click "Download" → .dmg from R2 CDN                       │
└──────────────────────────────────────────────────────────────┘

                              │ download .dmg

┌──────────────────────────────────────────────────────────────┐
│  USER'S MAC                                                  │
│                                                              │
│  /Applications/                                              │
│    ├── Transcribe.app    ← signed, notarized, standalone     │
│    ├── DocVault.app                                          │
│    └── (other Locara apps as user installs)                  │
│                                                              │
│  Each app:                                                   │
│   ─ Tauri shell + frontend bundle                            │
│   ─ Locara framework (linked Rust + TS code)                 │
│   ─ Manifest declaring capabilities                          │
│   ─ macOS App Sandbox entitlements derived from manifest     │
│   ─ Per-app SQLite store                                     │
└──────────────────────────────────────────────────────────────┘

                              │ build + sign via CI
                              │ revocation + manifest API

┌──────────────────────────────────────────────────────────────┐
│  REGISTRY + CI (cloud)                                       │
│  ─ GitHub Actions: builds every published app                │
│  ─ Single Apple Developer ID signs all apps                  │
│  ─ Notarizes each app via Apple                              │
│  ─ Sigstore-style provenance attestations                    │
│  ─ Cloudflare R2: artifact storage + CDN                     │
│  ─ Postgres: manifest metadata, ratings                      │
│  ─ Manifest API + revocation list                            │
└──────────────────────────────────────────────────────────────┘

                              │ locara publish

┌──────────────────────────────────────────────────────────────┐
│  DEVELOPER'S MAC                                             │
│  ─ locara CLI (init, dev, test, publish)                     │
│  ─ App source uses @locara/sdk + @locara/components          │
│  ─ App's locara.json declares capabilities                   │
└──────────────────────────────────────────────────────────────┘

Layers inside a running app (top to bottom)

LayerWhatLives in
App frontendTypeScript + React + @locara/componentsThe app’s own JS bundle
App backend logicCalls into @locara/sdkThe app’s own JS code
Tauri webviewFrontend rendering (WKWebView on Mac)OS native
Tauri IPCTrust boundary; commands gated by capabilitiesTauri runtime, linked into app
Locara pluginsRust code exposing capability-gated commandslocara-* crates linked into app binary
Locara coreInference, sandbox, model loader, capability enforcerlocara-core crate linked in
macOS App SandboxKernel enforcement of declared entitlementsOS, configured per-app at build time

Each Locara app is a self-contained Mac app with the framework code statically linked. Two installed Locara apps are two independent processes; nothing is shared at runtime except OS resources (filesystem, model cache directory).

Trust boundaries

[Frontend (untrusted JS)]
        ↕ (Tauri IPC, capability-gated by Locara plugins)
[Locara Rust runtime (trusted, linked into the app)]
        ↕ (syscalls, kernel-gated)
[macOS kernel + App Sandbox]
  • The frontend is treated as untrusted. Even an LLM-generated component shouldn’t be able to do anything outside declared capabilities.
  • The Rust runtime is trusted but constrained by the manifest.
  • The kernel is the final enforcement layer for OS-level capabilities (network, filesystem, camera, etc.).

This layering is the same as Tauri’s; Locara adds manifest-driven capability declarations and the model/tool primitives.

Data flow: install

1. User browses locara.app (a website)
2. Clicks "Install Transcribe"
3. Browser downloads Transcribe-0.1.0.dmg from R2 CDN
4. User opens the DMG, drags Transcribe.app to /Applications
5. First launch: macOS verifies Locara CI signature + Apple notarization
6. App reads its embedded manifest
7. macOS provisions App Sandbox container at ~/Library/Containers/<bundle-id>/
8. App shows first-run consent UI (capability summary)
9. Models declared in capabilities are downloaded to shared cache on first use

No “install Locara first” step. No shared runtime to start. Standard Mac app experience.

Data flow: runtime (a user calls llm.chat)

1. App calls @locara/sdk: llm.chat({ model: 'qwen-3b', messages: [...] })
2. SDK serializes call, invokes Tauri IPC: invoke('locara_llm_chat', args)
3. Tauri checks: is "llm.chat" capability declared in this app's manifest?
   - If no: error to frontend.
   - If yes: route to locara-core code linked into the app binary.
4. locara-core checks: is the requested model in the app's declared models[]?
   - If no: error.
   - If yes: load model from shared cache (or use already-loaded), run inference.
5. Stream tokens back through IPC to frontend.

All within one process. No daemon, no cross-app coordination needed.

Data flow: publish

1. Developer runs: locara publish
2. CLI validates manifest, runs capability tests locally
3. CLI pushes git ref + manifest to Locara registry submission API
4. Registry queues the submission; triggers GitHub Actions
5. CI clones source by commit hash in clean environment
6. CI runs: locara verify --strict, locara test
7. CI runs: tauri build (produces unsigned .app bundle)
8. CI runs: codesign with Locara's single Apple Developer ID
9. CI runs: notarize via Apple's notarization service; staples ticket
10. CI generates: Sigstore-style provenance attestation
11. CI uploads: signed .dmg to R2, manifest to Postgres, attestation to log
12. Manifest review: auto-approve if low-risk; queue for human if not
13. Once approved: app live on the website, downloadable

The developer never uploads a binary. CI builds + signs + notarizes from clean source.

Module decomposition

Rust crates (crates/)

These are library crates that apps depend on, not standalone binaries:

  • locara-core — capability enforcement, model loading, inference (llama.cpp + MLX-future).
  • locara-storage — sqlite + sqlite-vec adapter, zvec adapter, schema migrations.
  • locara-models — model registry client, content-addressed fetch, manifest validation.
  • locara-tools — Wasmtime + WASI tool runtime, tool registry.
  • locara-runtime — Tauri plugin orchestration; the Rust side of @locara/sdk’s IPC.
  • locara-cli — the locara binary (developer tool, NOT shipped to users).

Note: there is no locara-shell crate. Each Locara app embeds its own Tauri shell directly via the standard Tauri build process; locara-runtime is the framework code that gets linked in.

TypeScript packages (packages/)

  • @locara/sdk — API surface developers code against.
  • @locara/components — shadcn-style UI primitive registry source.
  • @locara/manifest — JSON schema + TS types for locara.json.
  • @locara/test — test helpers for capability tests.

No @locara/client package. The website is in website/; it’s plain Astro/HTML.

Reference apps (apps/)

  • transcribe/ — first reference app.
  • docvault/ — second reference app.

Each is a standalone Tauri project with its own Cargo.toml, package.json, and locara.json.

Cloud (registry/, website/)

  • registry/ — GitHub-Actions-based CI, manifest API (Cloudflare Workers), R2 artifact storage.
  • website/locara.app static site (Astro). Marketing, catalog, blog, docs.

See 17-repo-layout.md for full repo structure.

What runs at app launch

When a user opens Transcribe.app:

  1. macOS starts the app process.
  2. Tauri initializes; loads the app’s Rust backend (which includes the linked locara-* crates).
  3. The app reads its embedded locara.json manifest.
  4. The Locara runtime registers Tauri commands for declared capabilities only (commands not declared are not exposed to the frontend).
  5. macOS App Sandbox enforces entitlements (set at build time from the manifest).
  6. Tauri webview opens with the frontend bundle.
  7. Frontend ↔ Rust IPC begins.

No Locara process is running other than the app itself. If the user opens a second Locara app, that’s a second independent process.

Cross-app concerns (kept minimal)

  • Shared model cache — all Locara apps read from ~/Library/Caches/Locara/models/ (a directory, not a process). Apps download models there if missing; entries are content-addressed by SHA, so no conflict. Each app’s bundle has hardlinks into this cache.
  • Shared folder IPC — the explicit shared-folder mechanism in 03-capabilities.md. Apps that mutually declare a shared folder see each other’s files.
  • No process-level IPC, no daemon, no shared runtime in v1. macOS handles everything else (window management, memory pressure, scheduling).

What the website does (and doesn’t)

locara.app is a static Astro site. It:

  • Lists apps (catalog generated from registry data).
  • Renders app pages (manifest data + screenshots + reviews).
  • Hosts blog, manifesto, docs.
  • Provides download links for each app’s signed .dmg.

It does not:

  • Run JavaScript that talks to your Locara apps directly.
  • Track you (no analytics).
  • Require an account to browse or download.

Optional: a future “Locara Manager” menubar utility (phase 3+, not v1) could provide a unified view of installed Locara apps + update status. Not required for the architecture.

What we removed from earlier drafts

  • locara-shell Tauri app.
  • ❌ “Locara client” desktop application.
  • ❌ Per-publisher Apple Developer Program enrollment.
  • ❌ Centralized runtime daemon.
  • ❌ “Open Locara, then open the app” two-step UX.

All replaced by: standalone signed Mac apps + a static website.

Single-app vs daemon (open)

v1: each Locara app is its own process; framework is linked in. Simple, native UX. Cost: two apps using the same model load it twice in RAM (modulo OS-level mmap-sharing of the same file).

v2+: optional shared-runtime daemon. A long-running background service that hot-swaps models, arbitrates RAM, lets multiple apps share loaded weights. Adds operational complexity. Apps wouldn’t change shape; the daemon would just be a transparent optimization that opt-in apps can use.

Architecture leaves room for this without requiring it.

Cross-platform extension (post-v1)

  • iOS / iPadOS: capability subset (no tool exec, no network unless declared, no filesystem outside container). The manifest is the same; some capabilities are unavailable. Apps would be packaged via App Store, not direct .dmg.
  • Linux: WebKitGTK has rough edges; Tauri Linux story improving. Direct distribution via .AppImage / .deb feasible.
  • Windows: WebView2 is solid. Direct distribution via .msi / .exe feasible. Code signing via Microsoft’s processes.

These are architectural compatibility goals, not v1 deliverables.

Cross-references