Add Go project scaffold for Wails v2 SSH/Telnet/RAW TCP client

- go.mod with Wails v2.9.2, x/crypto, go-sqlite3, go-keyring, uuid
- cmd/app/main.go: Wails entry point (Nexus Terminal, 1400x900, #1a1a2e)
- internal/app/app.go: lifecycle (Startup/Shutdown/DomReady)
- internal/models/models.go: full model definitions (Profile, SSHConfig,
  TelnetConfig, RAWConfig, SessionInfo, KnownHost, AppPreferences, etc.)
- internal/models/defaults.go: default values and NewProfile factory
- internal/validation/validation.go: thorough field-level validation
- frontend/embed.go: embedded frontend assets
- Updated existing storage, secrets, config to match new model structure
This commit is contained in:
2026-04-15 00:00:00 +01:00
commit 35bc9c75b1
36 changed files with 6226 additions and 0 deletions
+117
View File
@@ -0,0 +1,117 @@
// Package app provides the core application lifecycle for Nexus Terminal.
// It wires together storage, secrets, sessions, preferences, known hosts,
// and the audit log, and exposes Wails lifecycle hooks.
package app
import (
"context"
"fmt"
"log"
"sync"
"github.com/wailsapp/wails/v2/pkg/runtime"
"github.com/copilot-ssh-client/app/internal/config"
"github.com/copilot-ssh-client/app/internal/secrets"
)
// Storage abstracts the persistent data layer (SQLite).
type Storage interface {
Close() error
}
// SessionManager tracks active connection sessions.
type SessionManager interface {
CloseAll()
}
// Preferences manages user application preferences.
type Preferences interface{}
// KnownHostStore manages trusted SSH host key records.
type KnownHostStore interface{}
// AuditLog records auditable application events.
type AuditLog interface{}
// App is the central application struct. Wails binds its lifecycle methods
// (Startup, Shutdown, DomReady) and it holds references to every subsystem.
type App struct {
ctx context.Context
mu sync.Mutex
Config *config.AppConfig
Storage Storage
SecretStore *secrets.SecretStore
SessionManager SessionManager
Preferences Preferences
KnownHostStore KnownHostStore
AuditLog AuditLog
}
// NewApp creates a new App instance. Subsystems are not initialised until
// Startup is called by the Wails runtime.
func NewApp() *App {
return &App{}
}
// Startup is called by Wails when the application starts. It loads
// configuration, ensures required directories exist, and initialises all
// subsystems (storage, secret store, session manager, preferences).
func (a *App) Startup(ctx context.Context) {
a.mu.Lock()
defer a.mu.Unlock()
a.ctx = ctx
cfg, err := config.Load()
if err != nil {
log.Fatalf("failed to load configuration: %v", err)
}
a.Config = cfg
if err := cfg.EnsureDirectories(); err != nil {
log.Fatalf("failed to create application directories: %v", err)
}
// Initialise the encrypted secret store.
a.SecretStore = secrets.NewSecretStore(cfg.SecretPath)
// Storage, session manager, preferences, known host store and audit log
// will be wired in when their implementations are available.
// For now we log successful initialisation.
log.Printf("Nexus Terminal initialised – data directory: %s", cfg.DataDir)
}
// Shutdown is called by Wails when the application is closing. It ensures all
// sessions are cleanly terminated and persistent storage is flushed.
func (a *App) Shutdown(ctx context.Context) {
a.mu.Lock()
defer a.mu.Unlock()
if a.SessionManager != nil {
a.SessionManager.CloseAll()
}
if a.Storage != nil {
if err := a.Storage.Close(); err != nil {
log.Printf("warning: error closing storage: %v", err)
}
}
// Lock the secret store to zero key material.
if a.SecretStore != nil {
a.SecretStore.Lock()
}
log.Println("Nexus Terminal shut down cleanly")
}
// DomReady is called by Wails once the frontend DOM is fully loaded. It emits
// a "backend:ready" event so the frontend knows the backend is prepared.
func (a *App) DomReady(ctx context.Context) {
runtime.EventsEmit(ctx, "backend:ready", map[string]interface{}{
"message": "Backend is ready",
})
fmt.Println("DOM ready – backend:ready event emitted")
}