Files
gridline/desktop/src-tauri/Cargo.toml
T
adrianbonpin 9089f313f8
Release / linux (push) Successful in 22m30s
Release / windows (push) Canceled after 0s
fix(keychain) + release: macOS keychain ACL self-repair, bump 0.8.1 (#37)
* fix(keychain): repair stale macOS keychain ACLs before reads

macOS records the trusted application of a legacy keychain item as the
executable *path* for an ad-hoc (dev/linker-signed) build, and as a code
requirement + cdhash partition list for a signed bundle. When the path
changes — the monorepo move (`src-tauri/` -> `desktop/src-tauri/`), a
reinstalled app, running the installed app after a dev build — the ACL no
longer admits the running binary, so macOS demands the keychain password on
*every* access: once per secret, every time, with no "Always Allow".

The pin only ran after writes, and writing to an inaccessible item needs the
same authorization, so the ACL was never repaired.

- keychain_acl::is_item_trusted() answers "am I already in this item's ACL?"
  with a metadata-only, prompt-free lookup (SecKeychainItemCopyAccess +
  SecAccessCopyACLList + comparison against this process's own
  SecTrustedApplication representation; a signed bundle's `cdhash:` partition
  lists count as trusted and are left alone).
- ensure_item_acl() now no-ops when already trusted (no duplicate ACL entries,
  no redundant authorization) and otherwise pins exactly as before.
- New before_read() hook, called from every keychain read path (DB password,
  SSH password, SSH passphrase — commands and internal helpers), so a stale
  item costs one authorization and is silent from then on.
- ItemSearchOptions reports "nothing matched" as errSecItemNotFound, which is
  now handled as "no item" instead of a lookup error — previously every
  connection without a stored password logged a spurious failure.

Verified: cargo test --lib (408 passed) plus the ignored live test
(`cargo test --lib -- --ignored keychain_acl`), which asserts a fresh item is
already trusted, repairs are idempotent and the secret still reads back. That
test now finishes in 0.25s instead of ~8s because the redundant
SecKeychainItemSetAccess is gone.

* chore(release): bump 0.8.1 and document GitHub-only releases

Version 0.8.0 -> 0.8.1 across every synced location: desktop/package.json,
desktop/src-tauri/Cargo.toml (+ Cargo.lock gridline entry), tauri.conf.json,
www/src/pages/index.astro, www/public/landing.js, both README download tables
(+ the MAINTENANCE note), and the version/docs-coverage/bundle-config tests.
Adds the 0.8.1 changelog entry (site + README Recent Changes).

AGENTS.md: releases are GitHub-only — tag `prod` and `git push github vN.M.N`
(origin/Gitea is a just-in-case mirror; never push branches, PRs or tags
there), and the keychain row documents the self-healing ACL repair.
2026-09-24 03:43:46 +08:00

62 lines
2.7 KiB
TOML

[package]
name = "gridline"
version = "0.8.1"
description = "An open-source, high-performance database GUI client for PostgreSQL and beyond"
authors = ["you"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
# The `_lib` suffix may seem redundant but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "gridline_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
rusqlite = { version = "0.31", features = ["bundled"] }
# URL percent-encoding for tokio-postgres connection strings (user/password may contain special chars)
urlencoding = "2"
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1", features = ["v4", "serde"] }
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
tokio = { version = "1", features = ["full"] }
tokio-postgres = { version = "0.7", features = ["with-chrono-0_4", "with-uuid-1", "with-serde_json-1"] }
bytes = "1"
futures-util = "0.3"
sqlx = { version = "0.8", features = ["runtime-tokio", "mysql", "tls-rustls", "json"] }
redis = { version = "0.27", features = ["tokio-comp"] }
# async-ssh2 is not available at v0.4; using synchronous ssh2 via tokio::task::spawn_blocking per plan's fallback
# vendored-openssl: link OpenSSL statically so the release binary has NO
# runtime dependency on the build machine's Homebrew openssl (@/opt/homebrew
# absolute LC_LOAD_DYLIB — dyld aborts on user machines without it).
ssh2 = { version = "0.9", features = ["vendored-openssl"] }
deadpool-postgres = { version = "0.14" }
indexmap = { version = "2", features = ["serde"] }
tauri-plugin-keyring-store = { version = "0.2.0", default-features = false }
tokio-postgres-rustls = "0.12"
# rustls: ring-only crypto provider (no aws-lc-rs / cmake C build); tls12 needed for Postgres
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12", "logging"] }
rustls-pemfile = "2"
rustls-pki-types = "1"
rustls-native-certs = "0.7"
# Keychain ACL normalization (explicit SecAccess on stored secrets so items
# survive app re-signs without permission prompts) — macOS only.
[target.'cfg(target_os = "macos")'.dependencies]
security-framework = "3.7"
security-framework-sys = "2.17"
# core-foundation: CFString/CFArray/TCFType helpers for the SecAccess FFI
# (already a transitive dep of security-framework; pinned to the same 0.10 line)
core-foundation = "0.10"