name: sigit-app
description: Use when working on the "siGit Code & Deploy" Tauri desktop app (repo ~/Repositories/sigit-app), especially account management — login, signup, email verification, password reset, me, logout, remove account — and keeping account feature parity with the sigit-si web app. Covers the src-tauri account command set, the AccountStatus/ErrorResponse contract, token storage, the settings/account React views, and the decision about whether the app talks to smbCloud Auth directly or through sigit.si/api/v1.
siGit Code & Deploy desktop app (sigit-app)
Product map: siGit Code (local agent) · siGit Code Cloud (hosted chat + Cloud Sessions) · siGit Code Cloud Agent (autonomous task → PR; planning).
sigit.siis Git hosting;code.sigit.siis the home of siGit Code. Full taxonomy: product-overview.
sigit-app is the Tauri desktop client for siGit (repo
~/Repositories/sigit-app). It is a public client (a shipped binary), so the
public-client security rules apply — see
smbcloud-cli/.agents/skills/smbcloud-auth/SKILL.md. This file is the
sigit-app-specific view; keep its account features at parity with the sigit-si
web account page (sigit-si/.agents/skills/smbcloud-auth/SKILL.md).
Account command set
Rust commands in src-tauri/src/account/ (registered in mod.rs), each a
#[tauri::command]:
command_login→login(app, env, username, password)command_signup→signup(...)command_me→me(...)command_logout→logout(...)command_remove_account→remove_account(app, env, client, access_token)command_resend_confirmation_emailcommand_reset_passwordcommand_resend_reset_password_instructiont(note: existing misspelled name — match it exactly when wiring the frontend; don't "fix" it without renaming the invoke call sites too)command_check_email_oauth
Current data flow
Today the commands call the Rust auth SDK directly, not an HTTP API:
smbcloud_auth::login::login(env, client(), username, password)
smbcloud_model::{ error_codes::{ErrorCode, ErrorResponse}, login::AccountStatus }
smbcloud_network::environment::Environment // Dev | Production
- success returns
AccountStatus; onAccountStatus::Ready { access_token }the token is persisted viacrate::store::store_token - preserve the
AccountStatuscontract end to end:NotFound·Ready { access_token }·Incomplete { status } - failures return
ErrorResponse::Error { error_code, message }(ErrorCodefromsmbcloud_model) env: Environmentis passed from the frontend (useEnvironment().current)
Frontend
src/components/sidebar/settings/:
account.tsx— signed-in view: email, Anthropic API key field (stored locally on-device viaget_setting/update_setting, used by the Claude ACP agent — not an auth credential), Logout, Remove Accountlogin-form.tsx,signup.tsx,verify-email-form.tsx,set-password-form.tsx,logged-out-view.tsx,debug-setting-view.tsx
Frontend calls Rust via invoke("<command>", { env, accessToken, ... }). The
env switch is gated through useEnvironment; keep production/dev switching behind
debug controls.
Integration decision: direct SDK vs sigit.si/api/v1
The current architecture is app → Rust SDK → smbCloud Auth. The active goal
is to route desktop auth through sigit.si/api/v1 instead (app → sigit.si →
smbCloud Auth). Before implementing, settle this explicitly:
- Direct SDK (status quo): fewer hops, but the desktop binary needs smbCloud app credentials and bypasses sigit-si entirely.
- Via sigit.si/api/v1 (goal): sigit-si becomes the trust boundary, holds the
confidential
app_secretserver-side, and the desktop app only ever sees a bearer token. Better for the public-client rule; requires building the JSON API in sigit-si first (see the sigit-si smbcloud-auth skill).
If switching to the API path, change the command bodies to call
sigit.si/api/v1/* and keep the same AccountStatus / ErrorResponse
shapes so the frontend and token storage are unaffected.
Git operations (repos)
Git uses Smart HTTP with token auth — no SSH. Live commands in
src-tauri/src/repos/ (registered in lib.rs):
clone_repo·publish_repo·push_repo/pull_repo·list_repos
Two-token flow — never use the account access token as a git credential:
- login → account access token persisted via
crate::store::store_token repos::api::fetch_git_token(env, access_token)POSTssigit.si→git_credentials(bearer = access token) → returns a short-lived scopedgit_token- git2 credential callback authenticates over HTTPS via HTTP Basic:
Cred::userpass_plaintext("x-access-token", git_token)— username is the literal stringx-access-token, password is the scoped git token repos::api::create_remote_repoPOSTsrepos(bearer = access token) to create the bare repo before first publish
This is in-process libgit2 (git2 / gix, vendored) over HTTPS — no subprocess,
no key files — so it works inside the sandboxed App Store build and the
container-stored-repo model.
Legacy SSH path (deprecated — do not extend)
src/_git/{clone_project,desktop_deploy}.rs,
src/project/command_clone_frontend_app.rs, and
src/ssh/command_generate_ssh_key.rs still use Cred::ssh_key and remain
registered (clone_project, clone_frontend_app, ssh_clone,
generate_ssh_key), but SSH-based git is no longer the model — new work uses
the Smart HTTP path above. desktop_deploy.rs also hardcodes
/Users/setoelkahfi/.ssh/..., which is dead in any non-author or sandboxed
build. Candidates for removal, not extension.
Validation
cargo checkinsrc-tauripnpm build(or the app's package script) when the frontend changed- exercise login → verify email → me → logout → remove against the dev environment
- confirm token storage and session restore (
me) still work
Common mistakes
- Breaking the
AccountStatuscontract the frontend depends on - Renaming a command without updating its
invoke(...)call sites (esp. the misspelled..._instructiont) - Treating the Anthropic API key field as an auth credential — it is local-only
- Shipping smbCloud
app_secretin the binary and assuming it is confidential - Diverging account features from the sigit-si web account page
- Reaching for SSH credentials /
generate_ssh_keyfor git auth — the live path is Smart HTTP over HTTPS (repos::*), notCred::ssh_key - Using the account access token directly as the git credential — always
exchange it for a short-lived scoped
git_tokenviafetch_git_tokenfirst