Skip to content

fix: honor catalog release packages instead of repository root - #93

Closed
loopx-agent wants to merge 2 commits into
dshplugin:mainfrom
loopx-agent:codex/catalog-release-artifacts
Closed

loopx-agent wants to merge 2 commits into
dshplugin:mainfrom
loopx-agent:codex/catalog-release-artifacts

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 4, 2026 •

Copy link
Copy Markdown

The live catalog's LoopX entry already supplies a prebuilt GitHub release .tgz in igc. With no npm package, the install button sends owner/repo instead, and the server falls back to repository HEAD. This selects the monorepo root and fails with entry file missing index.js even though the catalog's displayed command names a complete package.

Preserve npm priority, then select a same-repository release target from the existing authoritative catalog command, before the legacy Git fallback. A shared, pure installer parser accepts only a fixed HTTPS github.com/<owner>/<repo>/releases/download/<tag>/<asset>.tgz target; it never executes command text. Cross-repository catalog redirects, foreign hosts, credentials, moving latest URLs, query/fragment data, extra CLI arguments and shell code are rejected.

The HTTP installer preserves the release URL, uses the existing GitHub security setting and proxy path, and probes HTTP rather than a Git clone. Release packages bypass the unrelated repository-HEAD preflight; the existing post-install entry validation remains active. Repository identity is preserved for installed-state readback, deduplication, pinned updates and package-name removal. No new setting or UI control is added. Tracked server/Client artifacts and the new helper declarations are included; rebuilding changes CSS module identifiers without changing styles.

Validation:

  • npm run check passed: client/server/test type checks, 107 tests passed, 2 platform tests skipped, server and Client builds. Run with GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_NOSYSTEM=1; an initial proxy test was affected by local Git URL rewriting and passed with that configuration isolated.
  • Six focused cases cover catalog selection, npm parity, foreign-repository rejection, unsafe inputs, installed identity, preflight isolation and real HTTP permission/deduplication rejection.
  • A real HTTP server using the built Hub backend consumed the current online catalog entry, installed its existing beta.5 package through the native DSH CLI in a disposable profile, verified the entry and installed identity, updated the same pinned URL without @latest, then uninstalled with readback. No npm publication or model call was needed. A browser-mounted Hub interaction was not exercised.

Related repair: loopx-project/loopx#5589 and the repeated distribution incidents linked there. This PR requires upstream review and a Hub release before existing installations adopt the behavior; it does not claim deployment.

Remote CI is currently action_required on the fork pull request (no jobs executed). An upstream maintainer must authorize the workflow before remote CI evidence is available; local checks above are kept separate from that gate.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
@dshplugin

Copy link
Copy Markdown
Owner

Thanks @loopx-agent — this is a real bug, and your diagnosis is spot on. We've fixed it and shipped it.

The fix is released in v1.4.14 and is live on npm, following the same approach you outlined:

  • Catalog entries that name a prebuilt GitHub release .tgz and have no npm package are now a first-class install channel, instead of falling back to a git install of the repository root (which has no entry file and failed with entry file missing index.js).
  • The release target is parsed by a shared, pure helper that accepts only a fixed https://github.com/<owner>/<repo>/releases/download/<tag>/<asset>.tgz target — and only when its repository matches the catalog repository. Cross-repository redirects, foreign hosts, credentials, moving latest URLs, query/fragment data, path traversal, and appended CLI arguments or shell code are rejected. It never executes command text.
  • Release packages skip the repository-HEAD preflight (their package root differs from HEAD), while the post-install entry validation stays in place.
  • Repository identity is preserved for installed-state readback, deduplication and display.

Release notes: https://github.com/dshplugin/dsh-plugin-hub/releases/tag/v1.4.14 — with credit to you for both the report and the reference implementation.

Install it with:

dsh plugin --profile web add dsh-plugin

Thanks again for the detailed write-up and for taking the time to prepare the reference fix.

@dshplugin dshplugin closed this Oct 4, 2026
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.

2 participants