feat(tui): CRUD foundation (form, state, keys, delete ops) - #20
Open
lvlcn-t wants to merge 2 commits into
Open
Conversation
Foundation for adding create/edit/rename/delete to the TUI, wired per tab in follow-up PRs. No tab emits CRUD actions yet, so the TUI is behaviorally unchanged. - contexts.Manager: add DeleteTenant and DeleteCredential (deletion of an entry still referenced by a context is allowed and left for the caller to warn about); config.Config gains DeleteTenant/DeleteCredential. - tui/form: new reusable multi-field text-input form (focus navigation, required/validator checks, Submitted/Canceled messages), fully unit tested. - tui/state: add FormView and ConfirmView states plus a SetConfig setter to swap the store after a reload. - tui/keys: add Create (n), Edit (e), Rename (r), Delete (ctrl+d) bindings. - tui/tabs: add CRUD TabAction kinds, tabKeys fields, and a Reload() method on every tab to rebuild items from the current store after a write. The contexts.Manager dependency injection and handleAction dispatch land in PR2 alongside the first tab (tenants) that exercises them, keeping this PR free of unused code. Signed-off-by: lvlcn-t <75443136+lvlcn-t@users.noreply.github.com>
|
Minimum allowed coverage is Generated by 🐒 cobertura-action against b59dbe7 |
Replace the storage-shaped Set* verbs with intent-shaped operations so both UIs (cmd, tui) map user intent to one shared service instead of re-deriving CRUD semantics from upsert-by-name. This is the fix for the TUI edit-rename bug: renaming is a distinct operation, not an upsert with a different name. Per entity (tenant, credential, context): - CreateX -> fails with ErrXExists if present (POST). - UpdateX -> fails with ErrXNotFound if absent; never changes the name (PATCH). - RenameX -> the only identity change; cascades the new name to every referencing context across all affected config files (PATCH of identity). Reference integrity lives in the service: RenameTenant/RenameCredential rewrite context tenant/credential references (contexts only ever point at tenants/credentials, never the reverse), grouped by owning file so each file is written once. DeleteTenant/DeleteCredential now report OrphanedContexts so callers can warn (allow-and-warn, as agreed). Set*/SetContext are retained as thin create-or-update shims delegating to Create*/Update*, so the CLI and all existing tests keep working unchanged; the CLI migration onto the intent API is a separate later PR. config gains RenameTenant/RenameCredential, RetargetTenant/RetargetCredential, and ContextsReferencingTenant/Credential, each unit tested. New sentinels (ErrTenantExists/NotFound, etc.) enable errors.Is in callers and tests. Adds intent tests including same-file and cross-file rename cascade and delete orphan reporting; keeps all prior Set*/Delete*/RenameContext tests. Signed-off-by: lvlcn-t <75443136+lvlcn-t@users.noreply.github.com>
This was referenced Jul 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Foundation for adding create/edit/rename/delete to the TUI. This is PR
1 of a stacked series (foundation → tenants → contexts → credentials).
No tab emits CRUD actions yet, so the TUI is behaviorally unchanged;
this PR only lands the plumbing that the per-tab PRs build on.
Contents
contexts.Manager): addDeleteTenantandDeleteCredential(mirroringDeleteContextvia a small shareddeleteEntryhelper).config.ConfiggainsDeleteTenant/DeleteCredential. Deleting a tenant/credential still referenced by acontext is allowed and left for the caller to warn about (agreed
behaviour; the TUI will surface a status-line warning in a later PR).
tui/form(new package): a reusable multi-field text-input form —focus navigation (tab/shift-tab/↑↓), required + custom validators,
Submitted{Values}/Canceled{}messages. Fully unit-tested; knowsnothing about the domain.
tui/state: addFormViewandConfirmViewstates, and aSetConfigsetter to swap the store after a write-triggered reload.tui/keys: addCreate(n),Edit(e),Rename(r),Delete(ctrl+d).ctrl+dchosen k9s-style; verified no collisionwith bubbles/list (which uses plain
d/f/pgdown).tui/tabs: add CRUDTabActionkinds,tabKeysfields, and aReload()method on every tab to rebuild list items from the currentstore after a write.
Deliberately deferred to PR 2
The
contexts.Managerdependency injection into the TUI and thehandleActionCRUD dispatch (plus theConfirmViewmodel and thereload()flow) land in PR 2 alongside the tenants tab, which is thefirst to exercise them. Keeping them out here avoids shipping unused code.
Testing
go test -race -count=1 -short ./...— all pass (newtui/formandcontextsdelete tests included).pre-commit(generate, mod tidy, gofumpt, golangci-lint, gitleaks,markdownlint) — green.
tuiconfirmed to still import neithercmd,login, norcontexts(DI deferred);
contextsandloginremain leaf packages.unaffected.
Notes
Update/Viewidiom trips gocritic'shugeParam; suppressed with//nolint:gocriticand a note that theexisting models (
details.Viewer,splash.Model) already use pointerreceivers and a broader refactor is tracked separately.