diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 58fd978..964ec6f 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "JFrog Platform plugins for Cursor", - "version": "0.5.4", + "version": "0.5.5", "pluginRoot": "plugins" }, "plugins": [ diff --git a/plugins/jfrog/.cursor-plugin/plugin.json b/plugins/jfrog/.cursor-plugin/plugin.json index e24c846..5752f7e 100644 --- a/plugins/jfrog/.cursor-plugin/plugin.json +++ b/plugins/jfrog/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "jfrog", "displayName": "JFrog Platform", - "version": "0.5.4", + "version": "0.5.5", "description": "JFrog Platform integration with MCP, security skills, supply-chain best practices, and JFrog Agent Guard governance for adding, removing, and listing MCP servers.", "author": { "name": "JFrog", diff --git a/plugins/jfrog/skills/jfrog-ai-catalog-skills/SKILL.md b/plugins/jfrog/skills/jfrog-ai-catalog-skills/SKILL.md new file mode 100644 index 0000000..ed273b1 --- /dev/null +++ b/plugins/jfrog/skills/jfrog-ai-catalog-skills/SKILL.md @@ -0,0 +1,105 @@ +--- +name: jfrog-ai-catalog-skills +description: >- + Discover, install, manage, and publish agent skills hosted in the JFrog AI + Catalog (Artifactory skills repositories) using the JFrog CLI (`jf skills`) + and the JFrog Agent Guard. Lists and searches available skills (catalog-wide + or scoped to a project), shows a skill's versions and which repos host it, + installs the latest or a pinned version, verifies the install, lists + installed skills, updates and removes them, and publishes (uploads) a local + skill bundle and releases new versions. + Use when the user asks what skills are available or installed, to + search/browse the catalog, to install/update/uninstall a skill, to see a + skill's versions, or to publish/upload/release a skill to JFrog / + Artifactory / the AI Catalog. +metadata: + role: workflow +--- + +# JFrog AI Catalog Skills + +Discover, install, and manage agent skills from the JFrog AI Catalog +(Artifactory skills repositories), and publish your own skills back to it, all +through the JFrog CLI (`jf skills`) and the JFrog Agent Guard. + +## Choose a reference file + +Pick the row matching the user's intent and read that reference file. + +| Intent | Read | +|--------|------| +| "What skills are available?" / browse the catalog / list versions / search by name | [references/discovering-skills.md](references/discovering-skills.md) | +| Install or update a skill (latest or a pinned version), or a download is blocked | [references/installing-skills.md](references/installing-skills.md) | +| "What's installed?" / remove an installed skill | [references/managing-installed-skills.md](references/managing-installed-skills.md) | +| Publish / upload / release a skill to the catalog | [references/publishing-skills.md](references/publishing-skills.md) | + +## Prerequisites + +- **Read the base `jfrog` skill first.** [`../jfrog/SKILL.md`](../jfrog/SKILL.md) + owns the shared guards this skill depends on, so this skill does **not** repeat + them — follow them there: + - The [environment check](../jfrog/SKILL.md#environment-check) — confirm `jf` + is installed before the first `jf` call, and install it if missing. + - The [server selection rules](../jfrog/SKILL.md#server-selection-rules-mandatory) + — resolve the default `` once and reuse it, pass `--server-id ` + after the subcommand on every `jf` call, and use one server per request. + - The stop-on-error rule — on any `jf` failure, stop and never switch servers. + + One addition specific to this skill: never `cat` or parse + `~/.jfrog/jfrog-cli.conf.v6` (it can hold access tokens); list servers only + with `jf config show`, which redacts secrets. +- **Agent Guard registry.** Catalog discovery and repo provisioning run through + `npx --yes @jfrog/agent-guard`. `` is the npm registry that + provides the `@jfrog/agent-guard` package itself: use `JFROG_AGENT_GUARD_REPO` + if set, otherwise + `https://releases.jfrog.io/artifactory/api/npm/coding-agents-npm/`. Pass the + same `` to Agent Guard as `--server ""` so it targets the same server + as your `jf` calls. Agent Guard also reads `JFROG_URL` / `JF_URL` directly when + set, so make sure the `` you resolved points at that same host. +- **Resolve the project (``) only when needed, and always to a key.** + `` must be the JFrog **project key**, not the display name. It is + required for `--list-skills`, `--list-skill-versions`, and + `--provision-skills-repository`. Take the value from `JF_PROJECT` or the user, + then resolve it to a key against the projects list (see *List all projects* in + the base `jfrog` skill's [`references/projects-api.md`](../jfrog/references/projects-api.md)): + ```bash + jf api '/access/api/v1/projects' --server-id "" \ + | jq -r '.[] | select(.project_key=="" or .display_name=="") | .project_key' + ``` + Use the printed key. If it prints nothing, ask the user for the key. Never + assume `default`, never invent one. Install, update, remove, and publishing to + an explicit `--repo` are keyed by skill **name** and/or **repo**, not a + project. + +## Workflow overview + +```mermaid +flowchart TD + A[User request] --> B{jf CLI installed?} + B -->|No| C[Ask user to install jf CLI, then continue] + B -->|Yes| D{Intent} + C --> D + D -->|List all / versions| E[npx @jfrog/agent-guard --list-skills] + D -->|Install / update| F[Resolve slug + version, then jf skills install/update] + D -->|List installed / remove| G[jf skills list / rm -rf install dir] + D -->|Publish| H[Resolve/provision repo, validate bundle, jf skills publish] +``` + +## Gotchas + +Catalog-specific rules only. The shared `jf` guards — single server per request, +stop-on-error, and cautious mutation — live in the base +[`jfrog` skill](../jfrog/SKILL.md); follow those too. Flow-specific rules live in +the reference files above. + +- **Which operations mutate**: install and list are read-mostly; remove, registry + delete, and publish mutate state — the base skill's cautious-mutation rule + applies to those three. +- **Session pickup**: installs, updates, and removals usually take effect only at + the next agent session start, so tell the user to restart. +- **Don't leak the plumbing**: present skills/versions/repos to the user, never + the `npx`/Agent Guard commands, `--registry`, flags, or cursors. Run follow-ups + yourself. +- **Use the response templates verbatim**: where a reference file gives a "reply + using this exact template" block, fill the placeholders and send exactly that, + with the same wording every time and no extra preamble or commentary. diff --git a/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/discovering-skills.md b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/discovering-skills.md new file mode 100644 index 0000000..60d2f82 --- /dev/null +++ b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/discovering-skills.md @@ -0,0 +1,83 @@ +# Discovering skills + +List-all and versions go through the **Agent Guard**. + +## List skills (page through the catalog) + +```bash +npx --yes --registry @jfrog/agent-guard \ + --list-skills --project "" [--name ] [--server ""] [--page-size ] [--cursor ] [--format json] +``` + +| Flag | Required | Purpose | +|------|----------|---------| +| `--project ` | **Yes** | AI Catalog project to list. | +| `--name ` | No | Find skills by name: server-side, case-insensitive substring, scoped to the project. | +| `--server ` | No | jf CLI config entry to authenticate with (defaults to the resolved single server). | +| `--page-size ` | No | Results per page. Pass `50` to stay bounded. The Agent Guard defaults to 500 if omitted. | +| `--cursor ` | No | Continuation cursor from a previous page's JSON, to fetch the next page. | +| `--format json` | No | Raw page JSON instead of the default compact TSV (name + last-updated). | + +Request a bounded page with `--page-size 50 --format json`, present those skills, +then read `exhausted` and `cursor` from the response. If `exhausted` is `false` +there are more. Tell the user and offer to fetch the next page with +`--cursor `. Do not silently page through the whole catalog. + +**Presenting results (use this exact format).** Render the skills as this table, +sorted by name, and nothing else (no commands, URLs, flags, or cursors): + +| Skill | Last updated | +|-------|-------------| +| `` | `` | + +For a `--name` search with no matches, reply with one line instead: + +> No skills match "``". + +To offer a follow-up (a skill's versions or repos), ask in plain language +("want the versions for one of these?") and run the command yourself. + +## List a repo's skills + +To see what is published in one specific skills repository (for example, to check +a repo before or after publishing to it), list it directly with the CLI. This is +repo-scoped (Artifactory registry contents), unlike `--list-skills`, which is +project-scoped: + +```bash +jf skills list --repo "" --server-id "" --format json +``` + +Never run a bare `jf skills list` (it errors): always pass `--repo ` here, or +`--harness ` for installed skills (see `managing-installed-skills.md`). + +**Presenting results (use this exact format).** Render the skills as this table, +sorted by name, and nothing else (no commands, URLs, or flags): + +Skills in ``: + +| Skill | Version | Description | +|-------|---------|-------------| +| `` | `` | `` | + +Include the **Description** column only when the listing provides one (drop it if +every skill's description is empty). If the repo holds no skills, reply with one +line instead: + +> No skills published in ``. + +## A skill's versions and hosting repos + +```bash +npx --yes --registry @jfrog/agent-guard \ + --list-skill-versions --project "" --skill "" [--server ""] [--page-size ] [--cursor ] [--format json] +# JSON: versions[].version, versions[].locations[].repoKey (page through with cursor like above) +``` + +**Presenting versions (use this exact format).** Newest version first: + +Versions of ``: + +| Version | Hosted in | +|---------|-----------| +| `` | ``[, ``…] | diff --git a/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/installing-skills.md b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/installing-skills.md new file mode 100644 index 0000000..d591aee --- /dev/null +++ b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/installing-skills.md @@ -0,0 +1,177 @@ +# Installing and updating skills + +Install and update both download from the registry, so they share the same +`--repo`/`--quiet` rules, blocked-download (403 / Xray) handling, and +verify-landed check. + +## Contents + +- When evidence verification fails +- Handling a blocked download (403 / Xray-gated) +- Verify the install landed +- Update an installed skill + +Install by **slug** (the registry `slug`/`name`, never a display name). Latest +version is used by default, and the user may pass an explicit version. +**The `jf skills install` command takes no project.** Resolving which repo hosts +the slug uses `--list-skill-versions` (below), which does require `--project`, so +resolve it (from `JF_PROJECT`, else ask the user) before that lookup. + +```bash +jf skills install "" \ + --server-id "" \ + --version "latest" \ + --repo "" \ + --harness "" \ + --quiet +``` + +If the download returns **HTTP 403**, the archive is Xray-gated, not a +permissions or "not found" problem. See *Handling a blocked download +(403 / Xray-gated)* below. + +**Always pass `--quiet`.** `jf skills install`/`update` opens an interactive +prompt by default, and an agent's shell has no TTY, so without `--quiet` the +prompt fails (it can abort with `panic: device not configured`). `--quiet` also +defaults to `$CI`, so exporting `CI=true` has the same effect if the flag is ever +unavailable. Run non-interactively and resolve every choice (`--repo`, target) +up front. + +**Resolve `` from the host you are running in. Never take it from your +model name, and never hardcode it.** Get the valid names from the CLI: run +`jf skills list --harness '?'` to print the +`Supported agents:` table, then install into the row for your host. Identify the +host from its environment. For example, `CURSOR_*` → `cursor`, +`CLAUDECODE` → `claude-code`, VS Code / GitHub Copilot → `github-copilot`. If +nothing identifies the host, ask the user. Never assume. + +Choose exactly one install target (these are mutually exclusive): + +| Flag | Installs into | +|------|---------------| +| `--harness ` | The current agent's resolved skills dir (resolve per above, e.g. `cursor`, `claude-code`). | +| `--global` | Each agent's global directory from config. | +| `--project-dir ` | Project root combined with the agent's project path. | +| `--path ` | Direct: files go under `/`. | + +**Always resolve and pass `--repo`.** When the platform has more than one skills +repository (the common case), `jf skills install` errors with `multiple skills +repositories found … specify --repo` if you omit it, even when the skill lives +in only one repo. So **the first install step is always** to look up where the +slug is hosted with the Agent Guard: + +```bash +npx --yes --registry @jfrog/agent-guard \ + --list-skill-versions --project "" --skill "" [--server ""] --format json +# read versions[].version and versions[].locations[].repoKey +``` + +**Resolve the repo and version only via `--list-skill-versions`.** The catalog +listing (`--list-skills`, even with `--name`) returns just names, not repos or +versions, so use the versions call above to pick the repo, never a name listing. + +- **One repo hosts the slug.** Use it as `--repo ` directly. Don't ask. +- **Multiple repos host the slug.** Do not pick silently. Naming a project is not + a repo choice, so ask even when one repo is project-scoped. List the repos (and + the version each holds), ask the user which to install from, then pass + `--repo `. The newest version may only exist in one of them, so + surface that to avoid giving the user a stale version. + +## When evidence verification fails + +If install fails with `evidence verification failed … no evidence found`, the +skill has **no signed evidence/attestation** (proof it's genuine and scanned). +This is a security control. **Do not silently bypass it.** Stop and ask using +**this exact template**: + +> `@` has no signed evidence (proof it is genuine and scanned). +> Installing it skips that security check. Do you want to install it anyway? + +Only if the user explicitly agrees, re-run with +`JFROG_SKILLS_DISABLE_QUIET_FAILURE=true`. Never set that flag on your own. + +## Handling a blocked download (403 / Xray-gated) + +A `jf skills install`/`update` download can return **HTTP 403** even when the +slug, version, and repo are all correct, because the skill archive is gated by Xray +and Artifactory will not serve it until the scan resolves. Do **not** report +this as a permissions or "not found" problem. Query the skill's Xray status to +find out why (the path is the archive `//-.zip`, +URL-encoded): + +```bash +jf api --server-id "" \ + '/artifactory/api/skills//xrayStatus?path=%2F%2F-.zip' +``` + +Interpret the `status` field in the response: + +- **`SCAN_IN_PROGRESS`.** Xray is still scanning the archive. The download is + temporarily gated, not blocked. **Do not retry in a tight loop.** Reply using + **this exact template**: + + > `@` is still being scanned by Xray and isn't available to + > download yet. I can retry in a moment if you'd like. + + If it stays `SCAN_IN_PROGRESS` after a couple of polls, switch to **this exact + template** instead: + + > `@` is still being scanned by Xray and is taking longer than + > expected. Try again later, or check with your JFrog administrator if it never + > clears. +- **Blocked by a policy** (a blocked/violating status, with the offending + policy in the response body). The skill is **blocked by an Xray policy**. + Stop. Do not retry. Reply using **this exact template**, filling the + placeholders: + + > `@` is **blocked by the Xray policy ``** and + > cannot be installed. Contact your JFrog administrator to review or resolve + > the policy. +- **Any other status, or a non-zero `jf api` exit** (`jf api` signals a non-2xx + response via its exit code plus a stderr `[Warn] … returned NNN` line — see the + base `jfrog` skill's *CLI and `jf api`* gotchas). Treat as an operational + failure (auth, endpoint disabled): the deliberate **free-form** case — report + the CLI error verbatim (no template), but still strip the `Trace ID`. + +## Verify the install landed + +After install, confirm the `SKILL.md` exists at the resolved install location +before reporting success: + +```bash +test -f "//SKILL.md" && echo "installed" || echo "MISSING SKILL.md" +``` + +If the file is missing, report the failure. Do not claim success. + +On success, reply using **this exact template**: + +> Installed `@` from `` into ``. +> Restart your agent session to load it. + +## Update an installed skill + +To upgrade an installed skill to a newer version, use the CLI (it re-downloads +and reinstalls in place): + +```bash +jf skills update "" --server-id "" --harness "" --version "latest" --quiet +# Preview without touching Artifactory: +jf skills update "" --server-id "" --harness "" --dry-run +# Reinstall even if already at the target version: +jf skills update "" --server-id "" --harness "" --force --quiet +``` + +Use the same install-target flag (`--harness`/`--global`/`--project-dir`/ +`--path`) the skill was installed with. After updating, re-verify the `SKILL.md` +(see *Verify the install landed* above). If the update download 403s, handle it +as in *Handling a blocked download* above. + +On success, reply using **this exact template**: + +> Updated `` to `` (``). +> Restart your agent session to load it. + +If the skill was already current: + +> `` is already at the latest version (``). Nothing to update. diff --git a/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/managing-installed-skills.md b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/managing-installed-skills.md new file mode 100644 index 0000000..026c683 --- /dev/null +++ b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/managing-installed-skills.md @@ -0,0 +1,61 @@ +# Managing installed skills + +## List currently installed skills + +A skill can be installed in two separate places: the **project/harness** location +and the **global** location. For a full inventory, always run **both** lists and +present the union, not just the first: + +```bash +# Project/harness install (the default target) +jf skills list --server-id "" --harness "" --format json +# Global install (a separate location, always check it too) +jf skills list --server-id "" --harness "" --global --format json +# Add --check-updates to compare installed versions against the registry +jf skills list --server-id "" --harness "" --check-updates +``` + +Resolve `` to the current agent (see `installing-skills.md`). +**Never run a bare `jf skills list`** because it errors. Always pass +`--harness ` (installed skills) or `--repo ` (registry contents). +`--check-updates` is only supported with `--harness` (not with `--repo`). Merge +the project and global results and drop duplicates before presenting. This lists +only skills installed from the AI Catalog with `jf skills install`, not +plugin-bundled or built-in agent skills. + +**Presenting installed skills (use this exact format):** + +Installed skills (``): + +| Skill | Version | Description | +|-------|---------|-------------| +| `` | `` | `` | + +Include the **Description** column only when the listing provides one (drop it if +every skill's description is empty). With `--check-updates`, add an **Update to** +column (``, or `-` when the skill is already current). To upgrade a +skill, see *Update an installed skill* in `installing-skills.md`. + +## Remove a skill + +"Remove" defaults to removing the **locally installed** skill. There is no +`jf skills uninstall`. Delete the installed skill directory after confirming it +exists: + +```bash +if [ -d "/" ]; then + rm -rf "/" +else + echo "Not installed, nothing to remove" +fi +``` + +**Confirm before deleting.** Show exactly what will be removed using **this exact +template** and wait for an explicit "yes": + +> Removing skill `` deletes its local install from ``. Do you want to remove it? + +On success, reply using **this exact template**: + +> Removed `` from ``. +> Restart your agent session for the removal to take effect. diff --git a/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/publishing-skills.md b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/publishing-skills.md new file mode 100644 index 0000000..9cb4933 --- /dev/null +++ b/plugins/jfrog/skills/jfrog-ai-catalog-skills/references/publishing-skills.md @@ -0,0 +1,229 @@ +# Publishing a skill + +Publishing is mutating, so **always confirm the target repository and the skill +name with the user before publishing**. Resolve the repo and read the name from +the bundle, then show both and wait for an explicit "yes". Never publish on the +initial request alone, and never auto-pick a repo without surfacing it first. + +## Contents + +- Resolve the target repository +- Validate the bundle +- Sign the skill (evidence) +- Publish +- Report the publish result + +## Resolve the target repository + +Publish targets an Artifactory **repository** (`--repo`), not a JFrog project, +and there is no `--project` flag on `jf skills publish`. Resolve `` in this +order: + +1. **User named a repo up front.** Use it directly as `` and skip + provisioning. An explicit user-named repo always wins. + +2. **No repo given. Provision the project's skills repository.** Use Agent + Guard to create (or resolve, if it already exists) the project's local skills + repo, then publish to the returned key. This needs `` (resolve it per + *Prerequisites* in `../SKILL.md`, asking only if it is unknown): + +```bash +npx --yes --registry @jfrog/agent-guard \ + --provision-skills-repository --project "" [--server ""] [--format json] +``` + + It prints the bare repo key (or `{"repoKey":""}` with `--format json`). + Use that as ``, then **show the user the provisioned repo and the skill + name and wait for confirmation** before publishing (see *Confirm before + publishing*). Do not publish to it silently. + +3. **Provisioning failed. Stop and ask the user which repo to use.** Do not + retry in a loop. Publishing is mutating, so you must get an explicit repo from + the user here. This is the one case where you do ask before publishing. + + First list the existing skills repos: + +```bash +jf api '/artifactory/api/repositories?packageType=skills&type=local' \ + --server-id "" 2>/dev/null | jq -r '.[].key' +``` + + Then **wait for the user to pick one** (by name). If the command printed one or + more repos, reply in **this exact format**, sorted by name, one row per key, and + nothing else: + + Provisioning a skills repository for project `` on `` failed, so + pick an existing repository to publish `` to: + + | Repository | + |------------| + | `` | + + If the command printed nothing (no skills repos on the server), reply with one + line instead, filling `` with the provisioning error: + + > No skills repositories on `` to publish to (provisioning failed: ``). Tell me a repository to use, or ask me to retry. + + **Never auto-select a repo, even if one exists whose name matches the + project.** A name match is not consent. Do not publish to any repo the user did + not explicitly choose. Never guess a repo. + +## Validate the bundle + +The publish argument is the **path to the folder containing `SKILL.md`** (not +the `SKILL.md` file itself). Before publishing: + +```bash +test -f "/SKILL.md" || echo "No SKILL.md at , not a skill bundle" +``` + +Confirm the `SKILL.md` has valid YAML frontmatter with at least a `name` and +`description`. If the bundle is missing `SKILL.md` or the frontmatter is +malformed, do not publish and reply using **this exact template** (no extra +prose), filling `` with the specific issue found: + + > `` is not a publishable skill bundle: ``. Point me at the + > folder that contains `SKILL.md` and I'll retry. + +## Sign the skill (evidence) + +Signing attaches a cryptographic attestation so the skill **installs without an +evidence-verification warning** (see *When evidence verification fails* in +`installing-skills.md`). It is **opt-in**. Never generate keys or sign silently, +and never echo, print, or hardcode the key path or its contents. + +**Ask the user how to sign before doing anything else.** Do **not** inspect, echo, +or probe the signing environment variables up front. Only look at them if the user +picks the environment option below. Use the table below as your own reference. Do +not paste it into the chat. Ask the user to pick one option, **prefer signing**, +and keep **publish unsigned** last: + +| Option | What it needs | When to use | +|--------|---------------|-------------| +| **Provide an existing key** | a **PEM private key path** + **key alias** (its public key already trusted), passed as `--signing-key`/`--key-alias` | the user already has a key | +| **Read from the environment** | `EVD_SIGNING_KEY_PATH` (PEM private key path) + `EVD_KEY_ALIAS` (trusted alias) already exported, picked up with no flags | a signer is already configured in the shell/CI | +| **Generate one now** | run `jf evd gen-keys` (needs **admin** to upload the public key) | no signer exists yet, user runs it or asks you to | +| **Publish unsigned** | nothing | installers hit the evidence warning, least preferred | + +**Ask for the key in the same prompt.** Let the user give the PEM private key path +and key alias in that answer, so **Provide an existing key** needs no follow-up. +Ask again only if they picked it but left the path or alias blank. + +For **Read from the environment**, check both vars are set. If either is missing, +ask the user to export both and retry instead of failing the publish. + +Precedence: an explicit `--signing-key`/`--key-alias` wins. Without it, +`jf skills publish` falls back to `EVD_SIGNING_KEY_PATH`/`EVD_KEY_ALIAS`. With +neither, the publish is unsigned. + +To generate a key pair and register its public key in one step: + +```bash +jf evd gen-keys --key-alias "" \ + --key-file-path "" --server-id "" +# writes /evidence.key (private) + /evidence.pub, uploads the +# public key as a trusted key under +``` + +The key must be a **PEM private key**. Despite `--help` saying "PGP", an armored +PGP key fails with `failed to decode the data as PEM block`. `jf evd gen-keys` +produces the right format. + +## Confirm before publishing + +Once `` is resolved and the bundle validated, **show the user what will be +published and wait for an explicit confirmation**. Reply using this exact +template and do not run `jf skills publish` until the user agrees: + + > Publishing skill `` uploads it to repository `` on server ``. Do you want to publish it? + +If the user says no or names a different repo/name, use that instead and confirm +again. Only proceed to *Publish* after an explicit "yes". + +## Publish + +Publish to the resolved ``. The version is optional. Only pass `--version` +when the user gives an explicit semver, and do not ask the user for a version. Pass `--signing-key`/`--key-alias` only when signing with an +explicit key the user provided or generated. Omit them when relying on +`EVD_SIGNING_KEY_PATH`/`EVD_KEY_ALIAS` from the environment, or when publishing +unsigned. + +```bash +jf skills publish "" \ + --server-id "" \ + --repo "" \ + --skip-scan \ + --quiet \ + [--version ""] \ + [--signing-key "" --key-alias ""] +``` + +**Always pass `--skip-scan`.** Without it, the CLI runs a synchronous Xray check +immediately after upload. Because the artifact is brand-new and not yet indexed, +the check can falsely reject a perfectly clean skill. Skipping the inline scan +is safe. If the repo has an Xray watch, it scans asynchronously on its own. + +Only omit `--skip-scan` when the user explicitly asks for an inline scan. + +Useful flags (verify with `jf skills publish --help`): + +| Flag | Purpose | +|------|---------| +| `--repo` | Target Artifactory repository key. **Required.** | +| `--version` | Package version (semver, e.g. `1.2.0`) or `latest`. | +| `--signing-key` | Path to the PEM private key for evidence signing (overrides `EVD_SIGNING_KEY_PATH`). | +| `--key-alias` | Alias of the signer's trusted public key (overrides `EVD_KEY_ALIAS`). | +| `--skip-scan` | Skip the synchronous post-publish Xray scan (env `JFROG_CLI_SKIP_SKILLS_SCAN=true`). | +| `--auto-delete-on-failure` | Auto-remove the artifact if the Xray scan flags it as malicious. | +| `--quiet` | Skip interactive prompts (also defaults to `$CI`). | + +To release a new version, bump the bundle's `--version` and publish again. Each +publish adds a new version. + +**On a version conflict** (publish fails with `version ... already exists`): +the CLI's `[o] Overwrite` prompt is interactive-only (`--quiet`/CI aborts), so it +cannot be answered from here. Use the table below as your own reference. Do not +paste it into the chat. Ask the user to pick one option, filling `` with the +existing version and `` with the next patch (for example `3.0.0` to `3.0.1`): + +| Option | Action | +|--------|--------| +| **Overwrite** | Run `jf skills delete "" --version "" --repo "" --server-id ""`, then re-run the publish unchanged. | +| **Publish as a new version** | Re-run the publish with `--version ` (the user's semver, or ``). | +| **Abort** | Stop and report that nothing was published. | + +## Report the publish result + +- **Success.** Reply using **this exact template**. Do not mention Xray + scanning, async watches, or indexing: + + > Published `@` to `` on ``. +- **Blocked by the Xray scan** (only when `--skip-scan` was omitted, shown by + `[VIOLATION] … identified as malicious` or `blocked by Xray security scan`). + Publish uploads the archive first, then scans, so on a scan block the artifact + may still be in the repo unless you passed `--auto-delete-on-failure`. Never + claim it was removed. Verify: + +```bash +jf api '/artifactory/api/storage///' --server-id "" +# 200 = still present, 404 = already gone +``` + + If it is still present, tell the user the malicious-flagged artifact remains + and offer to delete it (`jf skills delete "" --version "" + --repo "" --server-id ""`). Treat the malicious flag as a real security signal. Reply + using **this exact template**: + + > Publish of `@` was **blocked by the Xray scan** (``). + > The flagged artifact is still in ``. I can delete it if you'd like. + + To auto-clean on a future failed publish, re-run with + `--auto-delete-on-failure`. +- **Other failure.** Reply using **this exact template**, quoting the CLI error + verbatim in ``: + + > Publishing `` to `` on `` failed: ``. + + On 401/403/404, follow the stop-on-error rule from the base `jfrog` skill + (see *Prerequisites* in `../SKILL.md`): stop and do not retry against a + different configured server. diff --git a/plugins/jfrog/skills/jfrog-package-safety-and-download/SKILL.md b/plugins/jfrog/skills/jfrog-package-safety-and-download/SKILL.md index 598318a..0adb9cf 100644 --- a/plugins/jfrog/skills/jfrog-package-safety-and-download/SKILL.md +++ b/plugins/jfrog/skills/jfrog-package-safety-and-download/SKILL.md @@ -20,17 +20,6 @@ metadata: - Read `../jfrog/SKILL.md` for JFrog Platform concepts, domain model, CLI setup, and API patterns. - **OneModel shapes drift by server version.** Before inventing GraphQL fields or `where` filters, read `../jfrog/references/onemodel-graphql.md` (schema fetch workflow) and `../jfrog/references/onemodel-query-examples.md` (**Public packages**, **Stored packages**). Regenerate or verify queries against `GET "$JFROG_URL/onemodel/api/v1/supergraph/schema"` when examples fail validation. -## Workflow - -# Package safety check and download workflow - -When to read this file: - -- User asks to **check if a package is safe** and/or **download** it. -- User asks to **download a package** from Artifactory. -- User mentions checking a package for **curation** approval. -- User wants to know if a package is **allowed** or **approved** for use. - ## Workflow overview ```mermaid diff --git a/plugins/jfrog/skills/jfrog/SKILL.md b/plugins/jfrog/skills/jfrog/SKILL.md index 67e0391..f7bc0ba 100644 --- a/plugins/jfrog/skills/jfrog/SKILL.md +++ b/plugins/jfrog/skills/jfrog/SKILL.md @@ -17,7 +17,7 @@ compatibility: >- Requires jq on PATH. metadata: role: base - version: "0.11.0" + version: "0.15.0" --- # JFrog Skill