Publish the declared command tree in the catalog, for discovery only
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 0
- Forks
- 3
- Avg merge
- 8h 43m
- Merged PRs (30d)
- 60
Description
Follow-up to #86, which delivered the parsing half: a module declares its command tree, the installer reads it out of the installed executable, and the shell parses a product command line against the local receipt. See PR #150 and ADR 0013.
This is the discovery half, which #86 specified and #150 deliberately left out.
What is missing
The catalog carries no copy of the tree. #86's third decision puts one in the per-namespace version entry, beside the compatibility, capability, and artifact information, never in the index. Nothing publishes it today, so catalog.Version has no commandTree field.
The release pipeline does not extract one. This is smaller than it looks: internal/release/build.go's Build already compiles a module, and cmd/wso2-module-release already calls it per platform. What is missing is running one of those builds to read its declaration, via WSO2_MODULE_COMMAND_TREE, and folding the answer into the catalog entry.
One wrinkle: the pipeline cross-compiles, setting GOOS/GOARCH per platform, so most artifacts it produces it cannot execute. Extraction needs one host-platform build whose only purpose is to be run. The tree itself is platform independent, so one extraction covers every artifact of a version.
No suggestion for a command in a module that is not installed. #86's user story 6: "As a CLI user, I want a suggestion for a command belonging to a module I have not installed, together with how to install it, so that discovery does not require reading the catalog." Today internal/app/app.go:216 reports shell.unknown_command from the local module store alone.
The decision this needs before it starts
Suggesting a command from a module nobody has installed means consulting the catalog at the moment the shell fails to recognise a word. It consults only the local store there now, so this would put a network fetch on the path of every mistyped command — paid by users who are offline, on a slow link, or simply typing badly. #86 does not address it.
The options are to suggest only from a catalog the shell has already fetched (no network on a typo, and a fresh machine gets today's message), or to fetch on any unrecognised word (best suggestions, worst failure mode). Settle this first; it changes the shape of the work.
The boundary this must not cross
The catalog copy is for discovery only. Parsing reads the receipt and nothing else, because the catalog is fetched over the network and is not signed, and a command tree decides how a user's command line is interpreted.
That split is enforced rather than documented, and the enforcement must survive this work:
internal/parsetree.Treekeeps its declaration in an unexported field andFromReceiptis its only constructor, so a catalog-borne tree does not compile at a call site that parses.internal/boundariesasserts both thatinternal/parsetree's whole dependency closure excludesinternal/catalog, and that the single constructor still takes a receipt.
Suggestions for uninstalled modules therefore need a second path to the catalog's copy that is provably not reachable from the parser. Adding a constructor to parsetree is the wrong move and the boundary test will say so.
#86's testing decision also asks for this explicitly: "The trust boundary gets an explicit test: a catalog copy that disagrees with the receipt must not change how a command parses." That test is not yet possible, because there is no catalog copy to disagree.
Also worth deciding
catalog.SchemaVersion has never been bumped and, like the receipt did, fails closed on an exact match. Adding a field to Version needs the same call #86 took for the receipt: whether to bump, and what an older shell does with a catalog it does not recognise.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with #86, PR #150, and ADR 0013, then inspect catalog.Version, internal/release/build.go, cmd/wso2-module-release, and internal/app/app.go:216. Review the internal/boundaries assertions and the existing receipt and catalog schema handling before resolving catalog-fetch and schema-compatibility behavior. Done means discovery can use the catalog copy without making it reachable by parsing, while release extraction and boundary tests cover the stated trust split.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- cli, release, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100