Locara

46 — Privacy Nutrition Labels Format

A standardized, structured way to describe each Locara app’s privacy properties on the registry catalog and within the app’s own UI. Inspired by Apple’s App Store privacy nutrition labels but adapted to Locara’s local-first reality.

The point: a non-technical user can glance at a Locara app and understand exactly what it can do without reading the full manifest.

Why this exists

Manifest declarations are precise but technical (net: { allowed_hosts: ["api.example.com"] }). For users browsing the catalog, we need a higher-level, plain-language summary that:

  • Is auto-generated from the manifest (not author-written marketing).
  • Is consistent across all apps (no app can present its privacy story differently from another).
  • Is at-a-glance scannable (visible on app cards in 0.5 seconds).
  • Is drillable (one click reveals more detail).

This is the registry-side version of the consent UI shown on first launch (per 25-onboarding.md).

The label structure

A privacy label consists of:

  1. Top-level badges (most prominent visual, always shown on cards)
  2. Capability summary (“This app: … / This app does NOT: …”)
  3. Data handling (what stays local, what leaves)
  4. Models + tools (what AI/computational resources)
  5. Trust attestations (signing, provenance)

Top-level badges

Each badge is a single icon + label. Auto-derived from the manifest. Always shown on app cards.

BadgeIconAwarded when
🔒 Fully Locallocknet: false AND all models in registry’s curated list AND all tools have net: false
📵 No Telemetrycrossed-out-broadcast(implied for all Locara apps; the framework forbids it) — shown to reinforce
📦 Open Sourcecoderepository field present and resolves to a public OSS repo
Verified PublishercheckmarkPublisher has DNS-verified domain
🔬 Verified PrivacyshieldPaid certification (post-phase-4 product)

A “Fully Local” app gets the most prominent badge treatment; an app with net: true does not — its card is honest about that.

Capability summary (the readable structured view)

For each app card and detail page, the registry auto-generates:

This app:
  ✓ Uses your microphone
  ✓ Reads files you select

This app cannot:
  ✗ Access the network
  ✗ Read other files on your Mac
  ✗ Use camera, contacts, or location
  ✗ Phone home or send telemetry
  ✗ Run code outside its sandbox

The list is derived from the manifest’s capability declarations, not author-supplied. Each line maps to a specific declaration:

Manifest field →User-facing line
device.microphone: true”Uses your microphone”
device.microphone: false”Cannot use your microphone” (under “cannot”)
device.camera: true”Uses your camera”
fs.user-selected: "read"”Reads files you select”
fs.user-selected: "read-write"”Reads and writes files you select”
fs.user-paths.documents: "read"”Reads files in your Documents folder”
net: false”Cannot access the network”
net: true”Uses the network”
net: { allowed_hosts: ["api.example.com"] }”Connects to api.example.com”
tools includes code-exec.python”Runs sandboxed Python code”
tools includes code-exec.subprocess”⚠ Runs system commands (high privilege)“
ipc.shared_folders declared”Shares data with [partner-app] (read/write)“
background.mode: active”Runs in the background while open”

The full mapping is canonical and lives in packages/manifest/labels.ts.

Data handling section

Data on your device
  📁 SQLite database (local)
  📁 Cached models (local, shared)
  📁 Logs (local)

Data leaving your device
  ✗ Nothing

For apps with net: true:

Data leaving your device
  → Sent to api.example.com:
    ─ User prompts (when calling the API)
    ─ Audio uploads (when transcribing)
  → NOT sent: any other data

This forces apps with network access to be honest about what they transmit. The registry review checks this against the actual code (via static analysis); discrepancies block submission.

Models + tools section

AI Models
  • Whisper-large-v3 (1.4 GB) — Apache 2.0
  • Qwen 2.5 3B Instruct (2.0 GB) — Apache 2.0
  • Nomic Embed Text v1.5 (270 MB) — Apache 2.0

Tools
  • OCR (locara-curated, sandboxed)
  • Filesystem search (locara-curated, sandboxed)

Click any item for details (model card, tool description, license info).

Trust attestations

Built and signed by Locara CI
  ✓ Source: github.com/kingtongchoo/transcribe-locara
  ✓ Commit: abc123def456...
  ✓ Build attestation: Sigstore log entry rekord-XYZ
  ✓ Apple notarization: ticket abc-XYZ

These are clickable; each one resolves to a verifiable artifact (public commit, Sigstore log entry, etc.).

Visual design

App card (compact)

┌──────────────────────────────────┐
│ [icon] Transcribe                │
│ by kingtongchoo • ✓ Verified     │
│                                  │
│ Fully-local audio transcription. │
│                                  │
│ 🔒 Fully Local  📦 Open Source   │
│                                  │
│ ★★★★★ 4.7 (23)                  │
│ [ Download ]                     │
└──────────────────────────────────┘

App detail page (full)

The capability summary appears prominently above the fold. The detailed sections (data handling, models, tools, attestations) are below in a clear hierarchy.

Same structure, in the app’s own UI on first launch. Per 25-onboarding.md.

Comparison: Apple App Store vs Locara

Apple’s privacy nutrition labels rely on publisher self-disclosure (“Did you tell us correctly?”) with limited verification. Locara’s are structurally different:

PropertyAppleLocara
SourcePublisher self-declaresAuto-derived from manifest
VerifiableLimited (Apple spot-checks)Yes (manifest + static analysis verify)
GranularityCoarse categoriesField-level capability declarations
DriftPossible (publisher updates code, label stays stale)Impossible (label is generated from current manifest)
FormatApple’s own templateLocara’s open-source format (others can adopt)

The label is automatic, not optional. An app cannot ship without one; the manifest is the label.

Implementation

Generation

A function in packages/manifest:

import { generatePrivacyLabel } from '@locara/manifest'

const label = generatePrivacyLabel(manifest)
// label: { topBadges, capabilities, dataHandling, models, tools, attestations }

Used by:

  • The registry website (catalog + app pages).
  • The first-run consent UI in each Locara app.
  • The optional Locara Manager utility (phase 3+).
  • Potentially: third-party tools doing privacy audits.

Schema

type PrivacyLabel = {
  topBadges: Array<{
    id: 'fully-local' | 'no-telemetry' | 'open-source' | 'verified-publisher' | 'verified-privacy'
    label: string
  }>
  capabilities: {
    can: Array<{ icon: string; label: string; manifestField: string }>
    cannot: Array<{ icon: string; label: string; manifestField: string }>
  }
  dataHandling: {
    onDevice: Array<{ kind: string; label: string }>
    leavingDevice: Array<{ destination: string; what: string[] }>
  }
  models: Array<{ id: string; sizeBytes: number; license: string }>
  tools: Array<{ id: string; locaraCurated: boolean; description: string }>
  attestations: {
    signedBy: 'locara-ci'
    sourceRepo?: string
    sourceCommit?: string
    sigstoreLogId?: string
    appleNotarizationId?: string
  }
}

This shape is JSON-serializable for the registry to publish + clients to consume.

Localization

Labels render in the user’s locale. Strings are pulled from a localization file. v1 English-only; structure supports future locales per 39-i18n.md.

Versioning

The label format is versioned (label.v1). Adding new badges or capability mappings is a minor version bump. Removing or restructuring is major + a migration period.

Apps don’t need to update; the registry auto-generates fresh labels on each version using the current label generator.

What an honest privacy label looks like

For an honest network-using app:

Mailmate (an example email client built on Locara, hypothetically)

  🌐 Uses Network  📦 Open Source  ✓ Verified Publisher

  This app:
    ✓ Connects to your IMAP/SMTP server (configured by you)
    ✓ Reads + writes mail in your local mailbox
    ✓ Uses Qwen 2.5 7B for drafting

  This app cannot:
    ✗ Connect to any other servers
    ✗ Access other files on your Mac
    ✗ Use camera, microphone

  Data leaving your device:
    → Your configured IMAP/SMTP server:
       ─ Email content (when sending/syncing)
       ─ NOT sent: any other data

This honest display would not earn the “Fully Local” badge — but it doesn’t pretend to be local either. The registry doesn’t ban network apps; it just ensures they label themselves accurately.

Anti-patterns

What we deliberately don’t do:

  • Marketing-speak labels. No “We respect your privacy.” Specific, structural claims only.
  • Voluntary disclosure. Apps don’t choose what to disclose; the manifest declares + we generate.
  • Tiered labels (e.g., “Bronze Privacy / Silver / Gold”). Either the structural claim is true or it isn’t.
  • Stale labels. Labels regenerate on every version’s publication. Old labels are clearly marked as such.

Open questions

  • (open) Should we ship a label embed widget for publishers to put on their own websites? “Verified Locara app” badge with link to the full label. Probably yes.
  • (open) Should there be a paid “Verified Privacy” badge that requires a third-party audit? Discussed in 24-monetization.md; phase 4+.
  • (open) Whether to include estimated battery impact in the label. Possibly; would need real telemetry the framework doesn’t have.
  • (open) Whether to expose the label as a JSON-LD structured data block on app pages for SEO + machine consumption. Probably yes.

Cross-references