feat: wire SSH, SFTP, and credential services into Wails app

Add SSHService, SFTPService, and CredentialService to the WraithApp
struct. SSH service uses a no-op output handler (Wails event emission
will be wired at runtime). CredentialService is created lazily after
vault unlock. Both SSH and SFTP services are registered with Wails
in main.go.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-17 07:04:15 -04:00
parent d05639ef4c
commit 8c902876e7
2 changed files with 30 additions and 0 deletions

View File

@ -9,10 +9,13 @@ import (
"path/filepath"
"github.com/vstockwell/wraith/internal/connections"
"github.com/vstockwell/wraith/internal/credentials"
"github.com/vstockwell/wraith/internal/db"
"github.com/vstockwell/wraith/internal/plugin"
"github.com/vstockwell/wraith/internal/session"
"github.com/vstockwell/wraith/internal/settings"
"github.com/vstockwell/wraith/internal/sftp"
"github.com/vstockwell/wraith/internal/ssh"
"github.com/vstockwell/wraith/internal/theme"
"github.com/vstockwell/wraith/internal/vault"
)
@ -27,6 +30,9 @@ type WraithApp struct {
Themes *theme.ThemeService
Sessions *session.Manager
Plugins *plugin.Registry
SSH *ssh.SSHService
SFTP *sftp.SFTPService
Credentials *credentials.CredentialService
unlocked bool
}
@ -52,6 +58,17 @@ func New() (*WraithApp, error) {
sessionMgr := session.NewManager()
pluginReg := plugin.NewRegistry()
// No-op output handler — Wails event emission will be wired at runtime.
sshSvc := ssh.NewSSHService(database, func(sessionID string, data []byte) {
// TODO: Emit Wails event "ssh:output" with sessionID + data
_ = sessionID
_ = data
})
sftpSvc := sftp.NewSFTPService()
// CredentialService requires the vault to be unlocked, so it starts nil.
// It is created lazily after the vault is unlocked via initCredentials().
// Seed built-in themes on every startup (INSERT OR IGNORE keeps it idempotent)
if err := themeSvc.SeedBuiltins(); err != nil {
slog.Warn("failed to seed themes", "error", err)
@ -64,6 +81,8 @@ func New() (*WraithApp, error) {
Themes: themeSvc,
Sessions: sessionMgr,
Plugins: pluginReg,
SSH: sshSvc,
SFTP: sftpSvc,
}, nil
}
@ -121,6 +140,7 @@ func (a *WraithApp) CreateVault(password string) error {
}
a.unlocked = true
a.initCredentials()
slog.Info("vault created successfully")
return nil
}
@ -157,6 +177,7 @@ func (a *WraithApp) Unlock(password string) error {
a.Vault = vs
a.unlocked = true
a.initCredentials()
slog.Info("vault unlocked successfully")
return nil
}
@ -165,3 +186,10 @@ func (a *WraithApp) Unlock(password string) error {
func (a *WraithApp) IsUnlocked() bool {
return a.unlocked
}
// initCredentials creates the CredentialService after the vault is unlocked.
func (a *WraithApp) initCredentials() {
if a.Vault != nil {
a.Credentials = credentials.NewCredentialService(a.db, a.Vault)
}
}

View File

@ -31,6 +31,8 @@ func main() {
application.NewService(wraith.Connections),
application.NewService(wraith.Themes),
application.NewService(wraith.Settings),
application.NewService(wraith.SSH),
application.NewService(wraith.SFTP),
},
Assets: application.AssetOptions{
Handler: application.BundledAssetFileServer(assets),