test: assert the entity spec table holds together - #3
Merged
Conversation
This repo had no tests at all, so CI's `go test ./...` ran over nothing. The entity table is the right place to start: it is the CLI's entire surface -- registerCRUD turns each spec into a command tree and pull/apply enumerate the same list -- and it is hand-maintained on purpose, since it is not derived from the platform's schema.json. Every failure mode it has is silent. Nothing in the type system objects to a typo'd field type, and both addFieldFlags and collectFields switch on Type without a default, so the field registers no flag and quietly cannot be set. A verb spelled "list" makes hasVerb answer false for every verb the spec meant to allow, and the command goes missing. A duplicated alias is not an error in cobra; one command shadows the other and an entity stops being reachable. A LookupKey naming a field the collection lacks turns every natural-key lookup into an opaque 400. So the tests assert: types are dispatchable, verbs are known and unique, LookupKey names a declared field, select/multiselect carry Values and nothing else does, flags are unique within a spec and do not collide with the flags ls, get, delete and create register themselves or with root.go's persistent ones, required fields only exist where create does, and no command name or alias is claimed twice across the whole table. Plus unit coverage of the helpers that back them -- aliases, flagName, hasVerb, composeOrgFilter, splitFields -- and a short explicit list of the collections that are not org-scoped, which is the one place the CLI's model of platform tenancy is written down. Each check was verified by planting the defect it describes and confirming the failure, then reverting: a passing test that cannot fail is not evidence. composeOrgFilter's parenthesisation is pinned for the same reason it exists -- an OR inside a user's --filter must not escape the org scope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
This repo had no tests at all — CI's
go test ./...ran over nothing. The entity table is the right place to start: it's the CLI's entire surface (registerCRUDbuilds a command tree per spec,pull/applyenumerate the same list), and it's hand-maintained on purpose since it isn't derived from the platform'sschema.json.Every failure mode that table has is silent. Concretely:
addFieldFlagsandcollectFieldsboth switch onTypewithout a default, so a typo'd type registers no flag and the field quietly cannot be set."list"makeshasVerbanswer false for every verb the spec meant to allow — the command just goes missing.LookupKeynaming a field the collection lacks turns every natural-key lookup into an opaque 400.What's asserted
Types are dispatchable · verbs known and unique ·
LookupKeynames a declared field · select/multiselect carryValuesand nothing else does · flags unique within a spec and not colliding with whatls/get/delete/createregister themselves (--filter,--sort,--fields,--yes/-y,--random-password) or with root.go's persistent flags ·Requiredonly wherecreateexists · no command name or alias claimed twice across the whole table · every entity reachable by at leastlsorget.Plus unit coverage of the helpers behind those checks —
aliases,flagName,hasVerb,composeOrgFilter,splitFields— and a short explicit list of the non-org-scoped collections, which is the one place the CLI's model of platform tenancy is written down.These were verified to fail
A passing test that cannot fail isn't evidence, so I planted each defect, confirmed the failure, and reverted:
Type: "strng"on a fieldaddFieldFlags does not dispatch onlocationsgivenPlural: "things"alias "things" is claimed by bothVerbs: ["list", …]unknown verb "list"LookupKey: "host_name"not a declared fieldfieldsthe ls command registers itselfFSelectwithValuesremovedrejects every value passed to itValueson anFStringdeclares Values, which nothing readscomposeOrgFilter's parenthesisation is pinned for the reason it exists: anORinside a user's--filtermust not escape the org scope.Two notes for you rather than for the code:
schema.json— is still open and still needs your call on vendoring vs fetching.platform-docs/docs/stone-cli.md§4 listsnats-accountandnebula-caasls / get, but both specs declarels, get, update, edit. The server rejects tenant writes either way, so it's a docs inaccuracy rather than a hole — say the word and I'll fix that page.🤖 Generated with Claude Code