Skip to content

release(1.1.0): publish new version - #206

Open
goniszewski wants to merge 7 commits into
mainfrom
release-1.1.0
Open

release(1.1.0): publish new version#206
goniszewski wants to merge 7 commits into
mainfrom
release-1.1.0

Conversation

@goniszewski

Copy link
Copy Markdown
Owner

Summary

Minor release 1.1.0 — the AI provider model picker (new feature), the SSRF / upgrade / bind security hardening, and the 1.0.1 release-identity fixes ported onto the release branch.

Semver: minor — new user-facing feature (model catalog picker); security hardening and fixes ride along.

Changes

Features

  • AI provider model picker in Settings: searchable OpenRouter model catalog with a Free models only filter and custom (typed) model entry, backed by a new SSRF-guarded, size-capped GET /settings/ai-models daemon endpoint.
  • Route-level error boundary so malformed API data cannot blank the app.

Security / fixes

  • SSRF hardening: outbound page fetches and update checks follow redirects manually and validate every hop; private hosts, embedded credentials, and non-http(s) schemes are rejected at bookmarks, capture, MCP, and import.
  • Remote upgrades require HTTPS release bases and detached signatures by default, with optional signing-key fingerprint pinning and download size caps; --allow-unsigned / LITTLEIMP_ALLOW_UNSIGNED_UPGRADE=1 is the explicit escape hatch.
  • Bind policy: non-loopback binds are refused unless container context or LITTLEIMP_ALLOW_NON_LOOPBACK_BIND=1.
  • Default JSON body limits on mutating routes; HTTP restore no longer accepts allow_unsafe_no_checksum.
  • Concurrent same-URL creates return the existing bookmark (clear 409 for trashed/archived duplicates); mutations await daemon confirmation before success toasts/undo.
  • Bookmarklet embeds the token/daemon URL via JSON.stringify; safe http(s) checks before opening bookmarks.
  • Ported 1.0.1 release-identity fixes: installer version default, Grimoire/<version> user-agents, www.github.com / trailing-.git handling, atomic sqlite-vec index rebuild.

Release

  • Version bumped to 1.1.0 (root + daemon manifests, API/MCP contract, install.sh, docs, e2e).
  • Release archives built; Homebrew formula + checksum baselines filled with the real 1.1.0 SHAs.
  • CHANGELOG entry and regenerated API docs.

Verification

  • npm run check green: lint (0 errors), type-check, frontend + daemon unit tests (516 daemon tests), docs:api:check, production build.
  • Release artifacts validated by npm run release:validate + shasum -c (checksum-only). Detached .asc signatures must be added by the maintainer before publishing — the CLI upgrade path now requires signatures by default (fix(security): harden SSRF, upgrades, bind policy, and mutation UX #201), so signing is mandatory for 1.1.0 remote upgrades unless --allow-unsigned is accepted.

goniszewski and others added 4 commits August 12, 2026 11:01
)

* fix(security): harden SSRF, upgrades, bind policy, and mutation UX

Address the comprehensive code-review findings: validate redirects before
following them, reject arbitrary HTTP update sources, require signed remote
upgrades, fail closed on non-loopback binds outside containers, reject URL
credentials consistently, apply default body limits, drop unsafe restore
bypass from HTTP, and make frontend mutations confirm before success UX.

Co-authored-by: Robert Goniszewski <goniszewski@users.noreply.github.com>

* test: align category filter expectations and simplify update check types

Prefer category_id-only list/search params in hook tests, and use a
concrete ApiUpdateCheckResult shape to avoid deep DTO instantiation.

Co-authored-by: Robert Goniszewski <goniszewski@users.noreply.github.com>

* fix(ui): keep Add Bookmark validation copy e2e-compatible

Preserve a "valid URL" phrase in the dialog error so existing journey
coverage continues to match the safer http(s)/no-credentials check.

Co-authored-by: Robert Goniszewski <goniszewski@users.noreply.github.com>

* fix(security): keep private update sources working and align fetcher UA

- update/service: thread allowPrivateHosts into the real-fetch path so the
  CLI's local test sources (e.g. --source http://127.0.0.1:9999) are not
  blocked by the new per-hop redirect guard; private hosts stay rejected
  by default on the HTTP route
- pipeline/fetcher: send the current Grimoire/<version> user-agent (was the
  stale LittleImp/0.0 string pointing at the old little-imp repo URL)
- tests: cover private-source checkForUpdates behavior and the fetcher UA

Co-authored-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>

---------

Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Robert Goniszewski <goniszewski@users.noreply.github.com>
- daemon: GET /settings/ai-models lists the OpenRouter model catalog with a
  free-only filter; guarded by the X-LittleImp-Frontend header, SSRF checks
  (private-host base URLs and redirect final hops), a 15s timeout, and a
  10 MB response cap; upstream error bodies are never relayed
- settings: default OpenRouter model becomes openai/gpt-latest (drop the
  confusing '~' fallback prefix); stored values are normalized on load
- frontend: searchable model combobox with free-only toggle, loading/error/
  retry states, and custom (typed) model entry
- contract, generated API docs, fixtures, and tests updated

Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>
* fix: patch release-blocking inconsistencies

- install.sh: default LITTLEIMP_VERSION to the current release (was 0.1.0-beta)
- extractors: accept www.github.com URLs, restore .git suffix stripping, and
  send Grimoire/1.0.0 User-Agent from all fetchers
- e2e: align mock daemon and specs with the real daemon version and repo URLs
- embedding-repository: rebuild the sqlite-vec index in a single atomic
  transaction instead of thousands of per-row transactions on every boot
- docs: refresh release-checklist.md and update-system.md version strings
  (0.1.0-beta -> 1.0.0) and align test fixtures

* chore(release): publish 1.0.1 patch

- Bump version identity to 1.0.1 across package manifests, install.sh,
  API/MCP contract, docs, e2e mocks, and test fixtures
- Derive the outgoing User-Agent from the packaged version instead of
  hardcoding it, so fetchers stop drifting from the release version
- Build release archives and fill the Homebrew formula and checksum
  baselines with the real 1.0.1 artifact SHAs
- Add a 1.0.1 changelog entry; regenerate API docs
- Bump version identity to 1.1.0 across package manifests, install.sh,
  API/MCP contract, docs, e2e mocks, and test fixtures
- Carry the 1.0.1 release-identity fixes onto the release branch: installer
  version default, Grimoire/<version> user-agents, www.github.com / .git
  handling, atomic sqlite-vec index rebuild
- Build 1.1.0 release archives and fill the Homebrew formula and checksum
  baselines with the real artifact SHAs
- Add a 1.1.0 changelog entry; regenerate API docs

Co-authored-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 09:12
@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Resolve all conflicts in favor of the 1.1.0 release branch (superset of
the 1.0.1 content cherry-picked earlier plus the 1.1.0 version bumps).

Co-authored-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 82bcda45db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread daemon/src/update/upgrade.ts Outdated
Comment on lines +331 to +335
const combined = `${outputToString(result.stderr)}\n${outputToString(result.stdout)}`;
const found = [...combined.matchAll(/([A-F0-9]{40}|[A-F0-9]{64})/gi)].map((m) =>
m[1].toUpperCase()
);
const matched = found.some((fp) => allowedFingerprints.includes(fp));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Parse the verified signing-key fingerprint from GPG status

When fingerprint pinning is enabled, this accepts any 40- or 64-hex substring from GPG's human-readable output, not specifically the key that produced the signature. GPG emits signer UIDs in the same stream (for example, Good signature from "..."), so a different key in the user's keyring can place an allowed fingerprint in its UID, sign a malicious archive, and satisfy found.some(...); the archive is then executed by the installer. Invoke GPG with a machine-readable status fd and compare only the fingerprint from VALIDSIG.

Useful? React with 👍 / 👎.

Comment thread daemon/src/ai/models-catalog.ts Outdated
Comment on lines +91 to +95
const res = await fetch(url, { signal: controller.signal, redirect: "follow" });
// SSRF guard: reject redirect chains that land on private hosts. Like
// pipeline/fetcher.ts this only inspects the final hop; intermediate hops
// are the same accepted risk documented in lib/network.ts.
if (res.redirected && isPrivateHost(new URL(res.url).hostname)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate catalog redirects before following them

When the configured public OpenRouter base URL redirects through a private or loopback URL, redirect: "follow" contacts that target before the final-host check runs, so the new catalog endpoint remains usable for SSRF despite being described as guarded. Use the shared manual redirect-validation helper so every Location is rejected before the request is sent.

AGENTS.md reference: AGENTS.md:L37-L37

Useful? React with 👍 / 👎.

Comment thread src/components/ui/combobox.tsx Outdated
className="h-9"
/>
</div>
{error ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve custom model entry when the catalog is unavailable

When the catalog request fails—for example while offline or during an OpenRouter outage—the error branch replaces the entire CommandList, while the custom Use … option exists only in the non-error branch. Because this combobox replaces the former text input, users cannot change to a custom OpenRouter model until the remote catalog recovers; keep custom entry available alongside the retry state so this normal settings flow does not depend on the cloud catalog.

AGENTS.md reference: AGENTS.md:L39-L39

Useful? React with 👍 / 👎.

Signs release/*.tar.gz with a detached gpg signature (key auto-detected
from the repo git user.email), verifies, runs release:validate
--require-signatures, and exports the public key + fingerprint.

Co-authored-by: Robert Goniszewski <robertgoniszewski@outlook.com>
Signed-off-by: Robert Goniszewski <robertgoniszewski@outlook.com>
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants