Skip to content

fix(output): narrow rows for every column format, not just the three spelled exactly (#353) - #376

Merged
neilmartin83 merged 3 commits into
mainfrom
fix/353-format-narrowing-polarity
Sep 9, 2026
Merged

neilmartin83 merged 3 commits into
mainfrom
fix/353-format-narrowing-polarity

Conversation

@neilmartin83

Copy link
Copy Markdown
Member

Fixes #353.

config list -o Table rendered a different table from config list -o table — the ENVIRONMENT-ID column gone, DEFAULT blanked, and so the scope of every platform profile invisible.

Cause

Three call sites decided whether to narrow their row type with an exact-match switch on the format string, and a default arm returning the wide shape:

site function
internal/commands/config.go listRowsForFormat
internal/commands/protect_helpers.go printResult
internal/scope/scope.go OutputScope

Nothing normalises that string — output.New takes the --output value verbatim and ResolveFormat returns it untouched — while Print has no case for Table and renders a table through its own default arm. So any value outside the three literals took the wide shape to a column renderer.

On config list that reopened the bug the code documents two comments above its own switch: a table's columns are the keys of its first row, EnvironmentID and Default carry omitempty, and configProfileTableRow exists precisely to remove it. An instance profile sorting first therefore hid the scope of every platform profile below it. --wide did not help; it reads rows[0] too.

Fix

Polarity inverted at all three: the narrow shape is the default and the keep-set is named, via a new output.RendersStructureVerbatimjson, yaml, ndjson, xml, raw.

That is correct rather than merely safer: the formatter renders a table for anything it does not recognise, so the narrow shape is the matching one. internal/commands/root.go's isFullDetailFormat already had this polarity and is the precedent.

json-multi is deliberately outside the keep-set. It means JSON on the wire and a table on the screen — multi.go sets it as the capture format and Print has no case for it either — so keeping the wide shape for it would put that shape back on a terminal by way of jamf-cli multi. The generated selectTableColumns excludes it from its own keep-set for the same reason, so the hand-written and generated paths now agree by construction rather than by coincidence.

Tests

Each site is covered against the mis-cased, unrecognised and json-multi values as well as the keep-set, plus output.RendersStructureVerbatim itself in both directions.

Verified against the pre-fix code rather than assumed: restoring OutputScope's old switch alone fails five cases.

Not a credential exposure

configProfileRow declares Token and ClientID, which the narrow type omits, so this looked like it might print credential references. Both are populated only by config show, never by config list. Checked before filing.

Notes

🤖 Generated with Claude Code

neilmartin83 and others added 3 commits September 9, 2026 10:30
…spelled exactly (#353)

`config list -o Table` rendered a different table from `config list -o table`,
dropping the `ENVIRONMENT-ID` column and blanking `DEFAULT`.

Three call sites decided whether to narrow their row type with an exact-match
switch on the format string and a `default` arm returning the wide shape:

  internal/commands/config.go        listRowsForFormat
  internal/commands/protect_helpers.go  printResult
  internal/scope/scope.go            OutputScope

Nothing normalises that string — `output.New` takes the `--output` value
verbatim and `ResolveFormat` returns it untouched — while `Print` has no case
for `Table` and renders a table through its own default arm. So any value
outside the three literals took the wide shape to a column renderer. On
`config list` that reopened the bug the code documents two comments above: a
table's columns are the keys of its *first* row, `EnvironmentID` and `Default`
carry `omitempty`, and `configProfileTableRow` exists precisely to remove it.
An instance profile sorting first therefore hid the scope of every platform
profile below it. `--wide` did not help; it reads `rows[0]` too.

Polarity inverted at all three: the narrow shape is the default and the keep-set
is named, via `output.RendersStructureVerbatim` — json, yaml, ndjson, xml, raw.
That is correct rather than merely safer, because the formatter renders a table
for anything it does not recognise, so the narrow shape is the matching one.
`internal/commands/root.go`'s `isFullDetailFormat` already had this polarity and
is the precedent.

`json-multi` is deliberately outside the keep-set. It means JSON on the wire and
a table on the screen — `multi.go` sets it as the capture format and `Print` has
no case for it — so keeping the wide shape for it would put that shape back on a
terminal by way of `jamf-cli multi`. The generated `selectTableColumns` excludes
it from its own keep-set for the same reason, so the hand-written and generated
paths now agree by construction rather than by coincidence.

Tests cover each site against the mis-cased, unrecognised and json-multi values
as well as the keep-set, and were checked against the pre-fix code — reverting
`OutputScope` alone fails five cases.

Not a credential exposure: `configProfileRow` declares `Token` and `ClientID`,
which the narrow type omits, but both are populated only by `config show`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@neilmartin83
neilmartin83 merged commit b7c2587 into main Sep 9, 2026
1 check passed
@neilmartin83
neilmartin83 deleted the fix/353-format-narrowing-polarity branch September 9, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An unrecognised or mis-cased -o value bypasses per-command row narrowing

2 participants