Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
c529b94
chore: sync main into develop after 0.1.4
socadb-release-bot[bot] Oct 12, 2026
e98cc4d
Merge pull request #93 from soca-projects/chore/sync-main-0.1.4
Cassidy321 Oct 12, 2026
eae3cec
feat: add notes, indexes, enums and type lengths to the schema model
Cassidy321 Oct 13, 2026
ae729c9
feat: keep enum links, indexes and type parameters consistent
Cassidy321 Oct 13, 2026
f70bd6b
feat: tell value defaults from expression defaults
Cassidy321 Oct 13, 2026
5c622cf
feat: add enum and index actions to the schema store
Cassidy321 Oct 13, 2026
239a173
fix: validate enum links when a schema is loaded
Cassidy321 Oct 13, 2026
f9eb03b
fix: keep notes, indexes and enums in JSON imports
Cassidy321 Oct 13, 2026
63dc705
feat: carry enums through SQL and JSON imports
Cassidy321 Oct 13, 2026
0b454dc
feat: copy notes, indexes and enums when duplicating a table
Cassidy321 Oct 13, 2026
ee5e6a1
fix: save schemas opened from the home or restored at startup
Cassidy321 Oct 13, 2026
e598985
Merge pull request #94 from soca-projects/feat/schema-model-enrichment
Cassidy321 Oct 13, 2026
7cd7983
Merge branch 'develop' into fix/save-recent-file
Cassidy321 Oct 13, 2026
747c796
Merge pull request #95 from soca-projects/fix/save-recent-file
Cassidy321 Oct 13, 2026
cb8d5aa
feat: add UNSIGNED to MySQL numeric columns
Cassidy321 Oct 14, 2026
b086a60
feat: add column type, enum and default helpers
Cassidy321 Oct 14, 2026
a7f9dce
feat: edit columns in a one-line list with a column editor
Cassidy321 Oct 14, 2026
89d6625
chore: keep only the why in code comments
Cassidy321 Oct 14, 2026
c904348
Merge pull request #96 from soca-projects/feat/column-editor
Cassidy321 Oct 14, 2026
e0bf078
feat: add index naming, foreign key hint and index editing helpers
Cassidy321 Oct 14, 2026
da9da33
feat: add the table note and an Indexes tab to the side panel
Cassidy321 Oct 14, 2026
6b1b7ae
chore: comment the column editor choices that break if undone
Cassidy321 Oct 14, 2026
c39c3f3
Merge pull request #97 from soca-projects/feat/table-indexes-panel
Cassidy321 Oct 14, 2026
0ba476b
refactor: confirm deleting all conversations in an app modal
Cassidy321 Oct 14, 2026
d3bbd1b
chore: enforce the CLAUDE.md conventions with ESLint
Cassidy321 Oct 14, 2026
2239466
chore: deny panics, prints and undocumented unsafe in the Rust code
Cassidy321 Oct 14, 2026
eb3cc44
Merge pull request #98 from soca-projects/chore/quality-gates
Cassidy321 Oct 14, 2026
c6298c1
feat: size tables and thumbnails for their index section
Cassidy321 Oct 14, 2026
8a7aa73
feat: show notes, enum values and indexes on canvas tables
Cassidy321 Oct 14, 2026
f0326e7
fix(deps): update rustls to 0.23.46
Cassidy321 Oct 14, 2026
e5d7654
Merge pull request #99 from soca-projects/fix/rustls-advisories
Cassidy321 Oct 14, 2026
820334c
Merge branch 'develop' into feat/canvas-enrichment
Cassidy321 Oct 14, 2026
a396330
Merge pull request #100 from soca-projects/feat/canvas-enrichment
Cassidy321 Oct 14, 2026
17368e5
feat: grey out columns an index can't use
Cassidy321 Oct 14, 2026
00cb887
fix: move an enum aside when a table takes its name
Cassidy321 Oct 14, 2026
2996671
feat: export enums, indexes, notes and type parameters to SQL
Cassidy321 Oct 14, 2026
5e7692a
Merge pull request #101 from soca-projects/feat/sql-export-enrichment
Cassidy321 Oct 14, 2026
dbe6483
feat: import enums, indexes, notes and pg_dump keys from SQL
Cassidy321 Oct 15, 2026
a71dc53
feat: list what a SQL import could not keep
Cassidy321 Oct 15, 2026
b4d3c7b
fix: keep empty text defaults through import and export
Cassidy321 Oct 15, 2026
4af2dc0
Merge pull request #102 from soca-projects/feat/sql-import-enrichment
Cassidy321 Oct 15, 2026
827512b
feat: let the agent read and write notes, enums, indexes and type par…
Cassidy321 Oct 15, 2026
c0e7de2
feat: tell the agent about notes, enums and indexes
Cassidy321 Oct 15, 2026
1602dd5
Merge pull request #103 from soca-projects/feat/agent-schema-enrichment
Cassidy321 Oct 15, 2026
a566a72
feat: parse DBML files
Cassidy321 Oct 15, 2026
a57ca7d
feat: import DBML files
Cassidy321 Oct 15, 2026
88aae30
Merge pull request #104 from soca-projects/feat/dbml-import
Cassidy321 Oct 15, 2026
5f7aaf6
feat: detect MySQL and PostgreSQL from more SQL types
Cassidy321 Oct 15, 2026
9eb7df0
feat: guess a DBML file's database from its types
Cassidy321 Oct 15, 2026
31d8030
Merge pull request #105 from soca-projects/feat/import-detection
Cassidy321 Oct 15, 2026
cfe4ca8
feat: create schema files without overwriting
Cassidy321 Oct 16, 2026
abaaf1b
refactor: move import actions out of the import window
Cassidy321 Oct 16, 2026
236d891
feat: build one schema file per imported file
Cassidy321 Oct 16, 2026
8e96657
feat: import several files from the home
Cassidy321 Oct 16, 2026
111046f
feat: show each imported file's result
Cassidy321 Oct 16, 2026
5a35777
Merge pull request #106 from soca-projects/feat/multi-file-import
Cassidy321 Oct 16, 2026
f4a7c34
feat: drop files on the home to import them
Cassidy321 Oct 16, 2026
f510b47
Merge pull request #107 from soca-projects/feat/home-drop
Cassidy321 Oct 16, 2026
42ffaff
fix: read a composite key declared one column at a time
Cassidy321 Oct 16, 2026
c5660c6
Merge pull request #108 from soca-projects/fix/composite-primary-key
Cassidy321 Oct 16, 2026
3e0b149
feat: give the app the website's paper look
Cassidy321 Oct 16, 2026
a8d2a54
Merge pull request #109 from soca-projects/feat/paper-theme
Cassidy321 Oct 17, 2026
2adba95
chore(deps): ignore zip advisories until the updater ships zip 9
Cassidy321 Oct 17, 2026
9e72047
Merge pull request #110 from soca-projects/chore/ignore-zip-advisories
Cassidy321 Oct 17, 2026
5db5e00
feat: draw the empty states
Cassidy321 Oct 17, 2026
980862f
Merge pull request #111 from soca-projects/feat/empty-state-drawings
Cassidy321 Oct 17, 2026
d03e4f7
fix: open the app's own menu instead of the system dropdowns
Cassidy321 Oct 17, 2026
910845a
Merge pull request #112 from soca-projects/fix/own-menus
Cassidy321 Oct 17, 2026
56c478d
fix: keep a selected table's relations when pressing delete
Cassidy321 Oct 17, 2026
0bef475
Merge pull request #113 from soca-projects/fix/backspace-keeps-relations
Cassidy321 Oct 17, 2026
a31b4ff
feat: sign and notarize the macOS app with a Developer ID
Cassidy321 Oct 19, 2026
0741ab2
Merge pull request #114 from soca-projects/feat/macos-developer-id
Cassidy321 Oct 19, 2026
6cf6bfa
feat: lighten the sticker on the home's New schema button
Cassidy321 Oct 20, 2026
701fe2c
Merge pull request #115 from soca-projects/feat/home-light-sticker
Cassidy321 Oct 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ jobs:
- platform: macos-latest
args: --target aarch64-apple-darwin
bunTarget: darwin-arm64
macTarget: aarch64-apple-darwin
publishArgs: --config '{"bundle":{"macOS":{"hardenedRuntime":true}}}'
- platform: macos-latest
args: --target x86_64-apple-darwin
bunTarget: darwin-x64
macTarget: x86_64-apple-darwin
publishArgs: --config '{"bundle":{"macOS":{"hardenedRuntime":true}}}'
- platform: ubuntu-22.04
args: '--verbose'
bunTarget: linux-x64
Expand Down Expand Up @@ -131,13 +135,31 @@ jobs:
if-no-files-found: warn
retention-days: 7

- name: Import the Developer ID certificate
if: ${{ inputs.publish && matrix.platform == 'macos-latest' }}
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
run: ./scripts/macos/import-signing-identity.sh

- name: Sign Sparkle's helpers
if: ${{ inputs.publish && matrix.platform == 'macos-latest' }}
run: ./scripts/macos/sign-sparkle-helpers.sh

- name: Build and publish
if: ${{ inputs.publish }}
timeout-minutes: 150
uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0.6.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
APPLE_API_KEY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_API_KEY || '' }}
APPLE_API_ISSUER: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_API_ISSUER || '' }}
APPIMAGE_EXTRACT_AND_RUN: '1'
NO_STRIP: 'true'
BUN_TARGET: ${{ matrix.bunTarget }}
Expand All @@ -155,7 +177,36 @@ jobs:
# succeed, so users never see a partial release.
releaseDraft: true
prerelease: ${{ inputs.prerelease }}
args: ${{ matrix.args }}
args: ${{ matrix.args }} ${{ matrix.publishArgs }}

- name: Notarize the disk image
if: ${{ inputs.publish && matrix.platform == 'macos-latest' }}
timeout-minutes: 150
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
TAG_NAME: ${{ inputs.tag-name }}
BUNDLE_DIR: src-tauri/target/${{ matrix.macTarget }}/release/bundle
run: |
dmgs=("$BUNDLE_DIR"/dmg/*.dmg)
if [ "${#dmgs[@]}" -ne 1 ] || [ ! -f "${dmgs[0]}" ]; then
echo "::error::Expected one disk image in $BUNDLE_DIR/dmg, found: ${dmgs[*]}"
exit 1
fi
./scripts/macos/notarize-dmg.sh "${dmgs[0]}" "$TAG_NAME"

- name: Check the signature and notarization
if: ${{ inputs.publish && matrix.platform == 'macos-latest' }}
env:
BUNDLE_DIR: src-tauri/target/${{ matrix.macTarget }}/release/bundle
run: ./scripts/macos/check-signature.sh "$BUNDLE_DIR/macos/SocaDB.app" "$BUNDLE_DIR"/dmg/*.dmg

- name: Remove the signing keychain
if: ${{ always() && inputs.publish && matrix.platform == 'macos-latest' }}
run: |
security delete-keychain "$RUNNER_TEMP/macos-signing/signing.keychain-db" || true
rm -rf "$RUNNER_TEMP/macos-signing"

- name: Upload AppImage debug artifacts on failure
if: failure() && matrix.platform == 'ubuntu-22.04'
Expand Down
82 changes: 82 additions & 0 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"src/components/ChatToolCall/ChatToolCall.tsx": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
}
},
"src/hooks/useChatStream.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/hooks/useMcpBridge.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/i18n.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/stores/chatStore.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
}
},
"src/stores/updateStore.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 2
}
},
"src/types/chat.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/utils/chatCommands.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/utils/chatEventHandler.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 9
}
},
"src/utils/chatPersistence.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 3
}
},
"src/utils/exportPng.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/utils/exportSvg.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/utils/fileOperations.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 3
}
},
"src/utils/importJson.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 3
}
},
"src/utils/languagePersistence.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
},
"src/utils/themePersistence.ts": {
"@typescript-eslint/consistent-type-assertions": {
"count": 1
}
}
}
65 changes: 62 additions & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import prettier from "eslint-config-prettier";

export default tseslint.config(
{ ignores: ["dist", "src-tauri"] },
{ linterOptions: { noInlineConfig: true } },
js.configs.recommended,
...tseslint.configs.strict,
...tseslint.configs.stylistic,
Expand All @@ -16,11 +17,69 @@ export default tseslint.config(
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
"@typescript-eslint/consistent-type-assertions": [
"error",
{ assertionStyle: "never" },
],
"no-console": "error",
"no-restricted-properties": [
"error",
{ object: "Math", property: "random", message: "Use genId() from utils/id.ts." },
{ property: "randomUUID", message: "Use genId() from utils/id.ts." },
],
"no-restricted-imports": [
"error",
{
paths: [
{ name: "lucide-react", message: "Icons come from @phosphor-icons/react." },
{ name: "nanoid", message: "Use genId() from utils/id.ts." },
{ name: "uuid", message: "Use genId() from utils/id.ts." },
{
name: "@tauri-apps/plugin-dialog",
importNames: ["message", "ask", "confirm"],
message:
"Use a sonner toast or the app's Modal: native dialogs look foreign and devctl can't drive them.",
},
],
},
],
"no-restricted-syntax": [
"error",
{
selector:
"ImportDeclaration[source.value='@phosphor-icons/react'] ImportSpecifier[imported.name!=/^(Icon(?:[A-Z]\\w*)?|\\w+Icon)$/]",
message: "Import Phosphor icons as `XIcon as X`.",
},
{
selector:
"ImportDeclaration[source.value='@phosphor-icons/react'] ImportNamespaceSpecifier",
message: "Import Phosphor icons as `XIcon as X`.",
},
{
selector: "JSXAttribute[name.name='target'][value.value='_blank']",
message:
"The WebView blocks target=_blank: open links with @tauri-apps/plugin-opener.",
},
],
},
},
{
files: ["src/utils/id.ts"],
rules: { "no-restricted-properties": "off" },
},
{
files: ["src/**/index.ts", "src/**/index.tsx"],
rules: {
"no-restricted-syntax": [
"error",
{ selector: "Program", message: "No barrel files: import the source file." },
],
},
},
{
files: ["**/*.test.ts"],
rules: { "@typescript-eslint/consistent-type-assertions": "off" },
},
prettier,
);
10 changes: 10 additions & 0 deletions mcp-server/runtime.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
16 changes: 12 additions & 4 deletions mcp-server/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@ if (os === "darwin") {
if (process.platform !== "darwin") {
throw new Error("A macOS runtime can only be built on macOS (it must be re-signed)");
}
console.log(`Ad-hoc signing bundled binaries`);
console.log(` ok: ${adHocSignMachOs("dist")} binaries`);
const identity = process.env.APPLE_SIGNING_IDENTITY;
console.log(identity ? `Signing bundled binaries as ${identity}` : `Ad-hoc signing bundled binaries`);
console.log(` ok: ${signMachOs("dist", identity)} binaries`);
}

console.log(`Done.`);
Expand All @@ -204,12 +205,19 @@ function isMachO(path: string): boolean {
}
}

function adHocSignMachOs(dir: string): number {
// Tauri signs the app and its frameworks but not resources, so the notary
// service would reject these binaries unless they carry the Developer ID,
// a timestamp and the hardened runtime. Under that runtime the Bun-compiled
// ones (bun, claude, socadb-mcp) can't JIT without runtime.entitlements.
function signMachOs(dir: string, identity: string | undefined): number {
const args = identity
? ["--force", "--sign", identity, "--options", "runtime", "--timestamp", "--entitlements", "runtime.entitlements"]
: ["--force", "--sign", "-"];
let count = 0;
for (const rel of readdirSync(dir, { recursive: true }) as string[]) {
const path = join(dir, rel);
if (!lstatSync(path).isFile() || !isMachO(path)) continue;
execFileSync("codesign", ["--force", "--sign", "-", path], { stdio: "pipe" });
execFileSync("codesign", [...args, path], { stdio: "pipe" });
execFileSync("codesign", ["--verify", "--strict", path], { stdio: "pipe" });
count++;
}
Expand Down
4 changes: 2 additions & 2 deletions mcp-server/src/tools/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function registerReadTools(server: McpServer) {
"get_schema",
{
description:
"Get the complete database schema including all tables, columns, and relations",
"Get the complete database schema: tables with notes, columns (type parameters, default and its kind, enum values, note) and indexes, relations, and PostgreSQL enum types",
inputSchema: {},
},
async () => ok(await send("get_schema")),
Expand All @@ -29,7 +29,7 @@ export function registerReadTools(server: McpServer) {
server.registerTool(
"get_table",
{
description: "Get a specific table by name with all its columns",
description: "Get a specific table by name with its note, columns and indexes",
inputSchema: {
name: z.string().describe("The table name to look up"),
},
Expand Down
Loading
Loading