Prerequisites

This plugin provides backend capabilities only and must be used together with frontend components.

  • DSH version: DSH >= 0.1.5-rc.1 must be installed.
  • Required components: dsh-better-sidebar and dsh-artifacts must be installed first. This plugin does not replace them; it completes the data path.

Core Features

dsh-artifact-index is the missing backend required by the sidebar tab in dsh-artifacts. It runs on DSH’s web server and is responsible for providing the artifact index JSON and file byte streams.

  • Serve index: Returns the artifact list as JSON via GET /report/.
  • Serve files: Returns the binary content of the specified artifact via GET /report/<name>.
  • Zero dependencies: No third-party runtime dependencies, no outbound network calls, and no telemetry.
  • Configurable: Supports configuration of the root directory, maximum item count, per-file size limit, and Content Security Policy (CSP).
  • Security protections: Built-in path security validation, allows loopback access only, and prevents path traversal.

Installation and Enablement

Use the official installation command to add the plugin.

dsh plugin --profile desktop add dsh-artifact-index

After installation, DSH Desktop must be restarted. The plugin and tool lists are snapshots taken at session creation; new plugins are loaded only after a restart.

Verify Installation

After restarting, check the log directory for activation information (usually %APPDATA%\DSH Desktop\logs\dsh-<date>.log on Windows):

[dsh-artifact-index] artifact root = <artifact 目录> (maxItems=500, ...)

If this line does not appear in the logs, check whether dsh.profile.bundles includes dsh-artifact-index, or look for a failed to apply loader entry error.

Because DSH’s web server rejects requests not initiated by a browser, curl cannot be used to verify the routes. To perform an end-to-end check against a real directory, run the script provided in the repository:

node scripts/smoke.mjs <artifact 目录>

Configuration

Configuration is written under the config key of the mount entry in the profile’s cordis.patch.yml, or overridden via environment variables. Precedence is: config > environment variables > defaults.

- id: dsh-artifact-index
  name: 'dsh-artifact-index'
  config:
    root: <artifact 目录>
    maxItems: 500
    maxFileBytes: 26214400
    csp: sandbox
Configuration Default Description
root $DSH_HOME/artifacts Directory to index. Does not recurse; only the current level is scanned.
maxItems 500 Maximum number of returned entries; excess entries are discarded and a warning is logged.
maxFileBytes 26214400 (25 MB) Maximum size per file; larger files return a 413 error.
csp sandbox Content Security Policy. sandbox forbids scripts/forms; sandbox-scripts allows scripts; none is not sent.
trustedHosts [] Additional allowed Host values; use only when DSH is not running on loopback.

The environment variable DSH_ARTIFACT_INDEX_ROOT can be used to override the root configuration.

Interface Contract

GET /report/ (index list)

Returns index data in JSON format. items are sorted by descending mtime; ties are sorted by ascending name.

{
  "count": 2,
  "items": [
    {
      "name": "report.html",
      "url": "/report/report.html",
      "ext": "html",
      "size": 5120,
      "mtime": 1757000000
    },
    {
      "name": "data.json",
      "url": "/report/data.json",
      "ext": "json",
      "size": 2048,
      "mtime": 1756990000
    }
  ]
}

Note:
* The url field is consumed directly by the upstream as the src of an iframe, so it is root-relative and encoded.
* mtime is in seconds.
* The response does not include the mine field (a v0.1 design choice; see below).
* If the directory cannot be read, returns a 200 status code with { count: 0, items: [], error: "..." }.

GET /report/<name> (file bytes)

Returns the binary stream for the specified file. Content-Type is automatically mapped based on the file extension. For HTML/SVG/XML files, a CSP header is included. Only single-segment file names are allowed; subpaths are not accepted.

Design and Limitations

About the mine Field

mine is a field specified by the dsh-artifacts client to mark whether an artifact belongs to the current session. This plugin intentionally does not return this field in v0.1. The reason is that in v0.1, accurately reconstructing session ownership is too complex and can easily produce incorrect results. The current version provides an accurate flat list instead of potentially misleading ownership information.

Security Features

  • Path safety: Request paths are double-validated (string validation + realpath) to prevent symbolic links pointing outside the allowed directory or path traversal.
  • Access control: Only loopback access is allowed. Sec-Fetch-Site: cross-site requests are rejected directly.
  • Operation limits: Only GET/HEAD is supported; there is no write, delete, or authentication functionality.

Summary

dsh-artifact-index resolves the issue where the dsh-artifacts sidebar displays “Could not read the artifact index” due to a missing backend. It is a lightweight middleware that maps the local file system to DSH’s HTTP service, suitable for developers who need to view locally generated reports or documents in the sidebar.