mcp-data-platform-v1.67.2
What's fixed
Persona editor blanked on the Connections tab
Switching to the Connections scope in the persona editor crashed the page with Cannot read properties of null (reading 'length'). The gateway toolkit returns a nil []string from Tools() when it has no live upstream connections; the admin /connections endpoint serialized that nil as "tools": null, and the UI dereferenced c.tools.length directly on the wire value.
The fix has two layers: the persona editor now defends with c.tools?.length ?? 0 so a contract violation cannot crash the page, and the backend connectionInfo type now has a MarshalJSON that normalizes Tools and HiddenTools to [] at serialization time. The wire contract is now enforced on the type itself, so any future handler that builds a connectionInfo literal cannot regress the invariant.
Same crash class fixed in adjacent persona endpoints
Reviewing the connections fix surfaced the identical pattern in listPersonas and getPersona:
- A YAML persona without a
roles:key produced"roles": null.RolesPageiteratesp.rolesandPersonasPanelreadsp.roles.length, both without guards, so the persona list page would crash for any such persona. getPersonashippedpersonaDetail.{Roles, AllowTools, DenyTools, Tools}with the same shape: declared[]stringwithoutomitempty, no normalization between the in-memory persona and the response.
Both response types now have a MarshalJSON that normalizes the required-non-null arrays. AllowConnections / DenyConnections retain omitempty and stay absent rather than null.
Audit page dropdowns hardened against stale caches
AuditLogPage had filters?.users.map(...) and filters?.tools.map(...), where the optional chain only guarded filters, not the inner array. The backend already normalizes these today, so this was not a live crash, but a stale react-query cache from a pre-fix server would crash the page. Both calls now use filters?.users?.map / filters?.tools?.map, matching the sibling toolkit_kinds and sources accessors.
Responsive persona editor layout
The persona editor now stacks the identity rail and the permissions area into a single flowing column below the lg breakpoint, with the parent panel handling page scroll. The three-pane bounded layout (identity / center explorer / trace) activates at lg+ widths.
Files changed in this release
| File | Change |
|---|---|
pkg/admin/system.go |
connectionInfo.MarshalJSON normalizes Tools and HiddenTools |
pkg/admin/system_test.go |
Regression test asserting "tools":[] and "hidden_tools":[] on the wire when Tools() returns nil |
pkg/admin/persona_handler.go |
personaSummary.MarshalJSON and personaDetail.MarshalJSON normalize the required-non-null arrays |
pkg/admin/persona_handler_test.go |
Two new subtests covering listPersonas (nil Roles) and getPersona (nil Roles / AllowTools / DenyTools / Tools) |
ui/src/pages/audit/AuditLogPage.tsx |
Defensive guards on filters?.users?.map / filters?.tools?.map |
ui/src/pages/settings/PersonaEditor.tsx |
Defensive c.tools?.length ?? 0 in the connections items memo; responsive stacking below lg |
Upgrade impact
No breaking changes. The wire contract for /api/v1/admin/connections, /api/v1/admin/personas, and /api/v1/admin/personas/{name} is unchanged for clients that already tolerated empty arrays; the only behavior change is that fields previously emitted as null for the nil case now emit []. The TypeScript type definitions in the UI already declared these fields as string[], so this brings the runtime in line with the documented contract.
Changelog
Bug Fixes
- d3d9724: fix(admin): unblock persona editor connections tab and lock null-array wire invariant (#482) (@cjimti)
Installation
Homebrew (macOS)
brew install txn2/tap/mcp-data-platformClaude Code CLI
claude mcp add mcp-data-platform -- mcp-data-platformDocker
docker pull ghcr.io/txn2/mcp-data-platform:v1.67.2Verification
All release artifacts are signed with Cosign. Verify with:
cosign verify-blob --bundle mcp-data-platform_1.67.2_linux_amd64.tar.gz.sigstore.json \
mcp-data-platform_1.67.2_linux_amd64.tar.gz