Unified architecture: workspace rename, dual-mode, shared store #85
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
localvsteam) with local auth bypass for desktop appnebi loginfrom CLI is visible in desktop and vice versaKey Design Decisions
1. Environment to Workspace Rename
All models, handlers, API routes, frontend types/pages renamed from "environment" to "workspace." API routes changed from
/environmentsto/workspaces, RBAC resource prefix fromenv:tows:. Straightforward but touched ~110 files.2. Single-Server Model (vs Multi-Server)
Each CLI/desktop instance connects to one server at a time.
Previously the workspace model had
Origins map[string]*Originkeyed by server name. Now it uses flat fields:OriginName,OriginTag,OriginAction,OriginTomlHash,OriginLockHash. This eliminated the-s <server>flag from all CLI commands and simplified the mental model to match npm/docker (one registry at a time) rather than git's multi-remote approach.nebi login <url>sets the server and authenticates in one step.3. Dual-Mode Operation: Local vs Team
Single codebase with
NEBI_MODEenvironment variable (localorteam, defaultteam)./api/v1/remote/*registeredThe frontend fetches mode from
GET /api/v1/versionand adapts (skip login page, hide admin nav, etc.).4. Local Auth Bypass
In local mode,
LocalAuthenticatorfinds the first user in DB and injects it into every request context -- no token validation, no password checks. Login returns a mock token"local-mode". Single-user desktop app doesn't need authentication overhead.5. JSON Files to SQLite/GORM for CLI State
Migrated CLI local storage from JSON files to SQLite via GORM.
Before:
~/.local/share/nebi/index.json(workspace registry) +~/.config/nebi/credentials.json(auth tokens per server), manually serialized.After: Single
~/.local/share/nebi/nebi.dbwith GORM auto-migration, WAL mode, and tables:workspaces,store_config(singleton, ID=1),store_credentials(singleton, ID=1). Gets ACID guarantees and eliminates race conditions.6. Shared Database Between CLI and Desktop
CLI and desktop app read/write the same
nebi.dbfile using the samestore_configandstore_credentialstables.Platform paths:
~/.local/share/nebi/nebi.db~/Library/Application Support/nebi/nebi.db%APPDATA%\nebi\nebi.dbThis means
nebi loginfrom CLI shows up in the desktop app and vice versa. TheRemoteServermodel was removed in favor of the shared singleton tables.7. Remote Server Proxy (Local Mode Only)
Desktop app includes an API proxy (
/api/v1/remote/*) so the frontend can browse a remote team server without the CLI. The handler usescliclient.Clientunder the hood -- same HTTP client the CLI uses. Read-only: list workspaces, get versions/tags/manifests. Push/publish requires the CLI.8. Shared Core Libraries Across CLI, REST Server, and Desktop
The CLI (
cmd/nebi/), the REST API server (internal/api/), and the desktop app (app.go) all consume the same internal packages rather than having separate implementations:internal/models/-- shared data models (Workspace, Job, User, etc.)internal/store/-- GORM-based local state (config, credentials, workspace tracking). Used by CLI commands directly, and by the desktop REST server's remote handlers.internal/cliclient/-- HTTP client for talking to remote Nebi servers. Used by CLI commands (nebi push,nebi pull, etc.) and by the desktop's remote proxy handlers to forward requests.This means a change to a model or store method is automatically picked up by all three consumers. Previously the CLI had its own JSON-based storage (
internal/localstore/) separate from the server's GORM models, which led to drift (e.g., credentials stored in different tables).9. Workspace Source Tracking
Sourcefield on workspace model distinguishes"local"(created vianebi initin a directory) from"managed"(created via desktop UI/API). Helps the system understand workspace provenance.Test plan
go vet ./...passesgo test ./internal/store/... ./cmd/nebi/...passescd frontend && npx tsc --noEmit && npm run buildpassesnebi loginvisible in desktop Settings)nebi login <url>visible in desktop Settings page