diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..6e4e7a9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,15 @@ +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +# +# Default owner for everything in the repository. +* @ActuallyTaylor + +# Anything touching credentials, signing, licensing, or the release pipeline should always get an explicit look, even once other reviewers are added above. +/Config.xcconfig @ActuallyTaylor +/Config.local.example.xcconfig @ActuallyTaylor +/LICENSE @ActuallyTaylor +/NOTICE @ActuallyTaylor +/TRADEMARK.md @ActuallyTaylor +/SECURITY.md @ActuallyTaylor +/scripts/ @ActuallyTaylor +/.github/workflows/ @ActuallyTaylor +/Minna.xcodeproj/ @ActuallyTaylor diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..b375a54 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,86 @@ +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +name: Bug report +description: Something in Minna isn't working the way it should +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report this. + + **If this is a security or privacy vulnerability, please stop and read [SECURITY.md](https://github.com/impel-intelligence/Minna/blob/main/SECURITY.md) instead — those should be reported privately, not in a public issue.** + + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you expect, and what did you get instead? + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + placeholder: | + 1. Add a folder containing ... + 2. Open Ask Minna and ask ... + 3. Observe ... + validations: + required: true + + - type: input + id: minna-version + attributes: + label: Minna version + description: Found under Minna → About. + placeholder: "0.13.1" + validations: + required: true + + - type: input + id: macos-version + attributes: + label: macOS version + placeholder: "26.1" + validations: + required: true + + - type: dropdown + id: install-source + attributes: + label: How did you install Minna? + options: + - Direct download / Sparkle + - Mac App Store + - Built from source + validations: + required: true + + - type: dropdown + id: provider + attributes: + label: Which AI provider were you using? + description: If the bug isn't provider-related, pick "Not applicable". + options: + - Not applicable + - Anthropic (Claude) + - OpenAI + - Google Gemini + - Ollama + - Apple Foundation Models (on-device) + - MLX (on-device) + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs + description: | + Minna logs to Console.app — filter by the Minna process. Paste anything relevant here. + + **Please review before pasting.** Logs may include file names or paths from your indexed documents. Redact anything you would rather not publish. + render: text + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..f6b89e4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,9 @@ +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +blank_issues_enabled: false +contact_links: + - name: Security or privacy vulnerability + url: https://github.com/impel-intelligence/Minna/security/advisories/new + about: Report privately, not as a public issue. See SECURITY.md. + - name: Question or general support + url: mailto:support@tryminna.com + about: For help using Minna rather than a bug in it. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..e8ccbda --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,37 @@ +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +name: Feature request +description: Suggest something Minna should be able to do +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: What problem are you trying to solve? + description: | + Describe the situation you're in, not the solution you have in mind. Understanding the underlying need usually leads to a better feature than implementing the first idea. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: What would you like Minna to do? + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: What have you tried instead? + description: Workarounds you're using today, or other tools that solve this well. + validations: + required: false + + - type: checkboxes + id: contribution + attributes: + label: Would you be interested in implementing this? + description: Entirely optional — proposals are welcome without it. + options: + - label: I'd be willing to open a pull request for this + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..0c4eeba --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,21 @@ + + +## What does this change? + + + +## How was it tested? + + + +## Checklist + +- [ ] I updated `CHANGELOG.md` under `## [Unreleased]`, written for a Minna user *(skip only if this change has no user-visible effect)* +- [ ] My commits are signed off (`git commit -s`) per the DCO in [CONTRIBUTING.md](../CONTRIBUTING.md) +- [ ] The build succeeds and existing tests pass +- [ ] I did not commit credentials, an Apple Team ID, or anything from `Config.local.xcconfig` +- [ ] If I used an AI assistant, I've said so below and reviewed the output myself + +## Anything else? + + diff --git a/.github/review-guidelines.md b/.github/review-guidelines.md new file mode 100644 index 0000000..367ae06 --- /dev/null +++ b/.github/review-guidelines.md @@ -0,0 +1,83 @@ +# Code review guidelines + + + +Project-specific criteria for the automated reviewer in `.github/workflows/claude-code-review.yml`, and a useful checklist for human reviewers too. + +These are **in addition to** ordinary code review. Correctness, clarity, and test coverage still matter; this file covers the things specific to Minna that are easy to miss and expensive to discover after a release. + +Report only what a change actually warrants. A one-line bug fix should not attract a lecture about trademark policy. If nothing in a section applies, say nothing about it. + +## Licensing, NOTICE, and TRADEMARK + +Minna is Apache-2.0 and commercially distributed, so licensing drift is a real cost rather than a formality. Flag a PR when: + +- **A new third-party component is vendored into the repository** — a binary framework, a bundled model, copied source, an icon set, a font — and `NOTICE` is not updated to record it. Vendored code carries its own license, and most licenses require the notice travel with the code. +- **Code is copied from an external source** (Stack Overflow, a blog, another project) without an attribution comment naming the source and its license. Stack Overflow answers are CC BY-SA, which is not Apache-2.0. See `Minna/objc/CatchException.m` for the expected form. +- **A new local Swift package is added** without an Apache-2.0 `LICENSE` file of its own. +- **A dependency is added whose license is not Apache-2.0-compatible.** MIT, BSD, and Apache-2.0 are fine. GPL, LGPL, AGPL, and source-available licenses (BUSL, SSPL, PolyForm) are not, and need a decision before merge. +- **New brand assets are added** — a logo, an app icon, a wordmark — and `TRADEMARK.md` still lists only the old ones. That file enumerates what a fork must replace, so it has to stay current or it stops being useful. +- **The product or company name changes**, or a new name is introduced, without `TRADEMARK.md` and `NOTICE` following. +- **`LICENSE` is edited.** It is verbatim canonical Apache-2.0 and should not be modified. The same goes for `Frameworks/Sparkle.framework/LICENSE` and `CODE_OF_CONDUCT.md`, which are verbatim third-party text. +- **A copyright header is removed or reassigned.** Attribution gets added alongside, never replaced. + +## Secrets and configuration + +- No credentials, API keys, tokens, DSNs, or Apple Team IDs in tracked files. They belong in `Config.local.xcconfig`, which is gitignored. +- `Config.xcconfig` must keep every value **blank**. It is committed, and a populated value there ships credentials to everyone. Real values go only in `Config.local.xcconfig`. +- New telemetry or network calls must fail closed when unconfigured, matching `BuildConfiguration.swift`: absent configuration means the feature is off, not that it falls back to a default endpoint. +- Any new network destination must be added to the list in `SECURITY.md`. That list is a promise to users about what leaves their machine, and an undocumented endpoint makes it false. +- Watch for secrets passed as command-line arguments in scripts and workflows — they leak into process listings and logs. Use environment variables. +- GitHub Actions workflows that consume secrets must stay gated to trusted actors, and must not switch from `pull_request` to `pull_request_target`, which would expose secrets to fork code. + +## Privacy + +Minna's central claim is that documents and chats stay local. Flag anything that could weaken it: + +- Document contents, chat contents, file paths, or index data being sent anywhere. +- Telemetry that grows beyond aggregate counts, or that could carry user content in an event property or error message. +- `sendDefaultPii` being enabled, or PII scrubbing being weakened. +- Logging that writes document contents or full paths, since users are asked to paste logs into bug reports. + +## Documentation currency + +Flag when: + +- A user-visible feature changes and `README.md` still describes the old behavior. +- An AI provider is added or removed and the provider lists in `README.md`, `SECURITY.md`, and `docs/ARCHITECTURE.md` are not updated. +- A package is added, removed, or substantially restructured and `docs/ARCHITECTURE.md` still describes the old layout, including its "where to look" table. +- The build or setup process changes and `CONTRIBUTING.md` still gives the old steps. +- The minimum macOS or Xcode version changes and the requirements in `README.md` and `CONTRIBUTING.md` do not follow. + +## Changelog + +- Every user-facing change needs an entry under `## [Unreleased]` in `CHANGELOG.md`, in Keep a Changelog format. +- Entries should be written for a Minna user, not a developer reading the diff. "Fixed a crash when opening a malformed database" is right; "Fixed nil unwrap in IrisDBController" is not. +- Internal refactors with no user-visible effect don't need one — don't insist. + +## Agent attribution + +Per `AGENTS.md`, AI-authored work identifies itself. Flag when: + +- A file created or meaningfully edited by an agent has no attribution comment in its header. +- A doc comment written by an agent lacks its attribution line. +- A commit authored by an agent lacks a `Co-Authored-By` trailer naming the specific model. +- An agent added a `Signed-off-by` line for itself. DCO sign-off belongs to the human submitting the work. +- `CLAUDE.md` was replaced with a regular file instead of remaining a symlink to `AGENTS.md`. + +## Formatting + +- Prose must not be hard wrapped — paragraphs, comments, doc comments, and commit bodies are single continuous lines. The exception is verbatim external text, where the original wrapping is preserved. +- Match the surrounding code's style. SwiftLint and SwiftFormat cover the rest. +- Use `SFSafeSymbols` (`systemSymbol:`) rather than `Image(systemName:)`. + +## Build and release integrity + +- Changes to `Minna.xcodeproj/project.pbxproj` that reintroduce a hardcoded `DEVELOPMENT_TEAM`, or that drop the `baseConfigurationReference` to `Config.xcconfig`, silently defeat the credential externalization. Inline `buildSettings` override an xcconfig. +- The `SPARKLE` compilation condition must keep Sparkle out of App Store builds. +- Changes to `scripts/release.sh` deserve close attention: it signs, notarizes, and uploads. +- New Swift files land automatically via file-system synchronized groups. A manual `PBXFileReference` addition for a source file usually indicates a mistake. + +## Extending this file + +Add a section when a class of mistake becomes worth catching automatically. Keep each item concrete enough to check against a diff — "flag when X changes but Y doesn't" is actionable; "ensure good architecture" is not. Sections are independent, so new feature areas can be appended without disturbing what's here. diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index b5e8cfd..09821a1 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -12,11 +12,10 @@ on: jobs: claude-review: - # Optional: Filter by PR author - # if: | - # github.event.pull_request.user.login == 'external-contributor' || - # github.event.pull_request.user.login == 'new-developer' || - # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + # Restricted to an explicit allowlist of logins, currently just @ActuallyTaylor, since this job spends CLAUDE_CODE_OAUTH_TOKEN. This is a hardcoded login check rather than a permission or role check, so it does not widen automatically when a collaborator is added — extend the condition below to grant access. + # + # NOTE: this workflow uses `pull_request` rather than `pull_request_target`, which is the safe choice — a pull request from a fork runs without access to repository secrets. The consequence is that this job cannot review fork pull requests at all, and will simply not run on them. That is expected behaviour, not a misconfiguration. Switching to `pull_request_target` to "fix" it would expose secrets to untrusted code from forks. + if: github.actor == 'ActuallyTaylor' runs-on: ubuntu-latest permissions: @@ -38,7 +37,13 @@ jobs: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' - prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' + # The slash command runs the standard review. The paragraph after it adds Minna's own criteria, which live in .github/review-guidelines.md so they are version controlled and reviewable rather than buried in this workflow. Extend that file, not this prompt. + prompt: | + /code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} + + Additionally, read `.github/review-guidelines.md` and review this pull request against the project-specific criteria it defines. They cover licensing and the currency of NOTICE and TRADEMARK.md, secrets and build configuration, Minna's privacy guarantees, documentation drift, CHANGELOG entries, agent attribution, and release integrity. + + Apply those criteria only where the diff actually warrants it — a small fix should not attract commentary on sections it does not touch. Where a guideline is violated, name the specific file that needs updating and why. # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://code.claude.com/docs/en/cli-reference for available options diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 6b15fac..a447a07 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -12,11 +12,14 @@ on: jobs: claude: + # Restricted to an explicit allowlist of logins, currently just @ActuallyTaylor. This is a hardcoded login check rather than a permission or role check, so it does not widen automatically when a collaborator is added — extend the condition below to grant access. This job spends CLAUDE_CODE_OAUTH_TOKEN, so on a public repository an unrestricted trigger would let any GitHub user run it by leaving a comment. if: | - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + github.actor == 'ActuallyTaylor' && ( + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + ) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/sparkle.yml b/.github/workflows/sparkle.yml deleted file mode 100644 index 8105bd6..0000000 --- a/.github/workflows/sparkle.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Update Sparkle w/ Latest Release -on: - release: - types: [released] - workflow_dispatch: - -permissions: - contents: write - -jobs: - upload: - name: Upload Release Files - runs-on: macos-26 - - steps: - - uses: actions/checkout@v7 - - - name: Install xcbeautify - run: brew install xcbeautify - - - name: Configure Git for Private Packages - run: | - git config --global url."https://x-access-token:${{ secrets.ACTIONS_PAT }}@github.com/".insteadOf "https://github.com/" - - # Download the last builds - - name: release-downloader - uses: robinraju/release-downloader@v1.13 - with: - tag: '${{ github.ref_name }}' - fileName: minna.* - out-file-path: 'tmp' - token: ${{ secrets.ACTIONS_PAT }} - - - name: Restore Sparkle Updater Cache - id: cache-sparkle - uses: actions/cache@v6 - with: - path: iris-sparkle-updater - key: updater-cache - - # Depth 1 for a shallow clone - - name: Checkout Minna Sparkle Updater - if: steps.cache-sparkle.outputs.cache-hit != 'true' - run: git clone --depth 1 https://github.com/impel-intelligence/minna-sparkle-updater/ - - - name: Update Sparkle - run: ./scripts/update_sparkle.sh ${{ secrets.SPARKLE_SIGNING_KEY }} ${{ github.ref_name }} "${{ github.event.release.body }}" diff --git a/.gitignore b/.gitignore index 1e81262..055c6a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,39 @@ +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 + .DS_Store -# Ignore generated Xcode projects and workspaces +# Local build configuration — credentials and team ID live here. See Config.local.example.xcconfig for the template. +Config.local.xcconfig + +# Xcode user-specific state *.xcuserstate *.xcuserdatad +**/xcuserdata/ +DerivedData/ +*.moved-aside +*.hmap +*.ipa +*.dSYM.zip -# Ignore Tuist build artifacts and cached files -/.build/ +# Swift Package Manager +.build/ +.swiftpm/ +Packages/*/.build/ +Tools/*/.build/ + +# Build output /Derived/ -/.claude -.build /build +out/ +tmp/ /tmp -docs/superpowers/ + +# Release artifacts /scripts/minna.tar.xz /scripts/minna.dmg -/Minna.xcodeproj/xcuserdata/taylorlineman.xcuserdatad/xcschemes/xcschememanagement.plist -out/ -tmp/ +/scripts/tmp/ + +# Agent tooling +/.claude +/.conductor +docs/superpowers/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..18030d7 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,82 @@ +# Agent instructions + +These instructions apply to **every AI coding agent** working in this repository — OpenAI Codex, Claude Code, Cursor, GitHub Copilot, Gemini, Jules, or anything else. Wherever the rules below say "you", they mean whichever agent is reading them. + +`AGENTS.md` is the canonical file. `CLAUDE.md` is a symlink to it, because Claude Code looks for that filename — so there is exactly one copy of these instructions and it cannot drift. Edit `AGENTS.md`; never replace the symlink with a real file. + +## Attribution + +Minna is open source, and a reader of this codebase should be able to tell which parts were written by an AI agent, which agent, and when. That is the entire purpose of this section. When you edit or create a file, attribute the work to yourself. + +**Identify yourself specifically.** Use your actual model or agent name and its vendor, not a generic label. `Codex (OpenAI)` is acceptable; `AI assistant` is not. If you know your version, include it. + +Examples of well-formed identities: + +- `GPT-5 Codex (OpenAI)` +- `Claude Opus 4.8 (Anthropic)` +- `Gemini 2.5 Pro (Google)` +- `Cursor Composer (Anthropic Claude Sonnet 4.6)` — name the harness and the underlying model when they differ and you know both + +### File-level attribution + +At the top of any file you create, or in the file's existing header or changelog when you make a meaningful edit, note that you authored or modified it. Use the comment syntax native to the file's language, and the current date: + +``` +// Edited by GPT-5 Codex (OpenAI) on 2026-06-26 +``` + +```python +# Edited by Claude Opus 4.8 (Anthropic) on 2026-06-26 +``` + +Don't add attribution to generated files, lockfiles, or non-source assets. + +### Doc comments + +When you write a documentation comment for a function, type, or method, include an attribution line within the doc comment. Adapt the line to the documentation convention of the language you're writing in. + +```swift +/// Fetches the user's profile from the remote API. +/// +/// - Parameter id: The user's unique identifier. +/// - Returns: The decoded `Profile`. +/// - Authored by: GPT-5 Codex (OpenAI) +func fetchProfile(id: String) async throws -> Profile { ... } +``` + +### Commit attribution + +Every commit you author must carry a co-author trailer naming you specifically, as the last line of the commit message: + +``` +Co-Authored-By: GPT-5 Codex (OpenAI) +``` + +``` +Co-Authored-By: Claude Opus 4.8 (Anthropic) +``` + +Use a `noreply` address for your vendor. If you don't know one, `agent@noreply.invalid` is fine — the name matters more than the address. This makes AI-authored work visible in `git log`, `git shortlog`, and the GitHub contributors view: the same tracking the file-level and doc-comment rules provide, extended to history. + +Note that contributions to this repository also require a DCO sign-off (`git commit -s`). The sign-off belongs to the **human** directing the work, who takes responsibility for the contribution; your co-author trailer is separate and additional. Never add a `Signed-off-by` line for yourself. + +### Guidelines + +- Keep attribution concise — a single line is enough. +- Don't overwrite or remove attribution from another author, human or agent; add yours alongside. +- Only attribute files you actually changed in the current task. +- If a file already carries your attribution from a previous session, update the date rather than adding a second line. + +## Formatting + +**Never hard wrap text.** Write each paragraph, comment, or documentation line as a single continuous line and let the editor soft wrap it. This applies to everything you write: Markdown, code comments, doc comments, commit message bodies, YAML descriptions, and configuration file comments. Hard wrapping makes diffs noisy, because editing one word reflows and touches every following line in the paragraph. + +The one exception is text you are copying verbatim, where the wrapping is part of the original: license texts, third-party notices, and anything quoted from an external source. Reproduce those exactly as they are, wrapping included. + +## Project conventions + +See [CONTRIBUTING.md](CONTRIBUTING.md) for build setup, code style, and pull request expectations. They apply to you as much as to human contributors. In particular: + +- Every user-facing change needs a `CHANGELOG.md` entry under `## [Unreleased]`, written for a Minna user rather than a developer reading the diff. +- Never commit credentials, an Apple Team ID, or anything belonging in `Config.local.xcconfig`. That file is gitignored; keep it that way. +- Use `SFSafeSymbols` (`systemSymbol:`) rather than stringly-typed `Image(systemName:)`. diff --git a/CHANGELOG.md b/CHANGELOG.md index eaabd20..220e07e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ The format has been adjusted to include a release Title. This has been inserted ## [Unreleased] +### Added +- Minna is now licensed under the Apache License 2.0. + +### Changed +- Crash reporting and analytics are now configured at build time and are turned off entirely in builds made from source, so a build you compile yourself reports nothing anywhere. + ## [0.13.1] - Database Hardening - 2026-08-13 ### Fixed diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 5acbced..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,27 +0,0 @@ -# CLAUDE.md - -## Attribution - -When you edit or create a file, attribute the work to yourself. - -- **File-level attribution:** At the top of any file you create, or in the file's existing header/changelog when you make a meaningful edit, note that Claude authored or modified it. Use the form the file's language supports for comments. Example: - ``` - // Edited by Claude Opus 4.8 (Anthropic) on 2026-06-26 - ``` - Replace the model name with whichever Claude model you actually are (e.g. `Claude Opus 4.8`, `Claude Sonnet 4.6`, `Claude Haiku 4.5`). Use the current date and the language's native comment syntax. Don't add attribution to generated files, lockfiles, or non-source assets. - -- **Doc comments:** When you write a documentation comment for a function, type, or method, include a Claude attribution line within the doc comment. Example (Swift): - ```swift - /// Fetches the user's profile from the remote API. - /// - /// - Parameter id: The user's unique identifier. - /// - Returns: The decoded `Profile`. - /// - Authored by: Claude Opus 4.8 (Anthropic) - func fetchProfile(id: String) async throws -> Profile { ... } - ``` - Include your specific model name (e.g. `Claude Opus 4.8`) and adapt the `Authored by:` line to the documentation convention of the language you're writing in. - -### Guidelines -- Keep attribution concise — a single line is enough. -- Don't overwrite or remove attribution from other authors; add yours alongside. -- Only attribute files you actually changed in the current task. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ea30524 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,84 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at . All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d1888b1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,111 @@ +# Contributing to Minna + + + +Thanks for your interest in Minna. This document covers how to build the project, what we expect in a pull request, and how contributions are licensed. + +Minna is a commercial product published as open source so that anyone can audit how it handles your data. Contributions are welcome, and so is scrutiny — if you find something in the privacy or security behavior that looks wrong, that is a particularly valuable thing to report. + +## Getting set up + +### Requirements + +- macOS 26 or later +- Xcode 26 or later +- A GitHub account with `git` and Git LFS installed + +### Build + +```sh +git clone --recursive https://github.com/impel-intelligence/Minna.git +cd Minna +open Minna.xcodeproj +``` + +If you already cloned without `--recursive`: + +```sh +git submodule update --init --recursive +``` + +Then build and run the `Minna` scheme. **No configuration is required.** Minna builds and runs out of the box. + +### Optional: local configuration + +`Config.xcconfig` holds build settings and ships with every value blank. Blank values are the normal, supported state for a build from source: + +- **Telemetry is off.** Crash reporting and product analytics are only initialized when credentials are present, so your development builds report nothing, anywhere. +- **Signing is local.** Xcode signs to run on your own machine. + +If you need to set a signing team or your own telemetry endpoints: + +```sh +cp Config.local.example.xcconfig Config.local.xcconfig +``` + +Fill in what you need. `Config.local.xcconfig` is gitignored and is picked up automatically. Note that xcconfig treats `//` as a comment, so URL values are stored without their scheme — the file explains this where it matters. + +### Tests + +```sh +swift test --package-path Packages/IrisSearch +swift test --package-path Packages/MinnaChat +``` + +Some tests in `IrisSearch` and `LookAtMe` depend on a document corpus that is not distributed with the repository, for size and licensing reasons. Those tests skip automatically when the corpus is absent. See the `Tests/Test Documents/` README in each package if you want to supply your own fixtures. + +## Code style + +The project uses SwiftLint and SwiftFormat, configured in `.swiftlint.yml` and `.swiftformat`. Match the surrounding code; the linters cover the rest. + +A few conventions worth knowing: + +- Use `SFSafeSymbols` (`systemSymbol:`) rather than stringly-typed `Image(systemName:)`. There is a custom lint rule enforcing this. +- Swift 6 language mode is on. Concurrency warnings are errors in practice — please don't silence them with `@unchecked Sendable` without a comment explaining why it is actually safe. +- Don't hard wrap prose. Write comments and documentation as continuous lines and let your editor soft wrap them, so that editing a sentence doesn't reflow and touch every line after it in the diff. + +## Pull requests + +1. **Open an issue first for anything substantial.** Small fixes can go straight to a PR, but for a feature or refactor it saves everyone time to agree on the approach before you write it. +2. **Keep PRs focused.** One logical change per pull request. +3. **Update `CHANGELOG.md`.** Every user-facing change needs an entry under the `## [Unreleased]` heading, in the existing [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format — `### Added`, `### Fixed`, `### Changed`, and so on. Write it for a Minna user, not for a developer reading the diff. Internal refactors with no user-visible effect don't need an entry. +4. **Sign off your commits** (see below). +5. **Describe what you changed and why.** The PR template will prompt you. + +### Developer Certificate of Origin + +Minna uses the [Developer Certificate of Origin](https://developercertificate.org) (DCO). There is no CLA to sign. You simply certify that you wrote the contribution, or otherwise have the right to submit it under the project's license, by adding a `Signed-off-by` line to your commits: + +```sh +git commit -s -m "Your commit message" +``` + +That appends: + +``` +Signed-off-by: Your Name +``` + +Use your real name and an email you can be reached at. If you forget, amend with `git commit -s --amend` and force-push to your branch. + +### Licensing of contributions + +Minna is licensed under the [Apache License, Version 2.0](LICENSE). By contributing, you agree that your contribution is licensed under the same terms. Apache-2.0 includes an express patent grant, which protects both you and other users of the project. + +Note that the Apache license covers the code only. The Minna name and marks are not licensed with it — see [TRADEMARK.md](TRADEMARK.md). + +### AI-assisted contributions + +These are fine, and Minna's own history includes them. If you use an AI coding agent, please say so in the pull request, and note that you remain responsible for the correctness and licensing of what you submit — review it as you would your own code. + +This repository asks agents to identify themselves in the work they produce: a comment in files they create or meaningfully edit, an attribution line in doc comments they write, and a `Co-Authored-By` trailer on commits they author. The instructions are in [AGENTS.md](AGENTS.md), symlinked as `CLAUDE.md` for tools that look for that filename. They apply to any agent — Codex, Claude, Cursor, Copilot, Gemini, or otherwise. + +The DCO sign-off is separate and always belongs to **you**, the human submitting the work. An agent's co-author trailer does not substitute for it. + +## Reporting security issues + +**Please do not open a public issue for a security vulnerability.** See [SECURITY.md](SECURITY.md) for how to report privately. + +## Questions + +Open a [discussion or issue](https://github.com/impel-intelligence/Minna/issues), or email . diff --git a/Config.local.example.xcconfig b/Config.local.example.xcconfig new file mode 100644 index 0000000..2e8188f --- /dev/null +++ b/Config.local.example.xcconfig @@ -0,0 +1,28 @@ +// Config.local.example.xcconfig +// Minna +// +// Template for local, uncommitted build configuration. +// +// cp Config.local.example.xcconfig Config.local.xcconfig +// +// Config.local.xcconfig is gitignored. Anything you set there overrides the blank defaults in Config.xcconfig. +// +// You do NOT need this file to build Minna. Without it the app compiles, runs, and reports no telemetry — which is the correct setup for contributors. +// +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 + +// Your Apple Developer Team ID, e.g. ABCDE12345. +DEVELOPMENT_TEAM = + +// Telemetry — leave blank unless you are building an official release. +// +// REMINDER: xcconfig treats "//" as a comment. Store these WITHOUT the "https://" scheme; Minna re-adds it at runtime. + +// e.g. abc123def456@o1234567.ingest.us.sentry.io/7654321 +SENTRY_DSN = + +// e.g. phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +POSTHOG_PROJECT_TOKEN = + +// e.g. us.i.posthog.com +POSTHOG_HOST = diff --git a/Config.xcconfig b/Config.xcconfig new file mode 100644 index 0000000..488786f --- /dev/null +++ b/Config.xcconfig @@ -0,0 +1,41 @@ +// Config.xcconfig +// Minna +// +// Build configuration for local development, signing, and optional telemetry. +// +// Every value here is EMPTY by default and Minna builds and runs correctly with all of them blank. Telemetry simply stays off, and the app is signed to run locally. You do not need to configure anything to build from source. +// +// To set your own values, copy this file's local override: +// +// cp Config.local.example.xcconfig Config.local.xcconfig +// +// and fill it in. Config.local.xcconfig is gitignored, so your credentials and team ID never enter version control. The optional #include? at the bottom of this file picks it up automatically if it exists, and is silently skipped if it does not. +// +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 + +// MARK: - Code Signing +// +// Your Apple Developer Team ID. Leave blank to build with automatic local signing, which is enough to compile and run Minna on your own machine. +DEVELOPMENT_TEAM = + +// MARK: - Telemetry +// +// Minna ships with crash reporting (Sentry) and privacy-focused product analytics (PostHog). Both are DISABLED when these values are blank, which is the default for all contributor builds — a source build reports nothing, anywhere, unless you deliberately opt in below. +// +// NOTE: xcconfig treats "//" as the start of a comment, so URLs here are stored WITHOUT their "https://" scheme. Minna re-adds the scheme at runtime. Do not paste a full URL into these values. + +// Sentry DSN with the leading "https://" removed. +// Full DSN: https://@.ingest.us.sentry.io/ +// Store as: @.ingest.us.sentry.io/ +SENTRY_DSN = + +// PostHog project token (starts with "phc_"). +POSTHOG_PROJECT_TOKEN = + +// PostHog host with the leading "https://" removed, e.g. us.i.posthog.com +POSTHOG_HOST = + +// MARK: - Local overrides +// +// Optional include — no error if the file is absent. +#include? "Config.local.xcconfig" diff --git a/Frameworks/Sparkle.framework/LICENSE b/Frameworks/Sparkle.framework/LICENSE new file mode 100644 index 0000000..abe6e04 --- /dev/null +++ b/Frameworks/Sparkle.framework/LICENSE @@ -0,0 +1,134 @@ +Copyright (c) 2006-2013 Andy Matuschak. +Copyright (c) 2009-2013 Elgato Systems GmbH. +Copyright (c) 2011-2014 Kornel Lesiński. +Copyright (c) 2015-2017 Mayur Pawashe. +Copyright (c) 2014 C.W. Betts. +Copyright (c) 2014 Petroules Corporation. +Copyright (c) 2014 Big Nerd Ranch. +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================= +EXTERNAL LICENSES +================= + +bspatch.c and bsdiff.c, from bsdiff 4.3 : + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +-- + +sais.c and sais.h, from sais-lite (2010/08/07) : + +The sais-lite copyright is as follows: + +Copyright (c) 2008-2010 Yuta Mori All Rights Reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +-- + +Portable C implementation of Ed25519, from https://github.com/orlp/ed25519 + +Copyright (c) 2015 Orson Peters + +This software is provided 'as-is', without any express or implied warranty. In no event will the +authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the + original software. If you use this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as + being the original software. + +3. This notice may not be removed or altered from any source distribution. + +-- + +SUSignatureVerifier.m: + +Copyright (c) 2011 Mark Hamlin. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Minna.xcodeproj/project.pbxproj b/Minna.xcodeproj/project.pbxproj index cea14f3..24619f6 100644 --- a/Minna.xcodeproj/project.pbxproj +++ b/Minna.xcodeproj/project.pbxproj @@ -82,6 +82,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + DBC0F1A02FF0000100000001 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; + DBC0F1A02FF0000100000002 /* Config.local.example.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.local.example.xcconfig; sourceTree = ""; }; DB0CF4D02FEDCA6B0036306B /* Minna.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Minna.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB0CF4DF2FEDCA6D0036306B /* MinnaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MinnaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DB0CF4E92FEDCA6D0036306B /* MinnaUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MinnaUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -215,6 +217,8 @@ DB0CF4C72FEDCA6B0036306B = { isa = PBXGroup; children = ( + DBC0F1A02FF0000100000001 /* Config.xcconfig */, + DBC0F1A02FF0000100000002 /* Config.local.example.xcconfig */, DB0CF7242FEDE88A0036306B /* ci_scripts */, DB0CF4D22FEDCA6B0036306B /* Minna */, DB0CF4E22FEDCA6D0036306B /* MinnaTests */, @@ -558,6 +562,7 @@ /* Begin XCBuildConfiguration section */ DB0CF4F12FEDCA6D0036306B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DBC0F1A02FF0000100000001 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -591,7 +596,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -622,6 +626,7 @@ }; DB0CF4F22FEDCA6D0036306B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DBC0F1A02FF0000100000001 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -655,7 +660,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -687,7 +691,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -713,7 +716,7 @@ INFOPLIST_KEY_CFBundleDisplayName = Minna; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -751,7 +754,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -777,7 +779,7 @@ INFOPLIST_KEY_CFBundleDisplayName = Minna; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -809,7 +811,6 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -830,7 +831,6 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -850,7 +850,6 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -870,7 +869,6 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -887,6 +885,7 @@ }; DB3F89D130005AB7003FE515 /* Debug Sparkle */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DBC0F1A02FF0000100000001 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -920,7 +919,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -960,7 +958,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -986,7 +983,7 @@ INFOPLIST_KEY_CFBundleDisplayName = Minna; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1024,7 +1021,6 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -1044,7 +1040,6 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -1061,6 +1056,7 @@ }; DB3F89D530005ABC003FE515 /* Release Sparkle */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DBC0F1A02FF0000100000001 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -1094,7 +1090,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -1126,7 +1121,6 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -1152,7 +1146,7 @@ INFOPLIST_KEY_CFBundleDisplayName = Minna; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1189,7 +1183,6 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -1209,7 +1202,6 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; @@ -1230,7 +1222,6 @@ CODE_SIGN_ENTITLEMENTS = SearchModelAssets/SearchModelAssets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -1246,7 +1237,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SearchModelAssets/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = SearchModelAssets; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1272,7 +1263,6 @@ CODE_SIGN_ENTITLEMENTS = SearchModelAssets/SearchModelAssets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -1288,7 +1278,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SearchModelAssets/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = SearchModelAssets; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1314,7 +1304,6 @@ CODE_SIGN_ENTITLEMENTS = SearchModelAssets/SearchModelAssets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -1330,7 +1319,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SearchModelAssets/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = SearchModelAssets; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1356,7 +1345,6 @@ CODE_SIGN_ENTITLEMENTS = SearchModelAssets/SearchModelAssets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 0.13.1; - DEVELOPMENT_TEAM = VV548YNZL3; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; @@ -1372,7 +1360,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SearchModelAssets/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = SearchModelAssets; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Impel Intelligence, Inc. Licensed under the Apache License, Version 2.0."; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", diff --git a/Minna/Database/Previews/SampleDatabase.swift b/Minna/Database/Previews/SampleDatabase.swift index 5373e5b..beb91e6 100644 --- a/Minna/Database/Previews/SampleDatabase.swift +++ b/Minna/Database/Previews/SampleDatabase.swift @@ -3,6 +3,7 @@ // Minna // // Created by Taylor Lineman on 6/12/26. +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 // import SwiftData @@ -46,7 +47,7 @@ class SampleDatabase: Database { title: "Syllabus Discussion", shortDescription: "A discussion about course requirements and syllabus details.", color: .random, - url: URL(fileURLWithPath: "/Users/taylorlineman/Developer/impel/minna-router/Papers/Open Research Knowledge Graph.pdf") , + url: URL(string: "https://example.com/papers/open-research-knowledge-graph.pdf")!, source: "pdf", type: .pdf ), diff --git a/Minna/Info.plist b/Minna/Info.plist index 0f2dce4..22c6f20 100644 --- a/Minna/Info.plist +++ b/Minna/Info.plist @@ -36,6 +36,12 @@ + POSTHOG_HOST + $(POSTHOG_HOST) + POSTHOG_PROJECT_TOKEN + $(POSTHOG_PROJECT_TOKEN) + SENTRY_DSN + $(SENTRY_DSN) SUEnableInstallerLauncherService SUFeedURL diff --git a/Minna/IrisApp.swift b/Minna/IrisApp.swift index 9063675..50bd82f 100644 --- a/Minna/IrisApp.swift +++ b/Minna/IrisApp.swift @@ -3,6 +3,7 @@ // Minna // // Created by Taylor Lineman on 6/11/26. +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 // import SwiftUI @@ -45,40 +46,44 @@ struct MinnaApp: App { init() { let sentryBox = SentryBox() - SentrySDK.start { options in - options.dsn = "https://b74c5dc356db0cda226438d09eb33a87@o4511615856607232.ingest.us.sentry.io/4511615959105537" - options.sendDefaultPii = false - options.enableUncaughtNSExceptionReporting = true - - #if SPARKLE - options.dist = "sparkle" - #if DEBUG - options.environment = "sparkle_debug" - #else - options.environment = "sparkle_release" - #endif // DEBUG - #else - options.dist = "app_store" - #if DEBUG - options.environment = "app_store_debug" - #else - options.environment = "app_store_release" - #endif // DEBUG - #endif // SPARKLE - - options.onLastRunStatusDetermined = { status, crashEvent in - if status == .didCrash, let event = crashEvent { - Log.logger.error("App crashed last run", metadata: ["sentry_id": "\(event.eventId.sentryIdString)"]) - sentryBox.sentryCrashID = event.eventId + // Crash reporting is opt-in via Config.xcconfig. Builds from a clean checkout have no DSN configured and report nothing. + if let sentryDSN = BuildConfiguration.sentryDSN { + SentrySDK.start { options in + options.dsn = sentryDSN + options.sendDefaultPii = false + options.enableUncaughtNSExceptionReporting = true + + #if SPARKLE + options.dist = "sparkle" + #if DEBUG + options.environment = "sparkle_debug" + #else + options.environment = "sparkle_release" + #endif // DEBUG + #else + options.dist = "app_store" + #if DEBUG + options.environment = "app_store_debug" + #else + options.environment = "app_store_release" + #endif // DEBUG + #endif // SPARKLE + + options.onLastRunStatusDetermined = { status, crashEvent in + if status == .didCrash, let event = crashEvent { + Log.logger.error("App crashed last run", metadata: ["sentry_id": "\(event.eventId.sentryIdString)"]) + sentryBox.sentryCrashID = event.eventId + } } } } - - let POSTHOG_PROJECT_TOKEN = "phc_nZHzNbtLBtLumJz9Yi6MvnzK2GDcMpt3MLCv6vDJxcSb" - let POSTHOG_HOST = "https://us.i.posthog.com" - let config = PostHogConfig(projectToken: POSTHOG_PROJECT_TOKEN, host: POSTHOG_HOST) - PostHogSDK.shared.setup(config) + // Product analytics are opt-in via Config.xcconfig on the same terms. + if let projectToken = BuildConfiguration.postHogProjectToken, + let host = BuildConfiguration.postHogHost { + let config = PostHogConfig(projectToken: projectToken, host: host) + PostHogSDK.shared.setup(config) + } #if SPARKLE // Don't start the sparkle updater under XCTest. Unit tests on CI will fail since sparkle opens a popup asking when to update which hangs the process. diff --git a/Minna/Sparkle.swift b/Minna/Sparkle.swift index 11a7fb6..0789fb8 100644 --- a/Minna/Sparkle.swift +++ b/Minna/Sparkle.swift @@ -3,6 +3,9 @@ // Minna // // Created by Taylor Lineman on 6/24/26. +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +// +// Attribution: the CheckForUpdatesViewModel / CheckForUpdatesView pair is adapted from the Sparkle project's SwiftUI sample code, licensed MIT. See Frameworks/Sparkle.framework/LICENSE for the full notice. // #if SPARKLE diff --git a/Minna/Utility/BuildConfiguration.swift b/Minna/Utility/BuildConfiguration.swift new file mode 100644 index 0000000..dd1573f --- /dev/null +++ b/Minna/Utility/BuildConfiguration.swift @@ -0,0 +1,61 @@ +// +// BuildConfiguration.swift +// Minna +// +// Created by Claude Opus 5 (Anthropic) on 8/13/26. +// + +import Foundation + +/// Build-time configuration supplied by `Config.xcconfig`. +/// +/// Values are injected into the app's `Info.plist` at build time and read back here. Every value is optional, and a missing or blank value — the default for any build made from a clean checkout — leaves the corresponding feature switched off. A build from source therefore reports no telemetry anywhere unless a developer deliberately opts in via `Config.local.xcconfig`. +/// +/// - Note: `xcconfig` files treat `//` as the start of a comment, so URL-shaped values are stored without their scheme and reassembled here. +/// - Authored by: Claude Opus 5 (Anthropic) +enum BuildConfiguration { + /// The Sentry DSN, or `nil` when crash reporting should stay disabled. + /// - Authored by: Claude Opus 5 (Anthropic) + static var sentryDSN: String? { + value(for: "SENTRY_DSN").map { "https://\($0)" } + } + + /// The PostHog project token, or `nil` when analytics should stay disabled. + /// - Authored by: Claude Opus 5 (Anthropic) + static var postHogProjectToken: String? { + value(for: "POSTHOG_PROJECT_TOKEN") + } + + /// The PostHog host, or `nil` when analytics should stay disabled. + /// - Authored by: Claude Opus 5 (Anthropic) + static var postHogHost: String? { + value(for: "POSTHOG_HOST").map { "https://\($0)" } + } + + /// Whether product analytics are configured for this build. + /// - Authored by: Claude Opus 5 (Anthropic) + static var isAnalyticsEnabled: Bool { + postHogProjectToken != nil && postHogHost != nil + } + + /// Reads a string from `Info.plist`, treating unconfigured values as absent. + /// + /// An xcconfig variable that was never assigned survives `Info.plist` substitution as either an empty string or the literal `$(NAME)` placeholder, so both forms are reported as "not configured". + /// + /// - Parameter key: The `Info.plist` key to read. + /// - Returns: The trimmed value, or `nil` when it is unset. + /// - Authored by: Claude Opus 5 (Anthropic) + private static func value(for key: String) -> String? { + guard let raw = Bundle.main.object(forInfoDictionaryKey: key) as? String else { + return nil + } + + let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) + + guard !trimmed.isEmpty, !trimmed.hasPrefix("$(") else { + return nil + } + + return trimmed + } +} diff --git a/Minna/objc/CatchException.h b/Minna/objc/CatchException.h index 99e875b..5259588 100644 --- a/Minna/objc/CatchException.h +++ b/Minna/objc/CatchException.h @@ -3,11 +3,13 @@ // Amoeba // // Created by Taylor Lineman on 1/16/25. -// https://stackoverflow.com/a/36454808 +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 +// +// Attribution: adapted from https://stackoverflow.com/a/36454808 +// Stack Overflow contributions from that period are licensed CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/), which is why this file carries its own attribution rather than the project's Apache-2.0 header. #import -// https://stackoverflow.com/a/36454808 @interface CatchException : NSObject + (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error; diff --git a/Minna/objc/CatchException.m b/Minna/objc/CatchException.m index 528dbd4..8ba79ae 100644 --- a/Minna/objc/CatchException.m +++ b/Minna/objc/CatchException.m @@ -3,9 +3,11 @@ // Minna // // Created by Taylor Lineman on 7/8/26. +// Edited by Claude Opus 5 (Anthropic) on 2026-08-13 // +// Attribution: adapted from https://stackoverflow.com/a/36454808 +// Stack Overflow contributions from that period are licensed CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/), which is why this file carries its own attribution rather than the project's Apache-2.0 header. -// https://stackoverflow.com/a/36454808 #import "CatchException.h" @implementation CatchException diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..5eb5367 --- /dev/null +++ b/NOTICE @@ -0,0 +1,51 @@ +Minna +Copyright 2026 Impel Intelligence, Inc. + +This product includes software developed by Impel Intelligence, Inc. +Licensed under the Apache License, Version 2.0. See LICENSE for the full text. + + +================================================================================ +THIRD-PARTY COMPONENTS REDISTRIBUTED IN THIS REPOSITORY +================================================================================ + +The following components are included in this source tree and are covered by their own licenses rather than the Apache License above. + +-------------------------------------------------------------------------------- +Sparkle +-------------------------------------------------------------------------------- +Location: Frameworks/Sparkle.framework/ +Version: 2.9.5 +License: MIT, with additional external licenses for bundled components (bsdiff/bspatch, sais-lite, and others) +Full text: Frameworks/Sparkle.framework/LICENSE +Homepage: https://sparkle-project.org + +Sparkle is redistributed here as a prebuilt binary framework and is used only in the direct-download ("Sparkle") build configuration. It is excluded from Mac App Store builds. + +The CheckForUpdatesViewModel and CheckForUpdatesView types in Minna/Sparkle.swift are adapted from Sparkle's SwiftUI sample code and are likewise MIT licensed. + +-------------------------------------------------------------------------------- +CatchException +-------------------------------------------------------------------------------- +Location: Minna/objc/CatchException.h, Minna/objc/CatchException.m +License: CC BY-SA 3.0 +Full text: https://creativecommons.org/licenses/by-sa/3.0/ +Source: https://stackoverflow.com/a/36454808 + +Adapted from a Stack Overflow answer. Contributions to Stack Overflow from that period are licensed CC BY-SA 3.0, so these two files carry their own attribution and are not covered by the Apache License above. + +-------------------------------------------------------------------------------- +Custom symbol images +-------------------------------------------------------------------------------- +Location: Minna/Resources/Assets.xcassets/*.symbolset/ +License: Apple SF Symbols license agreement +Homepage: https://developer.apple.com/sf-symbols/ + +Several custom symbol templates in this repository were exported from Apple's SF Symbols tooling. Use of SF Symbols and symbols derived from them is governed by Apple's SF Symbols license agreement, which permits use within applications but restricts redistribution and modification. Downstream users should review that agreement before reusing these assets outside an Apple platform app. + + +================================================================================ +DEPENDENCIES +================================================================================ + +Minna depends on a number of Swift packages that are fetched at build time rather than vendored into this repository. Each carries its own license; see Package.resolved and the respective project for details. diff --git a/Packages/DatabaseSchema/LICENSE b/Packages/DatabaseSchema/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/Packages/DatabaseSchema/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Packages/DatabaseSchema/Package.swift b/Packages/DatabaseSchema/Package.swift index b2542fc..d06d0e1 100644 --- a/Packages/DatabaseSchema/Package.swift +++ b/Packages/DatabaseSchema/Package.swift @@ -18,7 +18,6 @@ let package = Package( dependencies: [ .package(url: "https://github.com/evgenyneu/keychain-swift.git", from: "24.0.0"), .package(url: "https://github.com/impel-intelligence/AnyLanguageModel", from: "2.2.4"), -// .package(path: "/Users/taylorlineman/Developer/git/AnyLanguageModel", traits: ["MLX"]), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/Packages/MinnaChat/LICENSE b/Packages/MinnaChat/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/Packages/MinnaChat/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Packages/ModelCDN/LICENSE b/Packages/ModelCDN/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/Packages/ModelCDN/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README-OUTLINE.md b/README-OUTLINE.md new file mode 100644 index 0000000..98b370f --- /dev/null +++ b/README-OUTLINE.md @@ -0,0 +1,89 @@ +# README outline + + + +A structure for the rewritten `README.md`, for you to write in your own voice. The current README is 20 lines, has no build instructions, and states that "Claude / Anthropic is the only provider currently supported" — which stopped being true as of 0.11.0. **Delete this file once the README is rewritten.** + +Two audiences land on this page and they want different things in the first ten seconds: a *user* wants to know what Minna does and how to get it; a *developer or privacy reviewer* wants to know how to build it and what it sends over the network. Serve the user first, then the developer. + +--- + +## 1. Title and one-line description + +Lead with what Minna **does**, not what it's named after. The Minerva line is charming and worth keeping, but as a subtitle rather than the opening. + +Something in the shape of: *a local-first AI assistant for your own documents — your files are indexed and searched on your Mac, never uploaded.* + +Badges: license (Apache-2.0), latest release, macOS version. + +## 2. Screenshot or short demo + +The single highest-value thing on the page, and the current README has none of the app itself. A GIF of asking a question and getting a cited answer would carry more than any paragraph. `Minna/Resources/Videos/` already has recordings made for onboarding. + +## 3. What it does + +Four or five bullets. Concrete over abstract: + +- Index folders of documents — PDF, Markdown, TXT, HTML, XML, OPML +- Ask questions and get answers **with citations back to the source passage** +- Hybrid search: full-text (FTS5) and semantic (vector) over the same corpus +- Your index is one portable `.irisdb` file you can move between machines +- Bring your own AI provider, or run entirely on-device + +## 4. Privacy + +Give this its own section near the top rather than burying it. It is a primary reason the source is public, and reviewers should not have to hunt for it. + +- Documents and chats never leave your machine +- Prompts go directly to the provider *you* chose, with *your* key +- On-device models (MLX, Apple Foundation Models) make no network calls at all +- API keys are stored in the macOS Keychain +- Link to `SECURITY.md`, which enumerates every network destination + +## 5. Install + +Keep the existing Releases link. Add the Mac App Store link when that ships. State the macOS requirement (26+) plainly — it's a steep floor and people should hit it here rather than after downloading. + +## 6. Setup + +The existing screenshot walkthrough is good and should survive the rewrite. Two fixes: + +- **Correct the provider list.** Minna supports Anthropic, OpenAI, Gemini, Ollama, Apple Foundation Models, and MLX. +- Mention that on-device models need no key at all, which is the fastest path to trying it. + +Keep the Open Course Materials sample-data link. + +## 7. Build from source + +New section — nothing like it exists today, and its absence is the single biggest gap for contributors. + + git clone --recursive https://github.com/impel-intelligence/Minna.git + cd Minna + open Minna.xcodeproj + +- Requirements: macOS 26+, Xcode 26+, Git LFS +- Note `--recursive` (submodules) and the recovery command for people who forget +- **State clearly that no configuration is needed.** `Config.xcconfig` ships blank, telemetry is off, signing is local. This is worth saying explicitly because most projects do require setup and people assume they've missed a step +- Note that corpus-dependent tests skip when fixtures are absent +- Link to `CONTRIBUTING.md` for detail rather than duplicating it + +## 8. Architecture + +A short paragraph and the package list, then link to `docs/ARCHITECTURE.md`. Enough that someone can decide whether to read further. + +## 9. Contributing + +Short. Link `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`. Mention DCO sign-off and that there's no CLA — contributors specifically look for that. + +## 10. License + +Apache-2.0, link `LICENSE`. Then one sentence that the code license does not cover the Minna name or marks, linking `TRADEMARK.md`. State it plainly rather than defensively — forks are welcome, they just need their own name. + +--- + +## Things to avoid + +- Don't claim "open source" and leave the private dependencies unresolved. The build genuinely has to work from a fresh clone before the README says it does. +- Don't over-promise on roadmap. A commercial product's README aging badly is worse than a short one. +- Don't bury macOS 26 as a requirement. +- Don't let the provider list drift again — it's already been wrong once. If anything, link to the settings UI as the source of truth. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7e63d54 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,59 @@ +# Security Policy + + + +Minna is published as open source specifically so that its privacy and security behavior can be verified. Reports are welcome and taken seriously. + +## Reporting a vulnerability + +**Please do not open a public issue.** + +Report privately through either channel: + +- [GitHub private security advisories](https://github.com/impel-intelligence/Minna/security/advisories/new) — preferred, since it keeps discussion and the eventual fix in one place. +- Email with `SECURITY` in the subject line. + +Please include: + +- What the issue is and why you believe it is a security problem +- Steps to reproduce, ideally with a minimal case +- The Minna version (**Minna → About**) and your macOS version +- Whether you intend to disclose publicly, and on what timeline + +### What to expect + +- **Acknowledgement within 3 business days.** +- An assessment and a rough remediation timeline within 10 business days. +- Credit in the release notes and the advisory, unless you prefer otherwise. + +We ask that you give us a reasonable opportunity to ship a fix before disclosing publicly. We will keep you informed of progress and will not ask for open-ended delays. + +## Scope + +Minna is a local-first macOS application. The following are in scope: + +- Unintended exposure of indexed document contents, chat history, or the `.irisdb` index +- Mishandling of user-supplied AI provider API keys, which are stored in the macOS Keychain +- Telemetry or network traffic that transmits more than what is documented below +- Sandbox escapes, privilege escalation, or code execution via crafted documents during indexing +- Weaknesses in the Sparkle auto-update path, including update signature verification + +Out of scope: + +- Vulnerabilities in third-party AI providers (Anthropic, OpenAI, Google, Ollama) themselves — report those to the provider +- Issues that require an already-compromised machine or physical access to an unlocked device +- Findings from automated scanners without a demonstrated impact on Minna + +## What Minna sends over the network + +Stated here so that reports can be measured against intended behavior. If you observe traffic that contradicts this, that is a reportable issue. + +- **Your documents and chats stay on your machine.** They are indexed locally into an `.irisdb` package and are never uploaded by Minna. +- **AI provider requests** go directly from your machine to whichever provider you configured, using your own API key. On-device models (MLX, Apple Foundation Models) make no network requests at all. +- **Model downloads** come from `cdn.tryminna.com`. +- **Update checks** (direct-download builds only) come from the Sparkle appcast. +- **Crash reporting and analytics** are opt-in at build time and are disabled in builds from source. In official release builds they collect aggregate counts and a model name — no document contents, no chat contents, and no personally identifying information (`sendDefaultPii` is off). See `Minna/TelemetryWrapper.swift`, which is deliberately small enough to read in full. + +## Supported versions + +Security fixes are issued for the latest released version. Please update to the current release before reporting. diff --git a/TRADEMARK.md b/TRADEMARK.md new file mode 100644 index 0000000..453c293 --- /dev/null +++ b/TRADEMARK.md @@ -0,0 +1,42 @@ +# Trademark Policy + + + +Minna's source code is licensed under the [Apache License, Version 2.0](LICENSE). That license covers the **code**. It does not grant any rights to the Minna name or to Minna's visual identity. + +This is explicit in the license itself. Section 6 of Apache-2.0 reads: + +> This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work. + +This document explains what that means in practice. + +## What is not covered by the code license + +The following are trademarks and brand assets of Impel Intelligence, Inc., and are **not** licensed under Apache-2.0: + +- The name **Minna** +- The name **Impel Intelligence** +- The Minna app icon (`Minna/Resources/Main.icon/`) +- The Minna owl mark (`Minna/Resources/Assets.xcassets/owl.imageset/`) +- The Impel logo (`Minna/Resources/Assets.xcassets/impel_logo.imageset/`) + +## What you may do + +- **Use the code.** Build it, modify it, ship it, sell it, subject only to Apache-2.0. +- **Say what your software is derived from.** "Based on Minna", "a fork of Minna", or "compatible with Minna" are all fine. This is the "reasonable and customary use in describing the origin" that Section 6 permits. +- **Build Minna from source for your own use**, including modified builds, and keep the branding on your own machine. +- **Write about Minna**, review it, teach with it, or reference it in documentation and articles. + +## What requires permission + +- **Distributing a modified build under the name "Minna."** If you fork Minna and distribute it to other people, please rename it and replace the icon and logo. This is the ordinary open-source expectation: users who download something called "Minna" should get software that Impel Intelligence stands behind. +- **Using the Minna or Impel Intelligence names or logos in a way that suggests endorsement**, affiliation, or official status. +- **Registering domain names, social accounts, or app listings** that use the Minna name in a way likely to be mistaken for the official project. + +## Why this exists + +Minna is a commercial product published as open source so that anyone can audit its privacy and security behavior. Apache-2.0 deliberately makes the code free to use and fork. The trademark is what lets users tell an official, signed, notarized Minna release apart from someone else's build. Keeping the name distinct protects users, not the code. + +## Questions + +If you want to use the Minna name or marks in a way this document does not clearly permit, ask first: . Reasonable requests are generally granted. diff --git a/Tools/ModelUploader/LICENSE b/Tools/ModelUploader/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/Tools/ModelUploader/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..f2a771c --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,99 @@ +# Minna Architecture + + + +An orientation guide for people reading the code for the first time. It covers how the pieces fit together and where to look for a given behavior, rather than documenting every type. + +## The shape of the thing + +Minna is a **local-first** macOS app. You point it at folders of documents; it reads and indexes them on your machine, then lets you ask questions that are answered against that index. The only thing that leaves your computer is the prompt you send to whichever AI provider you configured — and if you use an on-device model, not even that. + +That constraint drives the architecture. Indexing, storage, search, and document rendering are all local. The AI provider is a pluggable edge, deliberately kept at arm's length. + +``` + ┌────────────────────────────────────────────────┐ + │ Minna (app target) │ + │ SwiftUI views, windows, onboarding, settings │ + └───────┬─────────────┬──────────────┬───────────┘ + │ │ │ + ┌───────▼──────┐ ┌────▼─────┐ ┌──────▼────────┐ + │ IrisSearch │ │ MinnaChat│ │ LookAtMe │ + │ index and │ │ RAG chat │ │ render source │ + │ search │ │ + tools │ │ + highlight │ + └───────┬──────┘ └────┬─────┘ └───────────────┘ + │ │ + ┌───────▼──────┐ ┌────▼──────────┐ ┌────────────┐ + │ .irisdb │ │ ModelManager │ │ ModelCDN │ + │ file package│ │ providers │ │ downloads │ + └──────────────┘ └───────────────┘ └────────────┘ +``` + +## Packages + +Local Swift packages under `Packages/`. Two are git submodules, because they're useful independently of Minna. + +### `IrisSearch` (submodule) + +The search engine, and the most substantial piece of the system. Hybrid retrieval: keyword and semantic search over the same corpus. + +- **`Digester`** — turns files into text. Handles PDF, TXT, HTML, XML, OPML, and Markdown, then chunks the result. Markdown gets structure-aware chunking; prose falls back to sentence chunking. +- **`Embedder`** — produces vectors. Two backends: `CoreMLEmbedder` (a bundled BGE model) and `AppleIntelligenceEmbedder` (system-provided). +- **`IrisSearch`** — the index and query layer. SQLite via GRDB, with FTS5 for full-text search and FAISS for vector search. Results from both are combined. +- **`IrisCommon`** — shared types. + +The whole index is a single macOS **file package** with the `.irisdb` extension. It looks like one file in Finder and can be moved between machines by dragging it. This is a deliberate product decision, not just a storage detail — your index is a document you own, not hidden application state. + +### `MinnaChat` + +RAG chat on top of `IrisSearch`. + +- **`MinnaChat`** — conversation flow, prompt construction (`Instructions/`), and the tools exposed to the model: `SearchTool`, `GetDocumentTool`, `SearchInDocumentTool`, `GetExcerptContextTool`. The model doesn't receive your corpus; it receives the ability to *search* it, and pulls in only what it asks for. +- **`ModelManager`** — provider abstraction. Six implementations in `Providers/`: Anthropic, OpenAI, Gemini, Ollama, Apple Foundation Models, and MLX. The first three are remote APIs using your key; the last three run locally. + +### `LookAtMe` (submodule) + +Renders source documents and highlights the passage a citation points at, so an answer can be traced back to where it came from. + +### `ModelCDN` + +Fetches on-device model weights from `cdn.tryminna.com`. No dependencies — deliberately small and auditable. + +### `DatabaseSchema` + +SwiftData schema for application state — files, chats, configured providers. Provider API keys are **stored in the macOS Keychain**, not in this database and not in `UserDefaults` (see `Functions/Chats/ConfiguredProvider.swift`). + +## App targets + +- **`Minna`** — the app. `IrisApp.swift` is the entry point; `Views/` holds the UI by feature area (Chat, Search, Dashboard, Onboarding, Settings). `Local Search/` bridges the app to `IrisSearch` via `IrisContext` and `IrisDBController`. +- **`SearchModelAssets`** — a Background Assets extension that downloads embedding and language models outside the app's lifetime, so a first run isn't blocked on a large download. +- **`Tools/ModelUploader`** — a maintainer-side CLI for publishing models to the CDN. Not part of the app. + +## Build flavors + +Two distribution channels, separated by the `SPARKLE` compilation condition: + +| | Mac App Store | Direct download | +|---|---|---| +| Configuration | `Release` | `Release Sparkle` | +| Updates | App Store | Sparkle (`Frameworks/Sparkle.framework`) | +| `SPARKLE` flag | off | on | + +`Frameworks/Sparkle.framework` is vendored as a prebuilt binary and is excluded from App Store builds, where Sparkle would be both unnecessary and disallowed. + +## Configuration + +`Config.xcconfig` supplies build settings and ships with every value blank. Blank is the supported default: telemetry stays off and signing is local, so a build from source reports nothing anywhere. `Config.local.xcconfig` is a gitignored override for maintainers. `BuildConfiguration.swift` reads the values back and treats blank or unsubstituted values as "not configured". + +## Where to look + +| To change… | Start at | +|---|---| +| How a file type is parsed or chunked | `Packages/IrisSearch/Sources/Digester/` | +| Search ranking or index schema | `Packages/IrisSearch/Sources/IrisSearch/` | +| What the model can do during a chat | `Packages/MinnaChat/Sources/MinnaChat/Tools/` | +| Prompts | `Packages/MinnaChat/Sources/MinnaChat/Instructions/` | +| Adding an AI provider | `Packages/MinnaChat/Sources/ModelManager/Providers/` | +| Persisted app state | `Packages/DatabaseSchema/Sources/DatabaseSchema/Schema/` | +| Citation rendering | `Packages/LookAtMe/Sources/` | +| Telemetry | `Minna/TelemetryWrapper.swift` — small on purpose, read it in full | +| Release pipeline | `scripts/release.sh` | diff --git a/scripts/export_options/AppStoreExportOptions.plist b/scripts/export_options/AppStoreExportOptions.plist index f2077c2..5298cab 100644 --- a/scripts/export_options/AppStoreExportOptions.plist +++ b/scripts/export_options/AppStoreExportOptions.plist @@ -10,7 +10,8 @@ automatic uploadSymbols + teamID - VV548YNZL3 + diff --git a/scripts/export_options/SparkleExportOptions.plist b/scripts/export_options/SparkleExportOptions.plist index 3bc1f30..d3a5358 100644 --- a/scripts/export_options/SparkleExportOptions.plist +++ b/scripts/export_options/SparkleExportOptions.plist @@ -10,7 +10,8 @@ automatic stripSwiftSymbols + teamID - VV548YNZL3 + diff --git a/scripts/release.sh b/scripts/release.sh index 93f541c..d449832 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,12 +1,13 @@ #!/bin/sh # A script to run the whole release pipeline for self-distributed Minna :) # This script should be run on a development computer, it will not support CI/CD. +# Edited by Claude Opus 5 (Anthropic) on 2026-08-13 set -eu set -o pipefail TEMPORARY_DIRECTORY=tmp OUTPUT_DIRECTORY="out" -BASE=$(PWD) +BASE=$PWD NOTARY_PROFILE="Impel-Intelligence" PROGRESS_FILE="$TEMPORARY_DIRECTORY/progress.txt" @@ -94,7 +95,7 @@ fi # Check to see if the Sparkle Framework is the newest verison SPARKLE_GITHUB=sparkle-project/Sparkle -SPARKLE_LOCATION=$(PWD)/Frameworks/Sparkle.framework +SPARKLE_LOCATION=$PWD/Frameworks/Sparkle.framework SPARKLE_INFO_PLIST="$SPARKLE_LOCATION/Resources/Info.plist" SPARKLE_VERSION=$(plutil -extract CFBundleShortVersionString raw $SPARKLE_INFO_PLIST) @@ -125,15 +126,40 @@ if [ -z "$TAG_EXIST" ]; then fi ### Build ### -SPM_BUILD_DIRECTORY="$(PWD)/$TEMPORARY_DIRECTORY/spm" +SPM_BUILD_DIRECTORY="$PWD/$TEMPORARY_DIRECTORY/spm" -APP_STORE_BUILD_DIR="$(PWD)/$TEMPORARY_DIRECTORY/app-store-build" +APP_STORE_BUILD_DIR="$PWD/$TEMPORARY_DIRECTORY/app-store-build" APP_STORE_ARCHIVE="$APP_STORE_BUILD_DIR/Minna.xcarchive" -APP_STORE_EXPORT_OPTIONS=$(PWD)/scripts/export_options/AppStoreExportOptions.plist -SPARKLE_BUILD_DIR="$(PWD)/$TEMPORARY_DIRECTORY/sparkle-build" +SPARKLE_BUILD_DIR="$PWD/$TEMPORARY_DIRECTORY/sparkle-build" SPARKLE_ARCHIVE="$SPARKLE_BUILD_DIR/Minna.xcarchive" -SPARKLE_EXPORT_OPTIONS=$(PWD)/scripts/export_options/SparkleExportOptions.plist + +### Export Options ### +# The committed export options plists leave teamID blank so that no Apple Team ID lives in version control. Resolve it here from Config.local.xcconfig (or the DEVELOPMENT_TEAM environment variable) and write it into throwaway copies. +# The `|| true` matters: with `set -e` and `set -o pipefail`, a grep that matches nothing exits 1, which fails the whole pipeline and aborts the script before the friendly error below can run. +if [ -z "${DEVELOPMENT_TEAM:-}" ] && [ -f "$PWD/Config.local.xcconfig" ]; then + DEVELOPMENT_TEAM=$(grep -E '^[[:space:]]*DEVELOPMENT_TEAM[[:space:]]*=' "$PWD/Config.local.xcconfig" | head -1 | sed 's/.*=[[:space:]]*//' | tr -d '[:space:]' || true) +fi + +if [ -z "${DEVELOPMENT_TEAM:-}" ]; then + printf "🙅‍♀️ No signing team found.\n" + printf "👩‍💻 Set DEVELOPMENT_TEAM in Config.local.xcconfig, or export DEVELOPMENT_TEAM before running.\n" + exit 1 +fi + +EXPORT_OPTIONS_DIRECTORY="$PWD/$TEMPORARY_DIRECTORY/export_options" +mkdir -p "$EXPORT_OPTIONS_DIRECTORY" + +APP_STORE_EXPORT_OPTIONS="$EXPORT_OPTIONS_DIRECTORY/AppStoreExportOptions.plist" +SPARKLE_EXPORT_OPTIONS="$EXPORT_OPTIONS_DIRECTORY/SparkleExportOptions.plist" + +cp "$PWD/scripts/export_options/AppStoreExportOptions.plist" "$APP_STORE_EXPORT_OPTIONS" +cp "$PWD/scripts/export_options/SparkleExportOptions.plist" "$SPARKLE_EXPORT_OPTIONS" + +plutil -replace teamID -string "$DEVELOPMENT_TEAM" "$APP_STORE_EXPORT_OPTIONS" +plutil -replace teamID -string "$DEVELOPMENT_TEAM" "$SPARKLE_EXPORT_OPTIONS" + +printf "🔏 Signing with team %s\n" "$DEVELOPMENT_TEAM" # Archive the App Store configuration of Minna. ARCHIVE_APP_STORE_PROGRESS_MARKER="archive-app-store" diff --git a/scripts/sentry.sh b/scripts/sentry.sh deleted file mode 100644 index 1aa8851..0000000 --- a/scripts/sentry.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -eu # Fail on errors and unset variables - -echo "Upload Symbols To Sentry" - -DSYM_FOLDER="tmp/archive/iris.xcarchive/dSYMs/" - -# NOTE: SENTRY_ORG / SENTRY_PROJECT are external Sentry identifiers and must -# match the project configured in Sentry. Update them there if renamed to Iris. -export SENTRY_ORG=iris-h0 -export SENTRY_PROJECT=iris-mac -export SENTRY_AUTH_TOKEN=$1 - -sentry-cli debug-files upload --include-sources --force-foreground "$DSYM_FOLDER"