diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 9ef0c11..16a577d 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jfrog", - "version": "0.1.2", + "version": "0.1.3", "description": "JFrog skills and the JFrog MCP server for Codex \u2014 interact with the JFrog Platform.", "author": { "name": "JFrog", diff --git a/package.json b/package.json index 09855c1..32d168e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codex-plugin", - "version": "0.1.2", + "version": "0.1.3", "private": true, "type": "module", "description": "JFrog skills and MCP server plugin for OpenAI Codex.", diff --git a/scripts/sync-skills-vendor.json b/scripts/sync-skills-vendor.json index e572b93..223ecef 100644 --- a/scripts/sync-skills-vendor.json +++ b/scripts/sync-skills-vendor.json @@ -1,6 +1,6 @@ { "repo": "jfrog/jfrog-skills", - "pin": "v0.22.0", + "pin": "v0.23.0", "paths": [ "skills" ] diff --git a/skills/jfrog-ai-catalog-skills/SKILL.md b/skills/jfrog-ai-catalog-skills/SKILL.md index f129918..ce2d39b 100644 --- a/skills/jfrog-ai-catalog-skills/SKILL.md +++ b/skills/jfrog-ai-catalog-skills/SKILL.md @@ -12,6 +12,8 @@ description: >- 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. + NOT for managing MCP servers (use jfrog-mcp-management) or downloading + packages/artifacts (use jfrog-package-safety-and-download). metadata: role: workflow --- diff --git a/skills/jfrog-mcp-management/SKILL.md b/skills/jfrog-mcp-management/SKILL.md index 8f38454..8568687 100644 --- a/skills/jfrog-mcp-management/SKILL.md +++ b/skills/jfrog-mcp-management/SKILL.md @@ -5,6 +5,8 @@ description: >- @jfrog/agent-guard), and browse the JFrog MCP catalog. Use whenever the user wants to add/enable/list/remove/uninstall an MCP server or tool — even without saying "MCP" — and never install one any other way. + NOT for installing agent skills (use jfrog-ai-catalog-skills) or running JFrog + platform operations such as Artifactory/Xray/AppTrust (use the base jfrog skill). compatibility: >- Requires network access to the npm registry and the JFrog platform, and ~/.jfrog/ write access for OAuth login and cache cleanup. diff --git a/skills/jfrog-mcp-management/references/harness-claude.md b/skills/jfrog-mcp-management/references/harness-claude.md index fa8c28a..a7f3fda 100644 --- a/skills/jfrog-mcp-management/references/harness-claude.md +++ b/skills/jfrog-mcp-management/references/harness-claude.md @@ -3,7 +3,7 @@ Claude Code-specific config for the `jfrog-mcp-management` skill. Read this together with [harness-common.md](harness-common.md) (shared entry shape and success criterion). You reached this file because the harness is Claude Code -(`CLAUDECODE` / `CLAUDE_CODE_ENTRYPOINT`). +(`CLAUDE_CODE_CHILD_SESSION`, or system prompt identifies Claude Code). ## Config files diff --git a/skills/jfrog-mcp-management/references/harness-common.md b/skills/jfrog-mcp-management/references/harness-common.md index 850a365..5139f46 100644 --- a/skills/jfrog-mcp-management/references/harness-common.md +++ b/skills/jfrog-mcp-management/references/harness-common.md @@ -10,36 +10,46 @@ plus **exactly one** harness file; do NOT open the others. ## Step A — detect the harness and open ONE file -The `CLAUDECODE` / `CURSOR_*` / `CODEX_*` / `OPENCODE` signals below -mirror `../../jfrog/scripts/check-environment.sh` `detect_harness()`; the -`TERM_PROGRAM=vscode` editor hint is **not** in that script, and Devin is -**not** detected by the script. Each row's signal is **self-contained and -non-overlapping**, so detection does not depend on evaluation order. The VS -Code harness file targets the **VS Code editor** (Copilot MCP support), not -the standalone GitHub Copilot terminal CLI — the CLI (`COPILOT_CLI`) has no -editor UI or `mcp.json`, so it falls through to the Fallback section. - -1. Call `../../jfrog/scripts/check-environment.sh` and parse `tool=` from - the User-Agent line. When `tool` is `claude` or `cursor`, that matches the - Claude or Cursor row below — open that harness file. This call also - satisfies the Prerequisites environment check — capture/export - `JFROG_CLI_USER_AGENT` from it here too, rather than calling the script - again later. -2. Otherwise other `tool` values, `unknown`, or a missing `tool` are not enough - — **match this table**. Use how your system prompt identifies you plus any +The session-marker signals below mirror +`../../jfrog/scripts/check-environment.sh` `detect_harness()` (lockstep with +jfrog-cli-core `agentEnvDetectors`); the `TERM_PROGRAM=vscode` editor hint is +**not** in that script, and Devin is **not** detected by the script. Signals can +overlap — when more than one is set, UA / census naming uses the first matching +branch in `detect_harness()` (see the Agent identity table in +`ARCHITECTURE.md` for that precedence; e.g. `GEMINI_CLI` wins over +`CURSOR_AGENT`). The MCP routing table below lists only harnesses that have a +dedicated config file — it is **not** ordered like `detect_harness()`, and must +not be used as UA precedence. The VS Code harness file targets the **VS Code +editor** (Copilot MCP support), not the standalone GitHub Copilot terminal CLI +— the CLI (`COPILOT_CLI` / `COPILOT_AGENT_SESSION_ID`) has no editor UI or +`mcp.json`, so it falls through to the Fallback section. + +1. Prefer this table (env + system prompt). On jf ≥ 2.120.0 the skill UA often + omits `tool=` because the CLI emits `ai-agent/` instead — do not rely + on parsing `tool=` alone. +2. Optionally call `../../jfrog/scripts/check-environment.sh ` and, + when present, parse `tool=` from the UA (or `ai-agent/` after + `jfrog-cli-go/`). The UA also carries `trigger=skill` (APR hooks use + `trigger=hook` when they spawn `jf`). When the name is `claude`, `cursor`, + or `opencode`, open that harness file. This call also satisfies the + Prerequisites environment check — capture/export `JFROG_CLI_USER_AGENT` and + `JFROG_CLI_AI_MODEL=''` (same slug passed to the script) here + too, rather than calling the script again later. +3. Other `tool` values, `unknown`, or a missing `tool` are not enough — + **match this table**. Use how your system prompt identifies you plus any environment variables that matching row lists. If row matches → open that file. - Unsure → step 3. Sure none apply → Fallback. -3. If detection is still not conclusive, ASK the user which agent/editor they + Unsure → step 4. Sure none apply → Fallback. +4. If detection is still not conclusive, ASK the user which agent/editor they are in — do not guess, and do not read multiple harness files. | Detected harness | Signal (self-contained) | Read THIS file (and no other harness file) | | --- | --- | --- | -| Claude Code | `CLAUDECODE` or `CLAUDE_CODE_ENTRYPOINT` env var | [harness-claude.md](harness-claude.md) | +| Claude Code | `CLAUDE_CODE_CHILD_SESSION` env var (or system prompt identifies Claude Code) | [harness-claude.md](harness-claude.md) | | Codex | `CODEX_SANDBOX` / `CODEX_THREAD_ID` / `CODEX_CI` | [harness-codex.md](harness-codex.md) | -| Cursor | `CURSOR_AGENT` / `CURSOR_CLI` / `CURSOR_TRACE_ID` env var | [harness-cursor.md](harness-cursor.md) | -| OpenCode | `OPENCODE` | [harness-opencode.md](harness-opencode.md) | +| Cursor | `CURSOR_AGENT` / `CURSOR_EXTENSION_HOST_ROLE=agent-exec` | [harness-cursor.md](harness-cursor.md) | +| OpenCode | `OPENCODE` / `OPENCODE_SESSION_ID` | [harness-opencode.md](harness-opencode.md) | | Devin Desktop | Your system prompt / system instructions identify you as **Devin** (Devin Desktop / Devin Local / Cognition). That alone is enough. Optionally confirm with `VSCODE_IPC_HOOK` set to the Devin Desktop IPC socket (full path), e.g. macOS: `~/Library/Application Support/Devin/-main.sock` — the expanded path contains `/Devin/`. The path alone is **not** enough. | [harness-devin.md](harness-devin.md) | -| VS Code editor | `TERM_PROGRAM=vscode` **and no `CURSOR_*` var is set** **and no `OPENCODE` var is set** **and no `CODEX_*` var is set** **and no `CLAUDECODE`/`CLAUDE_CODE_ENTRYPOINT` var is set** **and no `GEMINI_CLI` / `GOOSE_TERMINAL` / `COPILOT_CLI` var is set** **and** your system prompt / system instructions do **not** identify you as Devin | [harness-vscode.md](harness-vscode.md) | +| VS Code editor | `TERM_PROGRAM=vscode` **and no** `CURSOR_AGENT` / `CURSOR_EXTENSION_HOST_ROLE=agent-exec` **and no** `CLAUDE_CODE_CHILD_SESSION` **and no** `OPENCODE` / `OPENCODE_SESSION_ID` **and no** `CODEX_SANDBOX` / `CODEX_THREAD_ID` / `CODEX_CI` **and no** `GEMINI_CLI` / `GOOSE_TERMINAL` / `COPILOT_CLI` / `COPILOT_AGENT_SESSION_ID` **and** your system prompt / system instructions do **not** identify you as Devin | [harness-vscode.md](harness-vscode.md) | | anything else | none of the above | **Fallback** section below — no harness file exists | Once you know your harness, use ONLY these fields from its file: `Config files` diff --git a/skills/jfrog-mcp-management/references/harness-cursor.md b/skills/jfrog-mcp-management/references/harness-cursor.md index fc22c6e..09de1cd 100644 --- a/skills/jfrog-mcp-management/references/harness-cursor.md +++ b/skills/jfrog-mcp-management/references/harness-cursor.md @@ -3,7 +3,7 @@ Cursor-specific config for the `jfrog-mcp-management` skill. Read this together with [harness-common.md](harness-common.md) (shared entry shape and success criterion). You reached this file because the harness is Cursor (`CURSOR_AGENT` -/ `CURSOR_CLI` / `CURSOR_TRACE_ID`). +/ `CURSOR_EXTENSION_HOST_ROLE=agent-exec`). ## Config files diff --git a/skills/jfrog-mcp-management/references/harness-opencode.md b/skills/jfrog-mcp-management/references/harness-opencode.md index 816b810..64679ef 100644 --- a/skills/jfrog-mcp-management/references/harness-opencode.md +++ b/skills/jfrog-mcp-management/references/harness-opencode.md @@ -2,9 +2,10 @@ OpenCode-specific config for the `jfrog-mcp-management` skill. Read this together with [harness-common.md](harness-common.md) (shared entry shape and success -criterion). You reached this file because the harness is OpenCode (`OPENCODE`, -set in the environment at startup). This targets all OpenCode surfaces (TUI, CLI, -Desktop, IDE, web) - they share one backend and the same `opencode.json`. +criterion). You reached this file because the harness is OpenCode (`OPENCODE` +and/or `OPENCODE_SESSION_ID` in the environment). This targets all OpenCode +surfaces (TUI, CLI, Desktop, IDE, web) - they share one backend and the same +`opencode.json`. > **How OpenCode stores the entry:** config is **JSON / JSONC** under the > top-level **`mcp`** key; each server is a **`type: "local"`** entry whose diff --git a/skills/jfrog-setup-package-managers/SKILL.md b/skills/jfrog-setup-package-managers/SKILL.md index 9115f01..160086f 100644 --- a/skills/jfrog-setup-package-managers/SKILL.md +++ b/skills/jfrog-setup-package-managers/SKILL.md @@ -9,6 +9,8 @@ description: >- already has the same repo key. Never pick a repo by discovery; use resolver output only (unless the user names or asks to browse repos). On unresolved or failed setup, ask with the failure verbatim — never switch servers. + NOT for installing packages, general Artifactory repo operations (use the base + jfrog skill), or MCP server setup (use jfrog-mcp-management). metadata: role: workflow --- @@ -20,6 +22,33 @@ then record it in [`.jfrog/local/package-resolution.json`](references/workspace- `jf setup` writes package-manager-native config (`.npmrc`, `pip.conf`, `uv.toml`, …); the binding lets the hook re-apply on later sessions. +## At a glance (always-read core) + +Every `jf setup` this session: + +- **Cover base [`../jfrog/SKILL.md`](../jfrog/SKILL.md) At-a-glance / Tier A** + (Step 0.1) → ``, `--server-id` placement, single-server, stop-don't-switch. + Prefer full base SKILL.md when you can; Tier B (`cli-gotchas` / `jf-api` / …) + only if the next action needs `jf api` / advanced CLI +- **Always `--repo` + `--server-id`.** `` ← [Step 2](#step-2--get-the-resolved-repo) + (table / binding / global-cache) or user override / unresolved AskQuestion; + never self-discover. `` ← resolver only (never user-selected) +- **Confirm** before first `jf setup` unless user asked silent / non-interactive +- **Exit 0 → merge binding**; non-zero → stop, surface CLI verbatim, offer + alternate repo or `abort` (2-answer cap) +- **Binding = decisions, not creds** — never write tokens into + `.jfrog/local/package-resolution.json` +- **Unresolved / failed:** ask with failure verbatim — never switch servers +- **Never skip** [Gotchas](#gotchas--hard-rules-never-skip) + base Tier A hard + rules (`../jfrog/SKILL.md` Cautious execution / Server selection / Tier A + gotcha floor). Full `cli-gotchas.md` is Tier B — not required for `jf setup` + +Steps: [0](#step-0--read-the-base-skill-then-ensure-jf-is-ready) → +[1](#step-1--identify-package-managers-to-bind) → +[2](#step-2--get-the-resolved-repo) → +[3](#step-3--confirm-run-jf-setup-persist-binding) → +[4](#step-4--load-the-routing-policy) + ## Scope (this skill vs session hook) **Session-start hook:** resolves repo keys per package type, injects the @@ -42,11 +71,17 @@ unlisted package manager apply as usual). - `jf setup` **mutates user state** (`~/.npmrc`, `~/.docker/config.json`, …). Confirm before the first `jf setup` in a session unless the user explicitly requests silent/non-interactive setup. -- Reading [`../jfrog/SKILL.md`](../jfrog/SKILL.md) is required — done as Step 0.1 below. +- Covering base At-a-glance / Tier A is required — done as Step 0.1 below. **Out of scope:** CLI install/login (`../jfrog/references/…`). -## Gotchas +## Gotchas — hard rules (never skip) + +**Not tips.** Do/don'ts and known traps for `jf setup` — follow every bullet +before binding. Also honor base **Tier A** hard rules from +[`../jfrog/SKILL.md`](../jfrog/SKILL.md) (Cautious execution, Server selection, +Tier A gotcha floor). Full `cli-gotchas.md` is Tier B — load only if this +session also needs `jf api` / advanced CLI. - **Always pass `--repo` and `--server-id`** — omitting `--repo` fails when multiple repos match. See [`jf-setup-command.md`](references/jf-setup-command.md). @@ -70,11 +105,13 @@ unlisted package manager apply as usual). ## Step 0 — Read the base skill, then ensure `jf` is ready -1. **Read [`../jfrog/SKILL.md`](../jfrog/SKILL.md) fully first — always, before any - `jf` command, even when `jf` is already configured.** It carries the `jf` - invariants this skill relies on. After reading, run that skill's - *Environment check* (and export `JFROG_CLI_USER_AGENT`) before the first - `jf` call. +1. **Cover base skill At-a-glance / Tier A before the first non-exempt `jf` + (even when `jf` is already configured).** Prefer reading + [`../jfrog/SKILL.md`](../jfrog/SKILL.md) in full when you can; the At-a-glance + Tier A floor is enough for `jf setup` / package-manager binding. Load Tier B + (`cli-gotchas.md`, `jf-api.md`, …) only if the next action needs `jf api` / + advanced CLI. Then run that skill's *Environment check* (and export + `JFROG_CLI_USER_AGENT`) before the first `jf` call. 2. Ensure `jf` + a configured server (``). If `jf config show` already succeeds, skip to Step 1; otherwise: - **`jf --version`** missing → install per @@ -198,3 +235,16 @@ hard rules. Continue the original request using those URLs. If the command prints nothing, routing is off by config (`packageResolution.enabled` is not `true`) — an admin opt-in. Report that to the user and let them decide whether to enable it. + +## Before you run `jf setup` — checklist + +[At a glance](#at-a-glance-always-read-core) invariants: + +- [ ] base At-a-glance / Tier A covered; `` exported +- [ ] `` ← Step 2 or user override; `` ← resolver only +- [ ] confirmed (or explicit silent-setup) +- [ ] `jf setup --server-id --repo ` +- [ ] exit 0 → merge binding (no creds); non-zero → stop + report verbatim; + never switch servers +- [ ] **never skip** Gotchas (this skill) + base Tier A hard rules (full + `cli-gotchas.md` only if Tier B path) diff --git a/skills/jfrog/SKILL.md b/skills/jfrog/SKILL.md index d1d1702..2edb507 100644 --- a/skills/jfrog/SKILL.md +++ b/skills/jfrog/SKILL.md @@ -15,21 +15,78 @@ description: >- advanced security, exposures, or any JFrog product name. Do NOT use this skill to install, add, remove, list, or manage MCP servers. compatibility: >- - Requires jq on PATH. + Requires bash, jq, and awk on PATH. The JFrog CLI (jf) is required for Tier 2 + (CLI) and Tier 3 (jf api) operations; without it, only MCP (Tier 1) is available. metadata: role: base - version: "0.22.0" + version: "0.23.0" --- # JFrog Skill The foundational skill for all JFrog agent interactions. Covers JFrog Platform concepts, `jf` CLI setup and authentication, and intent routing to workflow skills. +## At a glance (always-read core) + +Network-facing `jf` this session. Exempt until ``: `jf --version`, +`jf config show`. + +**Tier A — always-read floor** (before first *non-exempt* `jf`): + +- **UA:** [Environment check](#environment-check) once → + `export JFROG_CLI_USER_AGENT=''` atop every bash that runs `jf` +- **Server:** resolve default once → `--server-id ` **after** subcommand + (`jf api --server-id …`, never `jf --server-id … api`). One request → one + server (unless user names servers, e.g. `compare and `) +- **Error (401/403/404/timeout):** stop — never retry another server / never + infer multi-server. Override only if user names a server +- **No prep mutations:** missing repo/artifact/build → stop + report; no + create/copy/upload unless asked +- **Never guess** tools / `jf api` paths → tool list / `--help` / `references/`. + 404 → stop (no guessed retry). `jf api` needs product prefix + (`/artifactory`, `/xray`, …) +- **Hard-rule signals:** [Cautious execution](#cautious-execution), + [Server selection rules](#server-selection-rules-mandatory), + [Gotchas](#gotchas--hard-rules-never-skip) Tier A bullets below — not tips +- **Gotcha floor (Tier A):** never interactive (`jf config add`, `jf login`, + template wizards, …); if a call fails **with** `--server-id`, do **not** + retry without it; 401/403/404/timeout → stop, never hop servers; `--quiet` + is not global — check `--help` before adding it + +**Tier B — path-gated MUST** (before `jf api` / AQL / advanced CLI I/O / +MCP-result-via-shell anti-patterns): full +[`references/cli-gotchas.md`](references/cli-gotchas.md), +[`references/jf-api.md`](references/jf-api.md), +[`references/preserving-command-output.md`](references/preserving-command-output.md), +[`references/cli-command-discovery.md`](references/cli-command-discovery.md). +Setup / `jf setup` / ordinary CLI do **not** require Tier B. + +**Tier C — on-demand:** [`references/INDEX.md`](references/INDEX.md) domain +refs; login / CLI install when needed. + +Contents (prefer full SKILL.md; At a glance = Tier A floor if you only see the +top): + +| Section | Topic | +|---------|-------| +| [Tool selection strategy](#tool-selection-strategy) | MCP vs CLI vs `jf api` | +| [Prerequisites](#prerequisites), [Environment check](#environment-check) | before first non-exempt `jf` | +| [Cautious execution](#cautious-execution), [Server selection rules](#server-selection-rules-mandatory) | **Tier A hard rules** | +| [Gotchas — hard rules](#gotchas--hard-rules-never-skip) | Tier A reminders; full `cli-gotchas.md` = **Tier B** | +| [Path-gated base references](#path-gated-base-references-must-before-jf-api--advanced-cli) | **Tier B MUST** before `jf api` / advanced CLI | +| [When to read reference files](#when-to-read-reference-files) → [`references/INDEX.md`](references/INDEX.md) | Tier C domain refs | +| [Command discovery](#command-discovery) / [jf api](#invoking-platform-apis-with-jf-api) | Tier B when those paths apply | +| [Structured inputs](#structured-inputs) / [Batch](#batch-and-parallel-execution) / [Preserving output](#preserving-command-output) | templates / parallel / temp files | + +> **Floor for partial reads:** Tier A (this section) before first non-exempt +> `jf`. Prefer the full SKILL.md when you can. Load **Tier B** only when the +> next action needs `jf api` / AQL / advanced CLI I/O (checklist). Domain +> detail → Tier C [`references/INDEX.md`](references/INDEX.md). + Interact with the JFrog Platform through three tool tiers — see -[Tool selection strategy](#tool-selection-strategy). In code examples below, -`` refers to this skill's directory and is resolved automatically -by the agent. If the agent does not resolve it, determine the path by locating -this SKILL.md file and using its parent directory. +[Tool selection strategy](#tool-selection-strategy). In code examples, +`` is this skill's directory, resolved automatically by the agent. +If unresolved, locate this SKILL.md file and use its parent directory. > **Out of scope: MCP server management.** Installing, listing, removing, or > configuring MCP servers (e.g. "install an MCP", "what MCPs can I install", @@ -51,8 +108,8 @@ cover the operation or fails: subcommand. Validate the path first — see rule 6 in [Cautious execution](#cautious-execution). -MCP and the CLI may use different token scopes. If one tier returns 403, -try the alternate tier before reporting the operation blocked. +MCP and CLI may use different token scopes. One tier returns 403 → try the +other tier before reporting the operation blocked. ## Prerequisites @@ -82,14 +139,17 @@ thing to check — re-run with the appropriate escalation above. ## Environment check -MCP (Tier 1) operations do not require this check and can proceed immediately. -Before your first Tier 2 or Tier 3 (`jf`) operation in a session, run the -environment check and **remember its stdout** as `` for the rest of the -session: +MCP (Tier 1) skips this check — proceed immediately. Before your first Tier 2 +or Tier 3 (`jf`) operation this session, run the environment check and +**remember its stdout** as `` for the rest of the session: ```bash bash /scripts/check-environment.sh -# stdout (one line): jfrog-skills/ [(tool=; model=)] jfrog-cli-go/ +# stdout (one line): jfrog-skills/ (trigger=skill; tool=; client=; model=) jfrog-cli-go/ +# Stack: trigger (skill vs hook) → client (app) → agent/tool (harness) → model. +# Keys after trigger= are present when known. On jf >= 2.120.0 the CLI emits +# ai-agent/ and ai-client/ itself, so tool=/client= are omitted here. +# `trigger=skill` always stays (APR hooks set `trigger=hook` when they spawn jf). # stderr: JSON state (cached 24h at ${JFROG_CLI_HOME_DIR:-$HOME/.jfrog}/skills-cache/jfrog-skill-state.json) ``` @@ -106,10 +166,15 @@ all `jf` calls in that invocation pick it up: ```bash export JFROG_CLI_USER_AGENT='' +export JFROG_CLI_AI_MODEL='' # jf >= 2.120.0 emits ai-model/ from this jf config show jf api /artifactory/api/system/version ``` +`JFROG_CLI_AI_MODEL` carries the model the CLI cannot infer from the environment; +export it alongside `` (same `` you passed the script). Older CLIs +ignore it and rely on the `model=` key already inside ``. + Do **not** repeat the assignment per `jf` call (`JFROG_CLI_USER_AGENT='' jf …` on every line). This is a **session-global invariant**: it applies to *every* `jf` invocation in the session, including `jf` calls you make while following @@ -153,8 +218,8 @@ command output* below. ## Cautious execution -Do not run commands speculatively. Before executing any JFrog CLI command, -MCP tool call, or API call: +**HARD RULES — never skip.** Speculative / preparatory / guessed ops are +forbidden. Before any JFrog CLI command, MCP tool call, or API call: 1. Confirm the operation is needed to fulfill the user's request. If the request is ambiguous or could refer to multiple systems (e.g. @@ -185,9 +250,15 @@ MCP tool call, or API call: ## Server selection rules (mandatory) -**Single-server invariant.** Every `jf` call MUST pass `--server-id ` -(default resolved below); for one user request, all `jf` calls use **exactly -one** server-id. A wrong answer from the wrong server is worse than a stop-and-ask. +**HARD RULES — never skip or soften.** Wrong-server answers and silent +server-switching are worse than stopping to ask. + +**Single-server invariant.** After `` is resolved, every subsequent +network-facing `jf` call MUST pass `--server-id ` (default resolved below); +bootstrap `jf --version` / `jf config show` stay exempt until then. For one user +request, all network `jf` calls use **exactly one** server-id — unless the user +names servers to compare (e.g. `compare and `), where each call passes +its own target's `--server-id`. **JFrog MCP and CLI use independent auth.** MCP tools authenticate through the MCP server session (not `jf config`); CLI commands authenticate through @@ -236,303 +307,135 @@ failure, **stop with no further `jf` calls** and respond: > configured server(s): `` — I won't query them without your explicit > instruction. How would you like to proceed? -## When to read reference files - -Load the most specific file for the task at hand. Avoid loading more than 2-3 -reference files for a single operation — start with the most relevant one and -only load additional files if the first doesn't cover the need. File sizes -vary (~25–640 lines); larger files are noted with approximate line counts -below. - -### Cross-domain - -- **Disambiguating a JFrog entity, understanding entity types, or planning operations that span multiple products**: read `references/jfrog-entity-index.md`, then follow pointers to the relevant domain file -- **Looking up documentation URLs**: read `references/jfrog-url-references.md` - -### Artifactory - -- **Repository types, artifacts, builds, properties, or permission targets (concepts)**: read `references/artifactory-entities.md` (~220 lines) -- **Stored packages, package versions, version locations, or the metadata layer over Artifactory (concepts)**: read `references/stored-packages-entities.md` (~165 lines) -- **Repo, file, build, permission, user/group, or replication operations**: if the JFrog MCP server exposes a tool for the operation, prefer it. For CLI/API fallback, read `references/artifactory-operations.md` (for **listing builds** use AQL with `limit`/`offset` — see § *Listing build names*; for **full build detail** use `GET /api/build//?project=` — see § *Retrieving full build info*) -- **AQL queries**: read `references/artifactory-aql-syntax.md` (~585 lines) -- **Artifactory REST beyond the CLI, structured JSON templates (replacing interactive wizards), or any Artifactory API gap**: read `references/artifactory-api-gaps.md` (~220 lines) - -### Xray & security - -- **Watches, policies, violations, components, or vulnerability scanning (concepts)**: read `references/xray-entities.md` (~290 lines) -- **Exposures scanning results (secrets, IaC, service misconfigurations, application security risks)**: read `references/xray-entities.md` § Exposures (Advanced Security) -- **Curation audit events (approved/blocked packages, dry-run policy evaluations, curation export)**: read `references/xray-entities.md` § Curation audit events +## Path-gated base references (MUST before `jf api` / advanced CLI) -### Release lifecycle & distribution +These four files **are Tier B of the base skill** — content that used to live +in this SKILL.md. They are **not** optional INDEX domain lookups, and they are +**not** required before every CLI / setup path. -- **Release bundles, lifecycle stages, distribution, or evidence (concepts)**: read `references/release-lifecycle-entities.md` (~180 lines) -- **Applications, application versions, releasables, promotions, or AppTrust (concepts)**: read `references/apptrust-entities.md` (~155 lines) +**MUST read every one in full before** `jf api`, AQL via `jf api`, advanced +CLI I/O (temp-file / stdout-stderr patterns), or acting on MCP results via +shell/`jq`. Ordinary `jf` (e.g. `jf setup`, `jf rt …` with known flags) needs +**Tier A only** ([At a glance](#at-a-glance-always-read-core)). -### Catalog +The short [Gotchas](#gotchas--hard-rules-never-skip) Tier A bullets are the +session floor — **they do not replace** full +[`references/cli-gotchas.md`](references/cli-gotchas.md) when you enter Tier B. -- **Public or custom catalog, package metadata, vulnerability advisories, licenses, OpenSSF, or MCP services (concepts)**: if the JFrog MCP server exposes a catalog tool, prefer it for single-package lookups. For deeper queries, read `references/catalog-entities.md` (~190 lines) -- **CVE details, vulnerability lookup by CVE ID, or severity/affected-packages/fix-versions for a specific CVE**: prefer an MCP vulnerability-lookup tool if the JFrog MCP server exposes one. Otherwise read `references/onemodel-query-examples.md` § *Public security domain* for the `searchVulnerabilities` query shape — this is self-contained; do not load the `jfrog-package-safety-and-download` skill for pure CVE lookups +| Tier B — MUST read in full (path-gated) | Covers | +|-----------------------------------------|--------| +| [`references/cli-gotchas.md`](references/cli-gotchas.md) | gotchas, caveats, known issues, do/don't, I/O & auth traps | +| [`references/jf-api.md`](references/jf-api.md) | product-prefix table, flags, examples, GraphQL payload | +| [`references/preserving-command-output.md`](references/preserving-command-output.md) | temp files, `$$` paths, no re-fetch for `jq` | +| [`references/cli-command-discovery.md`](references/cli-command-discovery.md) | namespaces, top-level cmds, Pipelines sunset | -### OneModel (GraphQL) +Skipping any of these **on a Tier B path** = incomplete base-skill load / +hard-rule violation. Skipping them on a Tier A-only path (setup / simple CLI) +is **not** a violation. -- **GraphQL queries** (applications, packages, evidence, release bundles, catalog, cross-domain, or "list/search my" platform entities): read `references/onemodel-graphql.md` (~325 lines) -- **Query templates and domain-specific examples**: read `references/onemodel-query-examples.md` (~555 lines) -- **Pagination, filtering, GraphQL variables, or date formatting**: read `references/onemodel-common-patterns.md` (~280 lines) - -### Platform administration - -- **Platform structure, project/repo membership, or project roles vs environments (concepts)**: read `references/platform-access-entities.md` -- **Access tokens, stats, projects, or system health**: read `references/platform-admin-operations.md` -- **Managing JFrog Projects, members, or environments**: read `references/projects-api.md` (~260 lines) -- **Platform REST beyond the CLI, or any platform-level API gap**: read `references/platform-admin-api-gaps.md` (~180 lines) - -### CLI setup & authentication - -- **Adding a server or logging in**: read `references/jfrog-login-flow.md` (~130 lines) -- **CLI not installed, upgrade needed, or `jq` unavailable**: read `references/jfrog-cli-install-upgrade.md` - -### General patterns +## When to read reference files -- **Batching, parallel Shell calls, or launching subagents**: read `references/general-parallel-execution.md` (~135 lines) -- **Large or parallel data gathering, list-vs-detail APIs, cache hygiene**: read `references/general-bulk-operations-and-agent-patterns.md` -- **Standalone HTML report with JFrog-aligned styling**: read `references/jfrog-brand-html-report.md` -- **Reusable gotchas from past tasks**: read or extend `references/general-use-case-hints.md` +Prefer reading this SKILL.md in full. [At a glance](#at-a-glance-always-read-core) +is the **Tier A** floor for partial readers. **Path-gated base references** +above are **Tier B** (mandatory on those paths, not every session). Everything +else under [`references/INDEX.md`](references/INDEX.md) is **Tier C** domain +detail — load ≤2–3 most specific files for the task; skip unused domains. +`references/INDEX.md` lists every `references/*.md` file (Tier B + Tier C). +Add/rename/remove a file → update INDEX in the same change — CI +(`tests/jfrog/test_reference_index_contract.py`) fails if they diverge. ## Command discovery -Use the commands listed below as your primary reference. Run `--help` to -verify options you are unsure about or to discover commands not listed here — -do not rely on memorized commands outside this skill, as they may be outdated. - -1. `jf --help` — list all namespaces and top-level commands -2. `jf --help` — list subcommands in a namespace -3. `jf --help` — show usage, arguments, and options - -### CLI namespaces - -| Namespace | Alias | Product | -|-----------|-------|---------| -| `rt` | | Artifactory | -| `xr` | | Xray | -| `ds` | | Distribution V1 | -| `at` | `apptrust` | AppTrust | -| `evd` | | Evidence | -| `mc` | | Mission Control | -| `worker` | | Workers | -| `config` | `c` | CLI server configuration | -| `plugin` | | CLI plugin management | -| `ide` | | IDE integration | - -> **Sunset notice:** JFrog Pipelines has been sunset and is no longer supported. -> Do not use the `pl` CLI namespace or the Pipelines REST API -> (`/pipelines/api/...`). If a user asks about Pipelines, inform them the -> product has been sunset. +Run `--help` to verify options — do not rely on memorized commands. -Top-level lifecycle commands (no namespace): `rbc`, `rbp`, `rbd`, `rba`, -`rbf`, `rbe`, `rbi`, `rbs`, `rbu`, `rbdell`, `rbdelr`. +1. `jf --help` → 2. `jf --help` → 3. `jf --help` -Top-level security commands: `audit`, `scan`, `build-scan`, `curation-audit`, -`sbom-enrich`. - -Top-level other: `access-token-create` (`atc`), `login`, `how`, `stats`, -`generate-summary-markdown`, `exchange-oidc-token`, `completion`. +**Tier B — MUST read in full before relying on discovery beyond `--help`:** +[`references/cli-command-discovery.md`](references/cli-command-discovery.md) +(namespaces, top-level lifecycle/security commands, Pipelines sunset). ## Invoking platform APIs with `jf api` -`jf api` is the Tier 3 entry point for JFrog Platform REST and GraphQL -endpoints, auto-authenticated against the resolved server. **Do not use -`jf rt curl` or `jf xr curl`**; they are superseded by `jf api`. - -### Product-prefix table - -`jf api` requires the **full** path including the product prefix; omitting it -returns 404. - -| Product | Path prefix | -|---------|-------------| -| Artifactory | `/artifactory/api/...` | -| Xray | `/xray/api/...` | -| Access (users, groups, tokens, permissions, projects) | `/access/api/...` | -| Evidence | `/evidence/api/...` | -| Release Lifecycle | `/lifecycle/api/...` | -| AppTrust | `/apptrust/api/...` | -| Distribution | `/distribution/api/...` | -| OneModel (GraphQL) | `/onemodel/api/v1/graphql`, `/onemodel/api/v1/supergraph/schema` | -| Mission Control | `/mc/api/...` | -| Curation | `/xray/api/v1/curation/...` (lives under Xray) | - -### Examples - -```bash -jf api /artifactory/api/repositories -jf api --server-id /artifactory/api/system/version - -# AQL (POST with text/plain body) -jf api /artifactory/api/search/aql \ - -X POST -H "Content-Type: text/plain" -d '' -``` - -Common flags: `-X/--method`, `-H/--header`, `-d/--data`, `--input `, -`--server-id`, `--timeout`. Body on stdout, status on stderr — see -[Gotchas](#gotchas). - -### GraphQL (OneModel) - -OneModel is the unified GraphQL API. **Do not** embed the query inside a JSON -literal (`-d '{"query":"..."}'`) — escaping breaks requests. Build the payload -with `jq -n --arg`, pass it via `--input`, and save the response to a file -before running `jq` on it. - -```bash -QUERY='{ evidence { searchEvidence(first: 5, where: { hasSubjectWith: { repositoryKey: "my-repo-local" } }) { totalCount } } }' -PAYLOAD=/tmp/onemodel-payload-$$.json RESPONSE=/tmp/onemodel-$$.json -jq -n --arg q "$QUERY" '{query:$q}' > "$PAYLOAD" -jf api /onemodel/api/v1/graphql -X POST \ - -H "Content-Type: application/json" --input "$PAYLOAD" > "$RESPONSE" -jq . "$RESPONSE" -``` - -Schema discovery: `jf api /onemodel/api/v1/supergraph/schema > "$SCHEMA_FILE"` -(store only under `~/.jfrog/skills-cache/`, never query responses). Read -`references/onemodel-graphql.md` for the full workflow (schema fetch, -validation, pagination, errors), plus `references/onemodel-query-examples.md` -and `references/onemodel-common-patterns.md` for query shapes, pagination, -variables, and dates. +Tier 3 for Platform REST/GraphQL, auto-authenticated. **Do not use +`jf rt curl` / `jf xr curl`.** Always include the **product prefix** +(`/artifactory`, `/xray`, `/access`, …) — omit → 404. +**Tier B — MUST read in full before `jf api`:** +[`references/jf-api.md`](references/jf-api.md) +(prefixes, flags, examples, OneModel GraphQL payload). Body on stdout / status +on stderr — see [Gotchas](#gotchas--hard-rules-never-skip) + full +`cli-gotchas.md` (Tier B). ## Structured inputs -Several CLI commands require JSON template files. The templates are normally -created by interactive wizard commands (`jf rt rpt`, `jf rt ptt`, `jf rt rplt`) -which agents cannot use. Instead, retrieve an existing config via REST API as a -starting point and modify it: +Interactive wizards (`jf rt rpt` / `ptt` / `rplt`) are unusable for agents. +Fetch an existing config via REST and edit: ```bash jf api /artifactory/api/repositories/ ``` -For other Artifactory or platform REST patterns, or when you need more than -this repo GET, see **Any API gap** under [When to read reference files](#when-to-read-reference-files). - -## Gotchas - -### MCP tools - -- MCP tools return structured data in the tool result. Read response fields - directly; do not pipe MCP output through shell commands or `jq`. - -### CLI and `jf api` - -- `jf api` requires the **product prefix** in the path. Omitting it returns - 404. See the [product-prefix table](#product-prefix-table) for the full list. -- `jf api` writes the body (success or error JSON) to **stdout** and - `[Info] Http Status: NNN` to **stderr** on every call; non-2xx also exits - 1 and adds `[Warn] jf api: returned NNN`. Pipe stdout to - `jq` directly; **never `2>&1 | jq`** — stderr corrupts the JSON. To keep - diagnostics: `jf api 2>/tmp/err-$$.log | jq .`. -- `jf api` has **no `-L`** (follow redirects) and **no `-o`** (output file). - Save bodies with shell redirection - (`jf api ... > /tmp/out-$$.json`); for - binary downloads through the Artifactory remote proxy prefer `jf rt dl`, - which handles the cache and redirect semantics natively. -- Remote repository content is stored in a `-cache` suffixed repo. Properties - and AQL queries for remote repo artifacts must target the cache repo. - Conversely, `/api/repositories/` only accepts the parent remote key - (without `-cache`) — strip the suffix for configuration lookups. -- **Do not use `jf rt search`** — always use a direct AQL query via - `jf api /artifactory/api/search/aql -X POST -H "Content-Type: text/plain" -d ''`. - See `references/artifactory-aql-syntax.md`. -- Use `--quiet` flag for non-interactive execution (suppresses confirmation - prompts). **Caution:** `--quiet` is not a global flag — commands that do not - support it (e.g. `jf rt s`, `jf rt ping`) will fail with misleading errors - like "Wrong number of arguments" or "flag provided but not defined". Check - `--help` for a command before adding `--quiet`. -- Use `--server-id` when targeting a non-default server. If a command fails - with `--server-id`, do not retry without it — that silently targets the - default server instead. See [Server selection rules](#server-selection-rules-mandatory). -- Never use interactive commands. All JFrog CLI operations must be performed - non-interactively. Known interactive commands to avoid: `jf config add`, - `jf login`, `jf rt repo-template`, `jf rt permission-target-template`, and - `jf rt replication-template`. For server setup, follow `references/jfrog-login-flow.md`. - For templates, use JSON schemas or REST API. If a command prompts for input - unexpectedly, find the non-interactive alternative via `--help` or REST API. -- `jf config export` output is base64-encoded JSON. Decode with - `base64 -d | jq` to extract fields. -- Build info lookups require a scope (`?buildRepo=` or `?project=`) — - resolve it before calling the API. See `references/artifactory-operations.md` - §Retrieving build info for the full workflow. -- If a `jf api` call returns 401, the configured token may have expired or - been rotated — ask the user to re-run the login flow (see - `references/jfrog-login-flow.md`) for the **same** server. If 403, the - token lacks required permissions. If 404, verify the endpoint path - (especially the product prefix) and target server version. On any of - these errors, do not try a different configured server as a workaround — - that targets a different environment. Report the error and ask the user. -- **Xray contextual analysis:** the summary artifact response has two - applicability fields — `applicability` (top-level, often null) and - `applicability_details` (always present with a `result` string). **Use - `applicability_details[].result` for counts and summaries.** Using the - top-level `applicability` field for aggregation produces wrong counts because - it is null when no scanner exists. See `references/xray-entities.md` - §Contextual analysis for the eight possible result values and jq snippets. -- **OneModel GraphQL:** always fetch the supergraph schema from the **same** - server you query before building operations (schemas differ by deployment); - cache, validate, and execute per `references/onemodel-graphql.md`. -- Never duplicate a network-fetching command to retry `jq` parsing — save the - response to a temp file first (see [Preserving command output](#preserving-command-output)). -- When collecting detail responses in a loop (e.g. per-repo GETs), validate - each body with `jq -e .` before appending to a results file. One non-JSON - or empty response corrupts a downstream `jq -s` slurp. Write validated - lines to an NDJSON file, then `jq -s '.' file.ndjson` to produce the final - array. See `references/general-bulk-operations-and-agent-patterns.md`. -- Accumulated edge cases from real tasks live in `references/general-use-case-hints.md` - — read when debugging odd failures; **append** a short entry when you confirm - a new, reusable gotcha. - +More REST/template patterns → `references/artifactory-api-gaps.md` or +`references/platform-admin-api-gaps.md` via [`references/INDEX.md`](references/INDEX.md). + +## Gotchas — hard rules (never skip) + +**Not tips.** Tier A bullets below are the always-read floor. Full +[`references/cli-gotchas.md`](references/cli-gotchas.md) is **Tier B** — +**MUST** before `jf api` / AQL / advanced CLI I/O / MCP-via-shell; **not** +required before every CLI or `jf setup`. Short bullets do **not** replace the +full file on Tier B paths. + +**Tier A floor (every non-exempt `jf` session):** + +- **`--quiet`** is not global — check `--help` before adding it +- **`--server-id`:** if a call fails with it, do not retry without it (silent + default-server switch). See [Server selection rules](#server-selection-rules-mandatory) +- **Non-interactive only** — avoid `jf config add`, `jf login`, `*template` + wizards; use `references/jfrog-login-flow.md` / REST +- **Auth errors:** 401 → re-login **same** server; 403 → permissions; 404 → + path/prefix/version. Never switch configured servers as a workaround + +**Tier B reminders (load full `cli-gotchas.md` + sibling Tier B refs before +these paths):** + +- **MCP:** read structured tool results directly — do not pipe through shell/`jq` +- **`jf api` I/O:** body → stdout, status → stderr; pipe stdout to `jq`; + **never `2>&1 | jq`**. No `-L` / `-o` — redirect: `jf api … > /tmp/out-$$.json` +- **Product prefix** required on every `jf api` path (see Tier B `jf-api.md`) +- **Never re-fetch to retry `jq`** — save output first + ([Preserving command output](#preserving-command-output) + Tier B + `preserving-command-output.md`) ## Batch and parallel execution -When a task requires multiple independent operations, use the lightest -parallelism mechanism that fits. Three tiers: (1) batch commands in a single -Shell call using loops or `&`, (2) issue parallel Shell tool calls, (3) launch -parallel subagents for large fan-out. Read `references/general-parallel-execution.md` -(~135 lines) for tier selection, examples, and subagent prompt structuring. +Independent ops → lightest parallelism: (1) loops/`&` in one Shell, (2) parallel +Shell calls, (3) subagents for large fan-out. Details → +`references/general-parallel-execution.md`. ## Preserving command output -When a CLI command or API call returns data, redirect the output to a temporary -file so you can re-read it without re-executing the call: - -```bash -OUT=/tmp/jf-repos-$$.json -jf api /artifactory/api/repositories > "$OUT" -echo "$OUT" -``` - -Use `$$` (the shell PID) in the filename to prevent collisions across -concurrent sessions or processes. - -**Cross-call gotcha:** each Shell tool invocation runs in a new process with a -different PID, so `$$` expands to a different value in each call. Always -**echo the expanded filename** so the agent can read it from the output and -reuse the literal path in subsequent calls. Three patterns, in priority order: - -1. **`$$` + echo** (preferred): use `$$` for collision safety, echo the path - as shown above. The agent reads `/tmp/jf-repos-12345.json` from the output - and passes that literal value to the next Shell call. -2. **Session ID**: when many files share a prefix across calls, generate an ID - once (`SID=$(date +%s)-$$`), echo it, and reuse in later calls. -3. **Hardcoded names**: last resort — risks collisions when parallel calls or - subagents write to the same path. - -This protects against wasted round-trips when you need to retry parsing — for -example, if a `jq` filter fails or you extract the wrong field on the first -attempt. Re-read the file instead of hitting the server again. - -Do **not** duplicate the same **network** request in a shell pipeline (e.g. with -`||`) only to re-run `jq` or to reveal jq diagnostics—the duplicate call -adds load on JFrog without fetching new data. Run -`jq '' /tmp/jf-*-$$.json` (or redirect stdin from the file) instead -of re-running the same `jf api` or other identical network-backed command. - -Do **not** reuse saved output across unrelated steps or changed contexts (different -server, user, or intent). The file is only valid for the immediate sequence of -operations that motivated the original call. +Save network responses to a temp file; echo the path; re-read for `jq` — never +re-run the same network call to fix parsing. + +**Tier B — MUST read in full before advanced I/O / re-parse patterns:** +[`references/preserving-command-output.md`](references/preserving-command-output.md) +(`$$` + echo, session id, no re-fetch / no cross-context reuse). + +## Before you run `jf` — quick checklist + +[At a glance](#at-a-glance-always-read-core) **Tier A** floor; add **Tier B** +only when the next action needs `jf api` / advanced CLI: + +- [ ] `export JFROG_CLI_USER_AGENT=''` in this bash +- [ ] network `jf`: `--server-id ` after subcommand (not `jf --version` / + `jf config show` pre-SID) +- [ ] one server; error → stop, don't switch (multi only if user names / + `compare`) +- [ ] no prep create/copy/upload unless asked +- [ ] never guess tools/paths → list / `--help` / `references/`; 404 → stop; + `jf api` product prefix (`/artifactory`, `/xray`, …) +- [ ] **Tier A** hard rules: Cautious execution + Server selection + Gotchas + Tier A floor (interactive / `--server-id` retry / stop-on-error / + `--quiet`) +- [ ] **Tier B** (only if next action is `jf api` / AQL / advanced CLI I/O): + full `cli-gotchas.md`, `jf-api.md`, `preserving-command-output.md`, + `cli-command-discovery.md` diff --git a/skills/jfrog/references/INDEX.md b/skills/jfrog/references/INDEX.md new file mode 100644 index 0000000..c005c53 --- /dev/null +++ b/skills/jfrog/references/INDEX.md @@ -0,0 +1,83 @@ +# Reference index — when to read which file + +**Tier A** = `SKILL.md` At-a-glance floor (before first non-exempt `jf`). +**Tier B** = four files below — **MUST** before `jf api` / AQL / advanced CLI +I/O / MCP-via-shell; **not** before every CLI or `jf setup`. +**Tier C** = domain entries — ≤2–3 most specific; skip unused. Login / CLI +install when needed. + +Paths relative to skill root. List **every** `references/` file (except this +one). CI: `tests/jfrog/test_reference_index_contract.py`. + +--- + +## Tier B — path-gated (MUST before `jf api` / advanced CLI) + +Ordinary CLI / `jf setup` → Tier A only. Skipping any below on a Tier B path = +hard-rule violation. + +- **Gotchas / caveats / do-don'ts**: **MUST** `references/cli-gotchas.md` on Tier B — not replaceable by SKILL.md Tier A floor +- **`jf api` prefixes / flags / GraphQL**: **MUST** `references/jf-api.md` before `jf api` +- **Temp files / `$$` / no re-fetch**: **MUST** `references/preserving-command-output.md` before advanced I/O +- **Namespaces / top-level cmds / Pipelines sunset**: **MUST** `references/cli-command-discovery.md` when discovery beyond `--help` + +Tier C (when needed — not Tier B): + +- **Login / add server**: `references/jfrog-login-flow.md` +- **CLI install / upgrade / `jq` missing**: `references/jfrog-cli-install-upgrade.md` + +--- + +## Domain / on-demand (INDEX navigation) + +Load the most specific file for the task. Avoid more than 2–3 reference files +for one operation. + +## Cross-domain + +- **Disambiguating a JFrog entity, understanding entity types, or planning operations that span multiple products**: read `references/jfrog-entity-index.md`, then follow pointers to the relevant domain file +- **Looking up documentation URLs**: read `references/jfrog-url-references.md` + +## Artifactory + +- **Repository types, artifacts, builds, properties, or permission targets (concepts)**: read `references/artifactory-entities.md` +- **Stored packages, package versions, version locations, or the metadata layer over Artifactory (concepts)**: read `references/stored-packages-entities.md` +- **Repo, file, build, permission, user/group, or replication operations**: if the JFrog MCP server exposes a tool for the operation, prefer it. For CLI/API fallback, read `references/artifactory-operations.md` (for **listing builds** use AQL with `limit`/`offset` — see § *Listing build names*; for **full build detail** use `GET /api/build//?project=` — see § *Retrieving full build info*) +- **AQL queries**: read `references/artifactory-aql-syntax.md` +- **Artifactory REST beyond the CLI, structured JSON templates (replacing interactive wizards), or any Artifactory API gap**: read `references/artifactory-api-gaps.md` + +## Xray & security + +- **Watches, policies, violations, components, or vulnerability scanning (concepts)**: read `references/xray-entities.md` +- **Exposures scanning results (secrets, IaC, service misconfigurations, application security risks)**: read `references/xray-entities.md` § Exposures (Advanced Security) +- **Curation audit events (approved/blocked packages, dry-run policy evaluations, curation export)**: read `references/xray-entities.md` § Curation audit events + +## Release lifecycle & distribution + +- **Release bundles, lifecycle stages, distribution, or evidence (concepts)**: read `references/release-lifecycle-entities.md` +- **Applications, application versions, releasables, promotions, or AppTrust (concepts)**: read `references/apptrust-entities.md` + +## Catalog + +- **Public or custom catalog, package metadata, vulnerability advisories, licenses, OpenSSF, or MCP services (concepts)**: if the JFrog MCP server exposes a catalog tool, prefer it for single-package lookups. For deeper queries, read `references/catalog-entities.md` +- **CVE details, vulnerability lookup by CVE ID, or severity/affected-packages/fix-versions for a specific CVE**: prefer an MCP vulnerability-lookup tool if the JFrog MCP server exposes one. Otherwise read `references/onemodel-query-examples.md` § *Public security domain* for the `searchVulnerabilities` query shape — this is self-contained; do not load the `jfrog-package-safety-and-download` skill for pure CVE lookups + +## OneModel (GraphQL) + +- **GraphQL queries** (applications, packages, evidence, release bundles, catalog, cross-domain, or "list/search my" platform entities): read `references/onemodel-graphql.md` +- **Query templates and domain-specific examples**: read `references/onemodel-query-examples.md` +- **Pagination, filtering, GraphQL variables, or date formatting**: read `references/onemodel-common-patterns.md` + +## Platform administration + +- **Platform structure, project/repo membership, or project roles vs environments (concepts)**: read `references/platform-access-entities.md` +- **Access tokens, stats, projects, or system health**: read `references/platform-admin-operations.md` +- **Managing JFrog Projects, members, or environments**: read `references/projects-api.md` +- **Platform REST beyond the CLI, or any platform-level API gap**: read `references/platform-admin-api-gaps.md` + +## General patterns + +- **Batching, parallel Shell calls, or launching subagents**: read `references/general-parallel-execution.md` +- **Large or parallel data gathering, list-vs-detail APIs, cache hygiene**: read `references/general-bulk-operations-and-agent-patterns.md` +- **Standalone HTML report with JFrog-aligned styling**: read `references/jfrog-brand-html-report.md` +- **Reusable gotchas from past tasks**: read or extend `references/general-use-case-hints.md` diff --git a/skills/jfrog/references/apptrust-entities.md b/skills/jfrog/references/apptrust-entities.md index 6ca5088..d1e014f 100644 --- a/skills/jfrog/references/apptrust-entities.md +++ b/skills/jfrog/references/apptrust-entities.md @@ -4,14 +4,13 @@ When to read this file: - Working with **applications**, **application versions**, or **releasables**. - Querying or managing **application version promotions** through stages. -- Understanding what **sources** (builds, release bundles, other app versions) feed into an application version. -- Using the OneModel GraphQL API with the `applications` query root. +- Understanding **sources** (builds, release bundles, other app versions) feeding an application version. +- OneModel GraphQL with `applications` query root. -AppTrust entities are accessed exclusively via the **OneModel GraphQL API** -(`/onemodel/api/v1/graphql`). There are no CLI commands for this domain. +AppTrust via **OneModel GraphQL API** (`/onemodel/api/v1/graphql`). No CLI. -For the OneModel query workflow (credentials, schema fetch, validation, -execution), read `references/onemodel-graphql.md`. +OneModel workflow (credentials, schema fetch, validation, execution): +`references/onemodel-graphql.md`. ## Entity relationship overview @@ -31,28 +30,26 @@ erDiagram ## Application -The top-level entity representing a software application registered in -AppTrust. Applications belong to a JFrog Project and serve as the -organizational container for tracking versions, ownership, and criticality. +Top-level software application in AppTrust. Belongs to a JFrog Project; +container for versions, ownership, criticality. | Field | Description | |-------|-------------| -| `key` | Unique identifier (referenced as `applicationKey` or `appKey` elsewhere) | -| `projectKey` | JFrog Project this application belongs to | +| `key` | Unique ID (`applicationKey` / `appKey` elsewhere) | +| `projectKey` | JFrog Project | | `displayName` | Human-readable name | | `criticality` | `unspecified`, `low`, `medium`, `high`, `critical` | | `maturityLevel` | `unspecified`, `experimental`, `production`, `end_of_life` | -| `owners` | List of users or groups that own the application | -| `labels` | Key-value pairs for custom categorization | +| `owners` | Owning users/groups | +| `labels` | Key-value categorization | Query: `applications.getApplication(key: "...")` or `applications.searchApplications(where: {...})`. ## Application version -A versioned instance of an application. Each version captures a specific set -of releasable artifacts, their sources, and a promotion history through -lifecycle stages. +Versioned instance of an application — releasable artifacts, sources, promotion +history through lifecycle stages. | Field | Description | |-------|-------------| @@ -61,20 +58,18 @@ lifecycle stages. | `tag` | Optional tag | | `status` | Processing status: `STARTED`, `FAILED`, `COMPLETED`, `DELETING` | | `releaseStatus` | Release maturity: `PRE_RELEASE`, `RELEASED`, `TRUSTED_RELEASE` | -| `currentStageName` | Most recent stage the version has been promoted to (null if never promoted) | +| `currentStageName` | Latest promoted stage (null if never promoted) | | `createdBy`, `createdAt` | Audit fields | | `evidenceSubject` | Evidence attestation anchor (shared across domains) | -The `releaseStatus` field is distinct from `status`: `status` tracks the -version creation process, while `releaseStatus` tracks its release maturity. +`releaseStatus` ≠ `status`: `status` = creation process; `releaseStatus` = release maturity. Query: `applications.getApplicationVersion(applicationKey: "...", version: "...")` or `applications.searchApplicationVersions(where: {...})`. ## Releasable -A deployable unit within an application version — either a **package version** -or an individual **artifact**. +Deployable unit within an application version — **package version** or individual **artifact**. | Field | Description | |-------|-------------| @@ -89,14 +84,12 @@ or an individual **artifact**. | `packageVersionLocation` | Link to `StoredPackageVersionLocation` for package releasables | | `vcsCommit` | VCS commit details (for AppTrust-bound package versions) | -Releasables bridge the application model to the underlying Artifactory -storage. The `packageVersionLocation` field connects to the Stored Packages -domain (see `stored-packages-entities.md`). +Releasables bridge application model to Artifactory storage. `packageVersionLocation` +→ Stored Packages domain (`stored-packages-entities.md`). ## Application version promotion -Records the promotion of an application version from one stage to another. -All promotions are recorded including failed attempts. +Promotion of application version between stages. All attempts recorded including failures. | Field | Description | |-------|-------------| @@ -107,13 +100,12 @@ All promotions are recorded including failed attempts. | `artifacts` | Artifacts included in this promotion (repo + path) | | `messages` | Error messages if the promotion failed | -Promotions use the same environment/stage model as Release Bundle promotions -(see `release-lifecycle-entities.md`) but at the application level. +Same environment/stage model as Release Bundle promotions +(`release-lifecycle-entities.md`), at application level. ## Sources -Sources describe how releasables were assembled into an application version. -Four types exist: +How releasables were assembled into an application version. Four types: | Source type | Fields | Description | |-------------|--------|-------------| @@ -122,8 +114,7 @@ Four types exist: | **ApplicationVersion** | `applicationKey`, `version` | Another application version (composition) | | **Direct** | (none) | Directly included without an associated build or bundle | -Sources appear at both the application version level (all sources) and the -individual releasable level (sources for that specific releasable). +At application version level (all sources) and releasable level (per-releasable sources). ## Artifacts (within application versions) @@ -139,16 +130,12 @@ Individual files within releasables. ## Cross-domain connections -AppTrust entities connect to other domains via the OneModel GraphQL API: +Via OneModel GraphQL: - **Evidence** — `ApplicationVersion.evidenceSubject` and - `ApplicationVersionArtifact.evidenceSubject` link to the Evidence domain - via `EvidenceSubject.fullPath`. This allows querying evidence attached to - app versions and their artifacts. -- **Stored Packages** — `Releasable.packageVersionLocation` links to - `StoredPackageVersionLocation`, connecting the application model to where - packages physically reside in Artifactory. -- **Release Bundles** — source type `ReleaseBundle` references release bundle - name/version from the Release Lifecycle domain. -- **Builds** — source type `Build` references build-info records from - Artifactory. + `ApplicationVersionArtifact.evidenceSubject` → Evidence domain via + `EvidenceSubject.fullPath`. +- **Stored Packages** — `Releasable.packageVersionLocation` → + `StoredPackageVersionLocation` (physical Artifactory location). +- **Release Bundles** — source type `ReleaseBundle` → Release Lifecycle name/version. +- **Builds** — source type `Build` → Artifactory build-info records. diff --git a/skills/jfrog/references/artifactory-api-gaps.md b/skills/jfrog/references/artifactory-api-gaps.md index 1533d8a..c125cf2 100644 --- a/skills/jfrog/references/artifactory-api-gaps.md +++ b/skills/jfrog/references/artifactory-api-gaps.md @@ -1,9 +1,8 @@ # Artifactory API Gaps -Operations available through REST API but not through CLI commands. -Invoke them via `jf api [flags]` (authentication is handled -automatically against the active `jf config` server; see the base skill's -*Invoking platform APIs with `jf api`* section). +REST operations without CLI commands. Invoke via `jf api [flags]` +(auth automatic against active `jf config` server; see base skill +*Invoking platform APIs with `jf api`*). ## Repository management @@ -11,8 +10,7 @@ automatically against the active `jf config` server; see the base skill's ```bash jf api /artifactory/api/repositories/ ``` -Returns the full JSON configuration of a repository. Useful as a template -for creating similar repos. +Full JSON repo config. Useful as template for similar repos. ### List all repositories ```bash @@ -89,7 +87,7 @@ jf api /artifactory/api/search/aql \ -d 'items.find({"repo":"my-repo","name":{"$match":"*.jar"}})' ``` -For remote repository content, query the `-cache` suffixed repo: +Remote repo content — query `-cache` suffixed repo: ```bash jf api /artifactory/api/search/aql \ -X POST -H "Content-Type: text/plain" \ @@ -113,8 +111,8 @@ jf api "/artifactory/api/search/gavc?g=com.example&a=mylib&v=1.0" ## User and group management -User and group operations are handled by the Access service. See -`platform-admin-api-gaps.md` (Users / Groups sections) for the full set. +User/group operations via Access service. See +`platform-admin-api-gaps.md` (Users / Groups sections). ## Metadata calculation @@ -172,10 +170,9 @@ jf api "/artifactory/api/federation/fullSyncAll/" -X POST ### List builds (prefer scoped queries) -**Unscoped** `GET /artifactory/api/build` (no query parameters) can **time -out** on busy instances. Prefer **project-scoped** or **repo-scoped** -listing, then detail GETs. Full flow: read `artifactory-operations.md` -§ *Listing builds when the project key is known*. +**Unscoped** `GET /artifactory/api/build` can **time out** on busy instances. +Prefer project- or repo-scoped listing + detail GETs. Flow: `artifactory-operations.md` +§ *Listing build names*. ```bash # Project scope — build names (latest per name) diff --git a/skills/jfrog/references/artifactory-aql-syntax.md b/skills/jfrog/references/artifactory-aql-syntax.md index b120275..c174a63 100644 --- a/skills/jfrog/references/artifactory-aql-syntax.md +++ b/skills/jfrog/references/artifactory-aql-syntax.md @@ -18,14 +18,14 @@ jf api /artifactory/api/search/aql \ .distinct() ``` -Only `.find()` is required. The others are optional and chainable. -**The chain order above is enforced by the server.** `.include()` must come -before `.sort()`, `.sort()` before `.offset()`, etc. Putting them out of -order (e.g. `.sort()` before `.include()`) produces a parse error. +Only `.find()` is required; others optional and chainable. +**Server enforces the chain order above.** `.include()` before `.sort()`, +`.sort()` before `.offset()`, etc. Out of order (e.g. `.sort()` before +`.include()`) → parse error. -**Mandatory include fields:** `items` requires `"repo","path","name"`; -`builds` requires `"name","number","repo"`. Always include these even when -you only need a subset — narrow results with `jq` post-query instead: +**Mandatory include fields:** `items` → `"repo","path","name"`; `builds` → +`"name","number","repo"`. Always include these even when you need a subset — +narrow with `jq` post-query: ``` items.find({"name":"commons-lang3-3.12.0.jar"}) @@ -35,9 +35,7 @@ items.find({"name":"commons-lang3-3.12.0.jar"}) ## Domains -AQL has 13 queryable domains. Each domain represents a different entity type -and has its own set of fields. - +13 queryable domains — each entity type has its own fields. | Domain | Query name | Description | | -------------------- | ------------------- | ---------------------------------------------- | @@ -55,12 +53,10 @@ and has its own set of fields. | Release bundles | `releases` | Release bundle records | | Release bundle files | `release_artifacts` | Files within a release bundle | - ## Domain relationships -Domains connect through the following join paths. Cross-domain queries -traverse these links — fields from related domains can appear in criteria -and include clauses by prefixing the domain path. +Join paths below. Cross-domain queries traverse these links — related-domain +fields in criteria/includes use a prefixed domain path. ```mermaid erDiagram @@ -79,15 +75,12 @@ erDiagram release_artifacts }o--|| releases : "belongs to" ``` - - -**Key:** Items connect to build artifacts and dependencies through SHA-1 -checksum matching, not a direct key. This means a cross-domain query from -items to builds traverses: items → artifacts → modules → builds. +**Key:** Items ↔ build artifacts/dependencies via SHA-1 checksum match (not +a direct key). Path items → builds: items → artifacts → modules → builds. ### Cross-domain field paths -To reference a field from a related domain, use dot-separated domain paths: +Related-domain field → dot-separated domain path: ``` items.find({"artifact.module.build.name":"my-build"}) @@ -108,12 +101,11 @@ From builds: ## Fields by domain -Field types: `string`, `date`, `int`, `long`, `itemType` (`file`, `folder`, -or `any`). Fields marked "default" are returned without explicit `.include()`. +Types: `string`, `date`, `int`, `long`, `itemType` (`file`, `folder`, `any`). +"Default" = returned without explicit `.include()`. ### items - | Field | Type | Default | | --------------- | -------- | ------- | | `repo` | string | yes | @@ -133,23 +125,19 @@ or `any`). Fields marked "default" are returned without explicit `.include()`. | `original_md5` | string | no | | `original_sha1` | string | no | - -Computed field: `virtual_repos` — returns virtual repositories that include -the item's actual repository. Must use `.include("virtual_repos")` explicitly; -requires `repo`, `path`, `name` in the result set. +Computed: `virtual_repos` — virtual repos that include the item's actual +repo. Requires `.include("virtual_repos")` plus `repo`,`path`,`name` in +the result set. ### properties - | Field | Type | Default | | ------- | ------ | ------- | | `key` | string | yes | | `value` | string | yes | - ### stats - | Field | Type | Default | | ---------------------- | ------ | ------- | | `downloads` | int | yes | @@ -161,20 +149,16 @@ requires `repo`, `path`, `name` in the result set. | `remote_origin` | string | yes | | `remote_path` | string | yes | - ### item.infos - | Field | Type | Default | | ------------------- | ------ | ------- | | `props_modified` | date | yes | | `props_modified_by` | string | yes | | `props_md5` | string | yes | - ### builds - | Field | Type | Default | | ------------- | ------ | ------- | | `url` | string | yes | @@ -187,18 +171,14 @@ requires `repo`, `path`, `name` in the result set. | `modified_by` | string | yes | | `repo` | string | no | - ### modules - | Field | Type | Default | | ------ | ------ | ------- | | `name` | string | yes | - ### artifacts - | Field | Type | Default | | ------ | ------ | ------- | | `name` | string | yes | @@ -206,10 +186,8 @@ requires `repo`, `path`, `name` in the result set. | `sha1` | string | yes | | `md5` | string | yes | - ### dependencies - | Field | Type | Default | | ------- | ------ | ------- | | `name` | string | yes | @@ -218,19 +196,15 @@ requires `repo`, `path`, `name` in the result set. | `sha1` | string | yes | | `md5` | string | yes | - ### build.properties - | Field | Type | Default | | ------- | ------ | ------- | | `key` | string | yes | | `value` | string | yes | - ### build.promotions - | Field | Type | Default | | ------------ | ------ | ------- | | `created` | date | yes | @@ -240,19 +214,15 @@ requires `repo`, `path`, `name` in the result set. | `comment` | string | yes | | `user` | string | yes | - ### module.properties - | Field | Type | Default | | ------- | ------ | ------- | | `key` | string | yes | | `value` | string | yes | - ### releases - | Field | Type | Default | | -------------- | --------------------------- | ------- | | `name` | string | yes | @@ -263,18 +233,14 @@ requires `repo`, `path`, `name` in the result set. | `type` | string (`SOURCE`, `TARGET`) | yes | | `storing_repo` | string | yes | - ### release_artifacts - | Field | Type | Default | | ------ | ------ | ------- | | `path` | string | yes | - ## Comparators - | Operator | Meaning | Example | | ---------- | -------------------------------- | ------------------------------------ | | `$eq` | Equals (default if omitted) | `{"type":"file"}` | @@ -288,16 +254,13 @@ requires `repo`, `path`, `name` in the result set. | `$lt` | Less than | `{"size":{"$lt":"5000"}}` | | `$lte` | Less than or equal | `{"modified":{"$lte":"2025-01-01"}}` | - ### Boolean operators - | Operator | Description | | -------- | ---------------------------------------------------------------------- | | `$and` | All conditions must match (implicit when fields are at the same level) | | `$or` | Any condition must match | - ``` items.find({"$and":[ {"repo":"my-repo"}, @@ -310,22 +273,18 @@ items.find({"$and":[ ### Relative date comparators -AQL supports relative date queries with `$last` and `$before`: - +`$last` / `$before` for relative dates: | Operator | Meaning | Example | | --------- | ------------------------------------------------------- | ------------------------------- | | `$last` | Within the last N period (equivalent to `$gt` from now) | `{"modified":{"$last":"7d"}}` | | `$before` | Before the last N period (equivalent to `$lt` from now) | `{"created":{"$before":"3mo"}}` | - -Supported units: `d` (days), `w` (weeks), `mo` (months), `y` (years), -`s` (seconds), `mi` (minutes), `ms` (milliseconds). +Units: `d`, `w`, `mo`, `y`, `s`, `mi`, `ms`. ### Multi-property AND -To match items that have property A=1 **and** property B=2 (different -property rows), use `$and` with `@` shorthand: +Match property A=1 **and** B=2 (different property rows) with `$and` + `@`: ``` items.find({"$and":[ @@ -334,20 +293,18 @@ items.find({"$and":[ ]}) ``` -AQL also documents a `$msp` (multi-set property) operator for this purpose, -but `$msp` is **unreliable in practice** — it returns 0 results on many -server versions even when matching items exist. Prefer `$and` with `@` -shorthand, which is verified to work correctly. +`$msp` (multi-set property) is **unreliable in practice** — often 0 results +even when matches exist. Prefer `$and` + `@` (verified). ## Date queries -Dates use ISO 8601 format for absolute dates: +Absolute dates → ISO 8601: ``` items.find({"modified":{"$gt":"2025-06-01T00:00:00.000Z"}}) ``` -Or use relative dates (preferred — avoids hardcoding timestamps): +Or relative dates (preferred — no hardcoded timestamps): ``` items.find({"modified":{"$last":"30d"}}) @@ -356,9 +313,9 @@ items.find({"created":{"$before":"6mo"}}) ## Property queries -Two equivalent syntaxes for property filtering: +Two equivalent property-filter syntaxes: -**`@key` shorthand** — concise, works for single property conditions: +**`@key` shorthand** — concise, single property conditions: ``` items.find({"repo":"my-repo","@build.name":"my-build","type":"file"}) @@ -374,15 +331,8 @@ items.find({ }) ``` -**Multi-property AND** — use `$and` with `@` shorthand to match across -different property rows: - -``` -items.find({"$and":[ - {"@build.name":"my-build"}, - {"@build.number":"42"} -]}) -``` +**Multi-property AND** — same `$and` + `@` pattern as +[Multi-property AND](#multi-property-and) above (do not re-copy here). > **Note:** The `@key` shorthand works inside `$and`. For `$or`, use the > explicit `property.key`/`property.value` form if the shorthand does not @@ -390,15 +340,12 @@ items.find({"$and":[ ## Include -Select which fields to return. Without `.include()`, AQL returns each -domain's default field set. +Fields to return. No `.include()` → domain defaults. -**When you use `.include()`, you replace the defaults — so you must -explicitly list any required fields:** +**`.include()` replaces defaults — list every required field:** -- `items` domain: always include `"repo","path","name"` (server rejects -the query otherwise) -- `builds` domain: always include `"name","number","repo"` +- `items`: always `"repo","path","name"` (else server rejects) +- `builds`: always `"name","number","repo"` ``` items.find({"repo":"my-repo"}) @@ -421,14 +368,14 @@ items.find({"repo":"my-repo"}) .limit(50) ``` -Sort directions: `$asc`, `$desc`. Sort fields must also appear in the result -set (explicit `.include()` or default fields). See +Sort: `$asc` / `$desc`. Sort fields must appear in the result set +(explicit `.include()` or defaults). See [Before constructing a query](#before-constructing-a-query) for sort performance rules. ## Distinct -Deduplicate result rows: +Deduplicate rows: ``` items.find({"repo":"my-repo"}).distinct(true) @@ -436,41 +383,37 @@ items.find({"repo":"my-repo"}).distinct(true) ## Validation rules -The server enforces these constraints — violating them produces an error: +Server constraints — violations → error: -**Non-admin users:** +**Non-admin:** -- `items` domain queries must include `repo`, `path`, `name` in results -(needed for permission filtering) -- `builds` domain queries must include `name`, `number`, `repo` in results +- `items` results must include `repo`, `path`, `name` (permission filtering) +- `builds` results must include `name`, `number`, `repo` -**Transitive mode** (`.transitive()` for querying through virtual repos): +**Transitive** (`.transitive()` through virtual repos): -- Only works with `items` domain +- `items` domain only - Include subdomains limited to `items` and `properties` -- Repo criteria must use `$eq` (exact match) with a single repository -- No `offset` or `sort` allowed +- Repo criteria: `$eq` only, single repository +- No `offset` or `sort` ## Before constructing a query -Run through these checks before writing any AQL query: - -1. **Never `.sort()` without a `repo` filter** — forces a full table scan - across all repositories. Sort client-side with `jq` instead. Also, - `.sort()` on cross-domain fields (e.g. `stat.downloads` in `items.find()`) - is silently ignored — fetch all rows and sort client-side. -2. **Always set `.limit()`** — no built-in default limit; unbounded queries - can time out or OOM. Broad queries without a `repo` filter are especially - expensive. -3. **`range.total` = returned count, not total matching** — AQL has no - count-only mode. To find the true total, paginate with `.offset()` until - a page returns fewer results than the limit. -4. **AQL has no repo-type field** — to restrict to local repos, either - pre-query `GET /api/repositories?type=local` and add repo names to - criteria (practical when count is small), or query without a repo filter - and exclude `-cache` / `-virtual` suffixed repos client-side with `jq`. +Checks before writing AQL: + +1. **Never `.sort()` without a `repo` filter** — full table scan. Sort + client-side with `jq`. Cross-domain sort fields (e.g. `stat.downloads` in + `items.find()`) are silently ignored — fetch all + sort client-side. +2. **Always `.limit()`** — no default; unbounded queries can time out / OOM. + Broad queries without `repo` are especially expensive. +3. **`range.total` = returned count, not total matching** — no count-only + mode. True total → paginate `.offset()` until a page returns fewer than + the limit. +4. **No repo-type field** — local-only: pre-query + `GET /api/repositories?type=local` and add names to criteria (small lists), + or query without repo filter and drop `-cache`/`-virtual` via `jq`. 5. **Narrow server-side first** — add every applicable filter (`created_by`, - `created`, `type`, `name`) before relying on client-side `jq` filtering. + `created`, `type`, `name`) before client-side `jq`. ## Common query patterns @@ -488,8 +431,8 @@ items.find({"repo":"my-repo","size":{"$gt":"104857600"},"type":"file"}) ### Find Maven SNAPSHOT JARs -Use `*-SNAPSHOT*.jar` (not `*-SNAPSHOT.jar`) to also match classifier -artifacts like `-sources.jar` and `-javadoc.jar`: +Use `*-SNAPSHOT*.jar` (not `*-SNAPSHOT.jar`) to also match classifiers +(`-sources.jar`, `-javadoc.jar`): ``` items.find({"repo":"libs-snapshot","name":{"$match":"*-SNAPSHOT*.jar"},"type":"file"}) @@ -505,9 +448,9 @@ items.find({"repo":"my-repo","modified":{"$last":"7d"},"type":"file"}) ### Docker queries -Use `"name":"manifest.json"` to **list tags** (one per tag). Use -`"name":{"$match":"*manifest.json"}` to **query all manifests** (includes -`list.manifest.json` for multi-arch tags — see [Gotchas](#gotchas)). +`"name":"manifest.json"` → **list tags** (one per tag). +`"name":{"$match":"*manifest.json"}` → **all manifests** (includes +`list.manifest.json` for multi-arch — see [Gotchas](#gotchas)). ``` items.find({"repo":"docker-local","path":{"$match":"my-image/*"},"name":"manifest.json"}) @@ -523,18 +466,16 @@ jf api "/artifactory/api/docker//v2//manifests/" \ -H "Accept: application/vnd.docker.distribution.manifest.v2+json" ``` -For multi-arch images the response is an image index; fetch each platform -manifest by digest to get its layers. +For multi-arch: response is an image index — fetch each platform manifest +by digest for layers. ### Find artifacts with a specific property -``` -items.find({"repo":"my-repo","@build.name":"my-build","type":"file"}) -``` +See [Property queries](#property-queries) (`@key` shorthand and explicit form). ### Find never-downloaded files (zero download count) -Zero-download items lack a stats row — filter client-side instead +Zero-download items lack a stats row — filter client-side (see [Gotchas](#gotchas)): ```bash @@ -547,8 +488,8 @@ items.find({"repo":"my-repo","type":"file"}) ### Find artifacts not downloaded in 90 days -Only matches previously-downloaded items (see [Gotchas](#gotchas)). -Combine with the never-downloaded pattern above for full coverage. +Only previously-downloaded items (see [Gotchas](#gotchas)). Combine with +never-downloaded pattern above for full coverage. ``` items.find({ @@ -569,8 +510,7 @@ items.find({"artifact.module.build.name":"my-service"}) ### Find builds by name -Non-admin users must include `name`, `number`, `repo` — omitting any -produces an error. +Non-admin must include `name`, `number`, `repo` — omit any → error. ``` builds.find({"name":{"$match":"*my-service*"}}) @@ -595,8 +535,8 @@ dependencies.find({"module.build.name":"my-service","module.build.number":"42"}) ### Remote repository content -Remote repo artifacts are stored in a `-cache` suffixed repo. Always query -the cache repo, not the remote repo itself: +Remote artifacts live in a `-cache` suffixed repo. Query the cache, not the +remote itself: ``` items.find({"repo":"npm-remote-cache","name":{"$match":"*.tgz"}}) diff --git a/skills/jfrog/references/artifactory-entities.md b/skills/jfrog/references/artifactory-entities.md index 1e4d950..59e650b 100644 --- a/skills/jfrog/references/artifactory-entities.md +++ b/skills/jfrog/references/artifactory-entities.md @@ -2,44 +2,39 @@ When to read this file: -- Working with **repositories** and you need to understand the difference between local, remote, virtual, and federated types. +- Working with **repositories** — need local/remote/virtual/federated type differences. - Managing **artifacts**, **properties**, or **package types**. - Working with **builds**, **build promotion**, or **permission targets**. -- Debugging unexpected behavior related to repo types (e.g. upload failures, missing search results). +- Debugging repo-type issues (e.g. upload failures, missing search results). -For CLI commands see `artifactory-operations.md`. For API gaps see -`artifactory-api-gaps.md`. For AQL syntax see `artifactory-aql-syntax.md`. +CLI: `artifactory-operations.md`. API gaps: `artifactory-api-gaps.md`. AQL: `artifactory-aql-syntax.md`. ## Repositories -A repository is the primary storage and resolution unit in Artifactory. Every -repo has a **key** (unique identifier), a **package type** (immutable after -creation), and a **repository class** (`rclass`) that determines its behavior. +Repository = primary storage/resolution unit in Artifactory. Each repo has **key** (unique id), **package type** (immutable after creation), **repository class** (`rclass`) determining behavior. ### Repository types | Type | `rclass` | Behavior | Stores artifacts? | |------|----------|----------|-------------------| | **Local** | `local` | Hosts artifacts deployed directly (upload, promote, copy, move) | Yes | -| **Remote** | `remote` | Proxies an external URL; downloads are cached in a companion `-cache` repo | Only in the `-cache` repo | -| **Virtual** | `virtual` | Aggregates multiple local and remote repos under a single URL for resolution | No (resolves from underlying repos) | -| **Federated** | `federated` | Local repo that bi-directionally synchronizes across Platform Deployments | Yes (replicated across sites) | +| **Remote** | `remote` | Proxies external URL; downloads cached in companion `-cache` repo | Only in `-cache` repo | +| **Virtual** | `virtual` | Aggregates local + remote repos under single URL for resolution | No (resolves from underlying repos) | +| **Federated** | `federated` | Local repo bi-directionally syncs across Platform Deployments | Yes (replicated across sites) | ### Key relationships and fields - `key` — unique repo identifier (e.g. `libs-release-local`) -- `packageType` — determines layout and protocol (see Package types below) +- `packageType` — layout + protocol (see Package types below) - `rclass` — `local`, `remote`, `virtual`, or `federated` -- `url` — (remote only) the external source URL being proxied +- `url` — (remote only) external source URL being proxied - `repositories` — (virtual only) ordered list of local/remote repos to aggregate -- `projectKey` — links repo to a JFrog Project (see `platform-access-entities.md`) -- `environments` — environments the repo is assigned to (used in RBAC and lifecycle) +- `projectKey` — links repo to JFrog Project (see `platform-access-entities.md`) +- `environments` — repo environment assignment (RBAC + lifecycle) ### System repositories -Artifactory and Xray maintain several **system repositories** for internal -platform metadata. These are not user-created and should be excluded when -iterating over repositories for reporting, scanning, or auditing: +Artifactory + Xray maintain **system repositories** for internal platform metadata. Not user-created — exclude when iterating repos for reporting, scanning, or auditing: | Pattern | Purpose | |---------|---------| @@ -51,34 +46,23 @@ iterating over repositories for reporting, scanning, or auditing: | `*-build-info` | Project-scoped build info storage | | `*-application-versions` | AppTrust application version metadata | -Including these in aggregate queries (violation counts, storage reports, etc.) -produces misleading results because they contain platform metadata rather than -user artifacts. +Including these in aggregate queries (violation counts, storage reports, etc.) produces misleading results — platform metadata, not user artifacts. ### Remote repository cache -When Artifactory downloads an artifact through a remote repo, it stores the -cached copy in a **separate local repo** named `-cache`. This is -critical for: +When Artifactory downloads via remote repo, cached copy stored in **separate local repo** named `-cache`. Critical for: -- **AQL queries** — search the `-cache` repo, not the remote repo key -- **Properties** — properties on cached artifacts live on the `-cache` repo -- **Storage calculations** — cached artifacts consume storage under the `-cache` repo +- **AQL queries** — search `-cache` repo, not remote repo key +- **Properties** — cached artifact properties live on `-cache` repo +- **Storage calculations** — cached artifacts consume storage under `-cache` repo -The remote repo key itself is used for **configuration** (URL, credentials, -inclusion/exclusion patterns) but does not directly contain artifacts. +Remote repo key used for **configuration** (URL, credentials, inclusion/exclusion patterns) — does not directly contain artifacts. ### Virtual repository resolution -A virtual repo aggregates **both local and remote repos** under a single URL. -It resolves artifacts by searching its underlying repos in the configured -**order** — when the same artifact exists in multiple underlying repos, the -first match wins. +Virtual repo aggregates **local + remote repos** under single URL. Resolves by searching underlying repos in configured **order** — same artifact in multiple repos → first match wins. -A virtual repo may designate one of its underlying **local** repos as the -**default deployment repository**. Uploads through the virtual URL are routed -to that local repo. Without a default deployment repo, the virtual repo is -read-only. +Virtual repo may designate underlying **local** repo as **default deployment repository**. Uploads through virtual URL routed there. Without default deployment repo → read-only. ```mermaid erDiagram @@ -90,65 +74,56 @@ erDiagram ## Artifacts -An artifact is a file stored in a repository. Each artifact is uniquely -identified by the triple **repo + path + name**. +Artifact = file in repository. Uniquely identified by **repo + path + name**. Key attributes: - `repo`, `path`, `name` — location identifier - `size` — bytes -- `sha256`, `sha1`, `md5` — checksums (sha256 is the primary identifier for cross-referencing with builds and Xray) +- `sha256`, `sha1`, `md5` — checksums (build-info records all three; Xray cross-references by sha256, AQL item↔build joins by sha1) - `created`, `modified`, `created_by`, `modified_by` — audit fields -Artifacts are **content-addressable** — build info and Xray reference them by -checksum, not by path. Moving or copying an artifact changes its path but not -its checksum, so build associations follow the artifact. +Artifacts are **content-addressable** — build info + Xray reference by checksum, not path. Move/copy changes path, not checksum → build associations follow artifact. ## Properties -Key-value metadata pairs attached to artifacts or folders. +Key-value metadata on artifacts or folders. -- Keys are strings; values are strings or arrays of strings -- Set via `jf rt set-props`, queried via AQL or the properties API -- Commonly used for: build metadata, maturity labels, promotion tracking, cleanup policies -- Properties on remote-cached artifacts live on the `-cache` repo +- Keys = strings; values = strings or string arrays +- Set via `jf rt set-props`, query via AQL or properties API +- Common uses: build metadata, maturity labels, promotion tracking, cleanup policies +- Remote-cached artifact properties live on `-cache` repo ## Package types -The `packageType` field on a repository determines how Artifactory interprets -its contents. It controls directory structure conventions, metadata extraction, -and which client protocols are supported (e.g. Docker registry API, npm -registry, Maven layout). +`packageType` on repo determines how Artifactory interprets contents — directory layout, metadata extraction, client protocols (Docker registry API, npm registry, Maven layout). Common types: `maven`, `gradle`, `npm`, `docker`, `pypi`, `nuget`, `go`, `helm`, `rpm`, `debian`, `generic`. -Package type is **immutable** — it cannot be changed after repo creation. Use -`generic` when no specific package type applies. +Package type **immutable** — cannot change after repo creation. Use `generic` when no specific type applies. ## Build info -A build info record captures CI/CD metadata: which artifacts were produced, -which dependencies were consumed, and the build environment. +Build info record captures CI/CD metadata: produced artifacts, consumed dependencies, build environment. | Field | Description | |-------|-------------| -| `name` + `number` | Unique identifier for a build run | -| `modules` | List of modules, each with its own artifacts and dependencies | -| `vcs` | Version control metadata (revision, URL, branch) | +| `name` + `number` | Unique build run identifier | +| `modules` | Modules, each with artifacts + dependencies | +| `vcs` | VCS metadata (revision, URL, branch) | | `buildAgent`, `agent` | CI tool info | | `properties` | Custom build-level properties | -Build info references artifacts **by checksum** (sha256). This means: -- A build can reference artifacts across multiple repositories -- Moving an artifact does not break the build association -- Xray scans build info by resolving checksums to components +Build info references artifacts **by checksum** (AQL item↔build joins by sha1; Xray cross-references by sha256): +- Build can reference artifacts across multiple repos +- Moving artifact does not break build association +- Xray scans build info by resolving checksums → components Lifecycle: collect → publish → (optionally) promote → (optionally) scan. ## Build promotion -Promotion changes a build's **status** and can copy or move its artifacts -from a source repo to a target repo. +Promotion changes build **status**; can copy/move artifacts from source repo → target repo. | Field | Description | |-------|-------------| @@ -157,18 +132,15 @@ from a source repo to a target repo. | `targetRepo` | Where artifacts should be moved/copied | | `copy` | If `true`, copy instead of move | -Promotion records are queryable via AQL (`build.promotions` domain) and the -build promotion API. +Promotion records queryable via AQL (`build.promotions` domain) + build promotion API. ## Permissions -Permissions define RBAC policies mapping **resources** and **principals** -(users and groups) to **actions**. Two models exist: +Permissions = RBAC policies mapping **resources** + **principals** (users, groups) → **actions**. Two models: ### Permissions V2 (Access Permissions) — current model -Managed by the **Access service** (since Artifactory 7.72.0, recommended from -7.77.2). Supports all resource types. +**Access service** (since 7.72.0, recommended 7.77.2+). All resource types. | Component | Description | |-----------|-------------| @@ -179,11 +151,11 @@ Resource types: `artifact` (repositories), `build`, `release_bundle`, `destination` (Edge nodes), `pipeline_source`. Each resource contains: -- `targets` — map of target names/patterns to include/exclude patterns -- `actions.users` — map of username → list of actions -- `actions.groups` — map of group name → list of actions +- `targets` — target names/patterns → include/exclude patterns +- `actions.users` — username → action list +- `actions.groups` — group name → action list -Actions use uppercase: `READ`, `ANNOTATE`, `DEPLOY/CACHE`, `DELETE/OVERWRITE`, +Actions uppercase: `READ`, `ANNOTATE`, `DEPLOY/CACHE`, `DELETE/OVERWRITE`, `MANAGE_XRAY_METADATA`, `MANAGE`. API: `POST/PUT/GET/DELETE /access/api/v2/permissions/{permissionName}`. @@ -192,17 +164,15 @@ Documentation: [Permissions](https://docs.jfrog.com/administration/docs/permissi ### Permission targets (V1) — legacy model -Managed by **Artifactory**. Still functional and backwards compatible, but -V2 is recommended for new implementations. The CLI `jf rt permission-target-*` -commands use this API. +**Artifactory**-managed. Functional + backwards compatible; prefer V2 for new work. CLI: `jf rt permission-target-*`. | Component | Description | |-----------|-------------| -| `repositories` | List of repo keys or patterns | -| `actions.users` | Map of username → list of actions | -| `actions.groups` | Map of group name → list of actions | +| `repositories` | Repo keys or patterns | +| `actions.users` | Username → action list | +| `actions.groups` | Group name → action list | -Actions use lowercase: `read`, `write`, `annotate`, `delete`, `manage`. +Actions lowercase: `read`, `write`, `annotate`, `delete`, `manage`. Does **not** support `destination` or `pipeline_source` resource types. @@ -219,18 +189,15 @@ API: `PUT /artifactory/api/security/permissions/{permissionName}`. | Pattern fields | `includes_pattern` / `excludes_pattern` | `include_patterns` / `exclude_patterns` | | CLI support | `jf rt permission-target-*` | No direct CLI commands (use REST) | -For project-scoped RBAC, see Project roles in `platform-access-entities.md`. +Project-scoped RBAC: see Project roles in `platform-access-entities.md`. ## Replication -Replication synchronizes artifacts and properties between repositories, either -within the same instance or across Platform Deployments. +Replication syncs artifacts + properties between repos — same instance or across Platform Deployments. | Type | Direction | Trigger | |------|-----------|---------| -| **Push** | Source pushes to target | Scheduled or event-based | -| **Pull** | Target pulls from source | Scheduled | +| **Push** | Source → target | Scheduled or event-based | +| **Pull** | Target ← source | Scheduled | -Replication configs are JSON templates applied per repository. Both artifact -content and properties are replicated. For federated repos, replication is -automatic and bi-directional across all member nodes. +Replication configs = JSON templates per repository. Both artifact content + properties replicated. Federated repos → automatic bi-directional replication across member nodes. diff --git a/skills/jfrog/references/artifactory-operations.md b/skills/jfrog/references/artifactory-operations.md index bab2b65..771584b 100644 --- a/skills/jfrog/references/artifactory-operations.md +++ b/skills/jfrog/references/artifactory-operations.md @@ -1,22 +1,20 @@ # Artifactory Operations -CLI commands for managing Artifactory resources. All commands use the `jf rt` -namespace. Run `jf rt --help` to discover subcommands not listed here. +CLI for Artifactory resources — `jf rt` namespace. Run `jf rt --help` for subcommands not listed here. ## Repository management -Repositories are created from JSON templates. The workflow is: +Repos from JSON templates: -1. Get a template: retrieve an existing repo config via +1. Get template: existing config via `jf api /artifactory/api/repositories/` - and modify it, or craft JSON manually. + and modify, or craft JSON manually. Note: `jf rt repo-template` is interactive and cannot be used by agents. 2. Create: `jf rt repo-create ` 3. Update: `jf rt repo-update ` 4. Delete: `jf rt repo-delete --quiet` -To list repositories, use: -`jf api /artifactory/api/repositories` +List: `jf api /artifactory/api/repositories` ## File operations @@ -31,12 +29,12 @@ To list repositories, use: ### Searching across repositories -`jf rt search` expects a `/` argument. When the repo is unknown, -agents tend to use a leading wildcard (`jf rt search "*/path/..."`), which -generates an unscoped AQL internally and can time out on large instances. +`jf rt search` expects `/`. When repo unknown, agents often use +leading wildcard (`jf rt search "*/path/..."`) → unscoped AQL internally → +timeouts on large instances. -Use a direct AQL query with `name` and `path` criteria instead — omitting the -`repo` field searches all accessible repos via indexed columns: +Use direct AQL with `name` and `path` — omitting `repo` searches all accessible +repos via indexed columns: ```bash jf api /artifactory/api/search/aql \ @@ -47,21 +45,16 @@ jf api /artifactory/api/search/aql \ }).include("repo","path","name","size","sha256")' ``` -Add `"repo":""` to the criteria when the target repo is known, to -narrow the search further. +Add `"repo":""` when target repo is known. ## Build info -**Project scoping rule:** Append `?project=` to **every** build detail -API call. When the user provides a project key, use it. When no project key -is provided, use `?project=default` (the built-in default project that covers -the `artifactory-build-info` repo). For AQL queries, scope by -`"repo":"-build-info"` (or `"repo":"artifactory-build-info"` for -the default project). +**Project scoping:** `?project=` on **every** build detail call. User key +→ use it; else `?project=default`. AQL: `"repo":"-build-info"` or +`"repo":"artifactory-build-info"` for default. -**Server rule:** A 404 from a `?project=` build call is **not** a signal -to try a different server. Use only the resolved server; on any failure, -report and stop. See `SKILL.md` § *Server selection rules*. +**Server rule:** 404 on `?project=` ≠ try another server. Resolved server +only; on failure report and stop. See `SKILL.md` § *Server selection rules*. ### Publishing builds @@ -73,8 +66,8 @@ report and stop. See `SKILL.md` § *Server selection rules*. ### Listing build names -**Do not use `GET /api/build`** — it has no pagination and times out on large -instances. Always use AQL with `limit` and `offset`. +**Do not use `GET /api/build`** — no pagination; times out on large instances. +Always AQL with `limit` and `offset`. **All builds** (no project scope): @@ -84,9 +77,8 @@ jf api /artifactory/api/search/aql \ -d 'builds.find().include("name","number","repo","created").sort({"$desc":["created"]}).offset(0).limit(100)' ``` -**Project-scoped** — filter by the project's build-info repository -(`-build-info`, or `artifactory-build-info` for the default -project): +**Project-scoped** — filter by build-info repo +(`-build-info`, or `artifactory-build-info` for default project): ```bash jf api /artifactory/api/search/aql \ @@ -94,19 +86,14 @@ jf api /artifactory/api/search/aql \ -d 'builds.find({"repo":"-build-info"}).include("name","number","repo","created").sort({"$desc":["created"]}).offset(0).limit(100)' ``` -**Pagination:** The response includes a `range` object with `total` (total -matching records). If `total` exceeds the `limit`, tell the user: *"Showing +**Pagination:** `range.total` vs `limit` → if exceeded, tell user: *"Showing first 100 of N results (paginated). Ask for the next batch if needed."* -For subsequent pages, increment `offset` by 100. +Increment `offset` by 100 per page. -**Output rule (mandatory):** AQL returns one row per name+number pair. -Extract **unique build names** client-side (e.g. -`jq '[.[].builds.name] | unique'`). Present **only the deduplicated list of -build names** to the user. **Do not** include build numbers, timestamps, run -counts, or any per-run details in the response — not even as a "bonus" or -"most recent" table. The user is asking "what builds exist", not "what runs -happened". Only show run-level details if the user explicitly asks for them -in a follow-up. +**Output rule (mandatory):** AQL = one row per name+number. Extract **unique +build names** client-side (e.g. `jq '[.results[].builds.name] | unique'`). Present +**only deduplicated names** — no numbers, timestamps, run counts, or per-run +details (not even "bonus"/"most recent" table). Run details only if explicitly requested. ### Listing runs of a specific build @@ -116,35 +103,29 @@ jf api /artifactory/api/search/aql \ -d 'builds.find({"name":""}).include("name","number","repo","created").sort({"$desc":["created"]}).offset(0).limit(100)' ``` -Add `"repo":"-build-info"` to the criteria when a project key -is known. Apply the same pagination rules as above. +Add `"repo":"-build-info"` when project key known. Same pagination rules. ### Retrieving full build info -Use the REST detail endpoint for a **single** build run. Always include -`?project=` (or `?project=default` when no key is provided): +REST detail endpoint for a **single** run. Always include `?project=` +(or `?project=default` when no key): ```bash jf api "/artifactory/api/build//?project=" ``` -This is the only `/api/build` endpoint that should be used — it returns a -single record and does not need pagination. +Only `/api/build` endpoint to use — single record, no pagination. ### When a build is not found -If the detail call returns 404, the build likely belongs to a different -project. **Ask the user for the project key** rather than searching across -repos or servers. +404 on detail call → build likely in different project. **Ask user for project +key** — do not search across repos or servers. ### Repository listing vs build-info `GET /artifactory/api/repositories?project=&type=buildinfo` may return -an empty list even when project-scoped build info exists (for example under -a `*-build-info` repository). Prefer AQL to -discover builds; do not treat an empty repository -list as proof that no -builds exist. +empty list even when project-scoped build info exists (e.g. under `*-build-info`). +Prefer AQL to discover builds; empty repository list ≠ no builds. ## Permissions @@ -164,7 +145,7 @@ Note: `jf rt permission-target-template` is interactive. - Delete group: `jf rt group-delete ` - Add users to group: `jf rt group-add-users ` -To get user details or update users, use `jf api`: +User details/update via `jf api`: ``` jf api /access/api/v2/users/ ``` diff --git a/skills/jfrog/references/catalog-entities.md b/skills/jfrog/references/catalog-entities.md index 085bea0..f8e9a87 100644 --- a/skills/jfrog/references/catalog-entities.md +++ b/skills/jfrog/references/catalog-entities.md @@ -3,40 +3,36 @@ When to read this file: - Querying **public package metadata** (descriptions, vulnerabilities, licenses, operational info). -- Working with the **Custom Catalog** (org-specific labels, package views, federation). -- Looking up **vulnerability details** beyond what Xray provides (advisories, EPSS, CWE, known exploits). +- Working with **Custom Catalog** (org-specific labels, package views, federation). +- Looking up **vulnerability details** beyond Xray (advisories, EPSS, CWE, known exploits). - Querying **OpenSSF scorecards**, **ML model metadata**, or **MCP service** registries. -- Using the OneModel GraphQL API with `publicPackages`, `customPackages`, +- Using OneModel GraphQL with `publicPackages`, `customPackages`, `publicSecurityInfo`, `publicLegalInfo`, `publicOperationalInfo`, `publicCatalogLabels`, or `publicRemoteServices` query roots. -Catalog entities are accessed via the **OneModel GraphQL API** -(`/onemodel/api/v1/graphql`). +Catalog entities via **OneModel GraphQL API** (`/onemodel/api/v1/graphql`). -For the OneModel query workflow (credentials, schema fetch, validation, -execution), read `references/onemodel-graphql.md`. +OneModel query workflow (credentials, schema fetch, validation, execution): `references/onemodel-graphql.md`. ## Two catalog layers | Layer | Scope | Description | |-------|-------|-------------| -| **Public Catalog** | Global | JFrog's curated package database — security, legal, and operational metadata for public packages across ecosystems | -| **Custom Catalog** | Organization | Org-specific overlay — custom labels, per-org package views, federation config | +| **Public Catalog** | Global | JFrog global package DB — security, legal, operational metadata across ecosystems | +| **Custom Catalog** | Organization | Org overlay: custom labels, per-org views, federation config | -The Custom Catalog builds on top of the Public Catalog. A public package -can be enriched with org-specific labels and metadata through the Custom -Catalog without altering the underlying public data. +Custom Catalog overlays Public Catalog — org labels/metadata without changing public data. ## Public Catalog entities ### PublicPackage -A package as known to JFrog's global package database. +Package in JFrog global package database. | Field | Description | |-------|-------------| -| `name` | Package name (e.g. `lodash`, `spring-boot-starter-web`) | -| `type` | Package type (e.g. `npm`, `maven`, `pypi`) | +| `name` | Package name (`lodash`, `spring-boot-starter-web`) | +| `type` | Package type (`npm`, `maven`, `pypi`) | | `ecosystem` | Ecosystem identifier | | `description` | Rich-text description | | `homepage`, `vcsUrl` | Package URLs | @@ -53,12 +49,12 @@ Query: `publicPackages.searchPackages(where: {...})`. ### PublicPackageVersion -A specific version with security, legal, and operational analysis. +Specific version with security, legal, operational analysis. | Field | Description | |-------|-------------| | `version` | Version string | -| `isLatest` | Whether this is the latest version | +| `isLatest` | Whether latest version | | `isListedVersion` | Whether visible in Catalog UI | | `publishedAt`, `modifiedAt` | Timestamps | | `trendingScore` | Version-level popularity | @@ -72,76 +68,71 @@ Each version carries three info blocks: ### PublicVulnerability -Vulnerability data richer than what Xray violations expose. Useful for -deep-dive security analysis and advisory lookups. +Richer vulnerability data than Xray violations — deep-dive analysis + advisory lookups. | Field | Description | |-------|-------------| -| `name` | CVE identifier (e.g. `CVE-2021-44228`) | +| `name` | CVE id (`CVE-2021-44228`) | | `ecosystem` | Affected ecosystem | | `severity` | `CRITICAL`, `HIGH`, `MEDIUM`, `LOW` | | `description` | Detailed impact description | | `cvss` | CVSS scores — v2, v3, **and v4** | -| `epss` | EPSS (Exploit Prediction Scoring System) — exploit likelihood | -| `knownExploit` | Known exploit information | -| `withdrawn` | Whether the CVE has been retracted | +| `epss` | EPSS exploit likelihood | +| `knownExploit` | Known exploit info | +| `withdrawn` | CVE retracted | | `aliases` | Alternative identifiers | | `references` | Advisory URLs | | `publishedAt`, `modifiedAt` | Timestamps | -Advisory sources (via `advisories` connection): -- **NVD** — NIST National Vulnerability Database +Advisory sources (`advisories` connection): +- **NVD** — NIST vulnerability DB - **GHSA** — GitHub Security Advisory -- **JFrog Advisory** — JFrog's own research (includes impact reasons) +- **JFrog Advisory** — JFrog research (impact reasons) - **Debian Security Tracker** - **RedHat OVAL** Additional connections: `cwesConnection` (CWE entries), `cpesConnection` -(CPE entries), `publicPackageInfo` (affected packages and versions). +(CPE entries), `publicPackageInfo` (affected packages + versions). Query: `publicSecurityInfo.searchVulnerabilities(where: {...})`. #### Filtering limitations -`searchVulnerabilities` can filter by CVE name, ecosystem, severity, CVSS, -EPSS, known exploit status, and publication date — but **not** by affected -package name. There is no `hasPublicPackageInfoWith` or similar filter on -`PublicVulnerabilityWhereInput`. To find vulnerabilities affecting a specific -package, use one of these alternatives: +`searchVulnerabilities` filters by CVE name, ecosystem, severity, CVSS, +EPSS, known exploit status, publication date — but **not** by affected +package name. No `hasPublicPackageInfoWith` or similar filter on +`PublicVulnerabilityWhereInput`. To find vulnerabilities affecting specific +package, use alternatives: - **Version-level security info** (GraphQL): query - `publicPackages.getPackage(type, name)` and navigate to - `versionsConnection → securityInfo → vulnerabilitiesConnection` to get + `publicPackages.getPackage(type, name)` → + `versionsConnection → securityInfo → vulnerabilitiesConnection` for CVEs affecting specific versions. -- **Individual CVE lookup**: use `searchVulnerabilities(where: { name: "" })` - and inspect `publicPackageInfo.vulnerablePublicPackagesConnection` on the +- **Individual CVE lookup**: `searchVulnerabilities(where: { name: "" })` + → inspect `publicPackageInfo.vulnerablePublicPackagesConnection` on `generic` ecosystem entry. #### Ecosystem multiplicity -A single CVE appears as multiple `PublicVulnerability` entries — one per -ecosystem. The `ecosystem` field determines which entry you see: +Single CVE → multiple `PublicVulnerability` entries (one per ecosystem). `ecosystem` field determines entry: | Ecosystem | Contains | |-----------|----------| -| `generic` | Non-OS package-level data (npm, maven, pypi, go, etc.) — includes `publicPackageInfo` with vulnerable versions and fix versions | -| `debian`, `redhat`, `ubuntu`, etc. | OS-specific advisory data — severity may differ from NVD; `publicPackageInfo` is typically empty (OS packages are tracked separately) | +| `generic` | Non-OS package-level data (npm, maven, pypi, go, etc.) — includes `publicPackageInfo` with vulnerable + fix versions | +| `debian`, `redhat`, `ubuntu`, etc. | OS-specific advisory data — severity may differ from NVD; `publicPackageInfo` typically empty (OS packages tracked separately) | -When looking up a CVE by name, `searchVulnerabilities(where: { name: "" })` -returns all ecosystem entries. To get affected packages and fix versions for -libraries like npm or maven, filter for or focus on the `generic` ecosystem -entry. `getVulnerability` requires both `name` and `ecosystem` — use -`searchVulnerabilities` when the ecosystem is unknown. +CVE lookup by name: `searchVulnerabilities(where: { name: "" })` +returns all ecosystem entries. For npm/maven library affected packages + fix versions → filter/focus on `generic` entry. `getVulnerability` requires `name` + `ecosystem` — use `searchVulnerabilities` when ecosystem unknown. ### PublicLicense -License metadata with permission, condition, and limitation details. +License metadata with permission, condition, limitation details. | Field | Description | |-------|-------------| -| `name` | License name (e.g. `Apache-2.0`, `MIT`) | +| `name` | License name (`Apache-2.0`, `MIT`) | | `spdxId` | SPDX identifier | -| `permissions` | What the license permits | +| `permissions` | What license permits | | `limitations` | Restrictions imposed | | `patentConditions` | Patent grant conditions | | `noticeFiles` | Required notices | @@ -150,23 +141,23 @@ Query: `publicLegalInfo.searchLicenses(where: {...})`. ### PublicPackageOperationalInfo -Operational risk assessment for packages and versions. +Operational risk assessment for packages + versions. | Entity | Key data | |--------|----------| -| **OpenSSF scorecard** | Overall score, individual checks with scores and pass/fail | -| **End-of-life** | Whether the package or version is EOL, justification | -| **Popularity** | JFrog popularity by segment and subscription tier, download counts | +| **OpenSSF scorecard** | Overall score + check scores/pass-fail | +| **End-of-life** | Package/version EOL status + justification | +| **Popularity** | JFrog popularity by segment/tier, download counts | ### MCP services and tools -The Public Catalog also indexes MCP (Model Context Protocol) services: +Public Catalog also indexes MCP (Model Context Protocol) services: | Entity | Description | |--------|-------------| -| `PublicMcpService` | An MCP service with name, description, version | -| `PublicMcpTool` | A tool exposed by an MCP service with arguments | -| `PublicMcpRemote` | Remote MCP server configuration | +| `PublicMcpService` | MCP service: name, description, version | +| `PublicMcpTool` | MCP service tool + arguments | +| `PublicMcpRemote` | Remote MCP server config | Query: `publicRemoteServices.searchMcpServices(where: {...})`. @@ -174,7 +165,7 @@ Query: `publicRemoteServices.searchMcpServices(where: {...})`. ### CustomPackage -A package in the organization's private catalog view. +Package in org private catalog view. | Field | Description | |-------|-------------| @@ -188,27 +179,25 @@ Connections: `versionsConnection`, `legalInfo`, ### CustomCatalogLabel -Organization-defined labels for categorizing packages. +Org-defined labels for categorizing packages. | Field | Description | |-------|-------------| | `name` | Label name | -| `description` | What the label represents | +| `description` | What label represents | | `color` | Display color | | `labelType` | `MANUAL` or `AUTOMATIC` | -| `assignmentInfo` | How and when the label was assigned | +| `assignmentInfo` | How/when label assigned | -Labels can be assigned to both custom packages and public packages/versions -within the org's catalog scope. The Custom Catalog mutations allow -creating, updating, and deleting labels. +Labels assignable to custom packages + public packages/versions within org catalog scope. Custom Catalog mutations: create, update, delete labels. ### CustomCatalogFederation -Configuration for federating catalog data across JFrog deployments. +Config for federating catalog data across JFrog deployments. ## Catalog vs. Xray vs. Stored Packages -These three domains provide different views of package and security data: +Three domains, different views of package + security data: | Aspect | Catalog | Xray | Stored Packages | |--------|---------|------|-----------------| diff --git a/skills/jfrog/references/cli-command-discovery.md b/skills/jfrog/references/cli-command-discovery.md new file mode 100644 index 0000000..bbe6263 --- /dev/null +++ b/skills/jfrog/references/cli-command-discovery.md @@ -0,0 +1,39 @@ +# CLI command discovery + +> **Tier B MUST** when discovery beyond `--help` is needed. Not every CLI / setup. + +Use `--help` to verify uncertain options. Do not rely on memorized commands +outside this skill — they may be outdated. + +1. `jf --help` — namespaces and top-level commands +2. `jf --help` — subcommands in a namespace +3. `jf --help` — usage, arguments, options + +## CLI namespaces + +| Namespace | Alias | Product | +|-----------|-------|---------| +| `rt` | | Artifactory | +| `xr` | | Xray | +| `ds` | | Distribution V1 | +| `at` | `apptrust` | AppTrust | +| `evd` | | Evidence | +| `mc` | | Mission Control | +| `worker` | | Workers | +| `config` | `c` | CLI server configuration | +| `plugin` | | CLI plugin management | +| `ide` | | IDE integration | + +> **Sunset notice:** JFrog Pipelines has been sunset and is no longer supported. +> Do not use the `pl` CLI namespace or the Pipelines REST API +> (`/pipelines/api/...`). If a user asks about Pipelines, inform them the +> product has been sunset. + +Top-level lifecycle commands (no namespace): `rbc`, `rbp`, `rbd`, `rba`, +`rbf`, `rbe`, `rbi`, `rbs`, `rbu`, `rbdell`, `rbdelr`. + +Top-level security commands: `audit`, `scan`, `build-scan`, `curation-audit`, +`sbom-enrich`. + +Top-level other: `access-token-create` (`atc`), `login`, `how`, `stats`, +`generate-summary-markdown`, `exchange-oidc-token`, `completion`. diff --git a/skills/jfrog/references/cli-gotchas.md b/skills/jfrog/references/cli-gotchas.md new file mode 100644 index 0000000..410b205 --- /dev/null +++ b/skills/jfrog/references/cli-gotchas.md @@ -0,0 +1,80 @@ +# CLI and `jf api` gotchas + +> **Tier B MUST** before `jf api` / AQL / advanced CLI I/O / MCP-via-shell. +> Not tips. Not required for every CLI / `jf setup` (use SKILL.md Tier A floor). +> Tier A bullets do **not** replace this file on Tier B paths. + +Hard rules and known failure modes: + +## MCP tools + +- MCP tools return structured data in the tool result. Read response fields + directly; do not pipe MCP output through shell commands or `jq`. + +## CLI and `jf api` + +- `jf api` requires the **product prefix** in the path. Omitting it returns + 404. See `references/jf-api.md` for the full product-prefix table. +- `jf api` writes the body (success or error JSON) to **stdout** and + `[Info] Http Status: NNN` to **stderr** on every call; non-2xx also exits + 1 and adds `[Warn] jf api: returned NNN`. Pipe stdout to + `jq` directly; **never `2>&1 | jq`** — stderr corrupts the JSON. To keep + diagnostics: `jf api 2>/tmp/err-$$.log | jq .`. +- `jf api` has **no `-L`** (follow redirects) and **no `-o`** (output file). + Save bodies with shell redirection + (`jf api ... > /tmp/out-$$.json`); for + binary downloads through the Artifactory remote proxy prefer `jf rt dl`, + which handles the cache and redirect semantics natively. +- Remote repository content is stored in a `-cache` suffixed repo. Properties + and AQL queries for remote repo artifacts must target the cache repo. + Conversely, `/api/repositories/` only accepts the parent remote key + (without `-cache`) — strip the suffix for configuration lookups. +- **Do not use `jf rt search`** — always use a direct AQL query via + `jf api /artifactory/api/search/aql -X POST -H "Content-Type: text/plain" -d ''`. + See `references/artifactory-aql-syntax.md`. +- Use `--quiet` flag for non-interactive execution (suppresses confirmation + prompts). **Caution:** `--quiet` is not a global flag — commands that do not + support it (e.g. `jf rt s`, `jf rt ping`) will fail with misleading errors + like "Wrong number of arguments" or "flag provided but not defined". Check + `--help` for a command before adding `--quiet`. +- Use `--server-id` when targeting a non-default server. If a command fails + with `--server-id`, do not retry without it — that silently targets the + default server instead. See `SKILL.md` → Server selection rules. +- Never use interactive commands. All JFrog CLI operations must be performed + non-interactively. Known interactive commands to avoid: `jf config add`, + `jf login`, `jf rt repo-template`, `jf rt permission-target-template`, and + `jf rt replication-template`. For server setup, follow `references/jfrog-login-flow.md`. + For templates, use JSON schemas or REST API. If a command prompts for input + unexpectedly, find the non-interactive alternative via `--help` or REST API. +- `jf config export` output is base64-encoded JSON. Decode with + `base64 -d | jq` to extract fields. +- Build info lookups require a scope (`?buildRepo=` or `?project=`) — + resolve it before calling the API. See `references/artifactory-operations.md` + §Retrieving build info for the full workflow. +- If a `jf api` call returns 401, the configured token may have expired or + been rotated — ask the user to re-run the login flow (see + `references/jfrog-login-flow.md`) for the **same** server. If 403, the + token lacks required permissions. If 404, verify the endpoint path + (especially the product prefix) and target server version. On any of + these errors, do not try a different configured server as a workaround — + that targets a different environment. Report the error and ask the user. +- **Xray contextual analysis:** the summary artifact response has two + applicability fields — `applicability` (top-level, often null) and + `applicability_details` (always present with a `result` string). **Use + `applicability_details[].result` for counts and summaries.** Using the + top-level `applicability` field for aggregation produces wrong counts because + it is null when no scanner exists. See `references/xray-entities.md` + §Contextual analysis for the eight possible result values and jq snippets. +- **OneModel GraphQL:** always fetch the supergraph schema from the **same** + server you query before building operations (schemas differ by deployment); + cache, validate, and execute per `references/onemodel-graphql.md`. +- Never duplicate a network-fetching command to retry `jq` parsing — save the + response to a temp file first (see `references/preserving-command-output.md`). +- When collecting detail responses in a loop (e.g. per-repo GETs), validate + each body with `jq -e .` before appending to a results file. One non-JSON + or empty response corrupts a downstream `jq -s` slurp. Write validated + lines to an NDJSON file, then `jq -s '.' file.ndjson` to produce the final + array. See `references/general-bulk-operations-and-agent-patterns.md`. +- Accumulated edge cases from real tasks live in `references/general-use-case-hints.md` + — read when debugging odd failures; **append** a short entry when you confirm + a new, reusable gotcha. diff --git a/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md b/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md index 2b44979..2fe30f4 100644 --- a/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md +++ b/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md @@ -1,70 +1,55 @@ # Bulk operations and agent execution patterns -Platform-wide guidance for agents that gather data from multiple JFrog products -(Artifactory, Xray, Access, Distribution, etc.), run long shell -sequences, or parallelize work. Product-specific field names and endpoints live -in the other `references/*` files; this document describes **patterns**, not -one workflow. +Platform-wide guidance for agents gathering data from multiple JFrog products +(Artifactory, Xray, Access, Distribution, etc.), long shell sequences, or +parallel work. Product field names/endpoints in other `references/*` files; +this document = **patterns**, not one workflow. ## List vs detail responses -Many REST surfaces expose a **light list** (keys, names, minimal fields) and a -**richer GET by id or key**. Fields needed for audits, reporting, joins, or -permission checks may appear **only** on the detail response. Before building a -multi-step flow on a single list call, confirm in API docs or with a sample GET -whether the fields you need are present. +REST: **light list** + **detail GET**. Audit/join/permission fields often +detail-only — confirm via docs or sample GET before building on list alone. ## Volume, batching, and timeouts -- Estimate **N** round-trips (list + per-item GETs, paginated APIs, etc.) before - starting so execution time and tool timeouts stay predictable. -- Prefer batching independent reads in one Shell invocation when credentials and - tier match (see SKILL.md **Batch and parallel execution**). -- Split very large work across chunks, parallel Shell calls, or subagents when - the skill's tiering guidance says so. -- Before starting an N+1 loop (list + per-item detail), **estimate wall time** - as roughly `N * 1.5s` for sequential calls. Set `block_until_ms` to at - least that estimate plus a 30-second buffer. -- For loops exceeding ~60 items, prefer a single Shell invocation that writes - progress to a log file (`>> /tmp/jf-progress-$$.log`) so partial results - are visible even if the job is interrupted. -- If the task is read-only and items are independent, consider Tier 2 or - Tier 3 parallelism (see `general-parallel-execution.md`) to reduce total time — - but respect rate limits and keep concurrency modest (4-8 parallel calls). +- Estimate **N** round-trips before starting. +- Batch independent reads in one Shell when credentials/tier match (SKILL.md + **Batch and parallel execution**). +- Large work → chunks, parallel Shell, or subagents per tiering. +- N+1 loop: wall time ≈ `N * 1.5s`; `block_until_ms` ≥ estimate + 30s. +- > ~60 items: Shell + progress log (`>> /tmp/jf-progress-$$.log`). +- Read-only independent items: Tier 2/3 (`general-parallel-execution.md`); + rate limits; 4-8 parallel calls. ## Parallelism and shared files -**Unsafe:** Multiple concurrent processes appending lines to the **same** file -(JSONL, logs, ndjson) without synchronization. Output can interleave on one -line and break parsers (e.g. JSON "Extra data" errors). +**Unsafe:** Concurrent processes appending to **same** file (JSONL, logs, ndjson) +without sync → interleaved lines, broken parsers (JSON "Extra data" errors). **Safer:** - Write sequentially to one file; or - One temp file per worker or chunk, then concatenate; or -- Use advisory locking (`flock`) if one file must be shared. +- Advisory locking (`flock`) if one file must be shared. -For bulk API or CLI output files, use `/tmp` or `mktemp`; do not use -`~/.jfrog/skills-cache/` except for `jfrog-skill-state.json` and the OneModel -schema file (see main SKILL.md). +Bulk API/CLI output: `/tmp` or `mktemp`; not `~/.jfrog/skills-cache/` except +`jfrog-skill-state.json` and OneModel schema (main SKILL.md). ## Shell hygiene -- Use `set -euo pipefail` in non-trivial scripts so failures are not silent. -- Use unique temp paths (e.g. `$$` in the filename) and **echo the expanded - path** so it can be reused across Shell calls (see SKILL.md **Preserving - command output** for the `$$` + echo, session ID, and hardcoded patterns). -- Parse CLI and API JSON with **`jq`**. +- `set -euo pipefail` in non-trivial scripts — failures not silent. +- Unique temp paths (`$$` in filename) + **echo expanded path** for cross-call + reuse (SKILL.md **Preserving command output** — `$$` + echo, session ID, hardcoded patterns). +- Parse CLI/API JSON with **`jq`**. ## Safe multi-response collection -When looping over items (repos, builds, users) and fetching detail for each: +Looping items (repos, builds, users) + per-item detail: -1. Save each response to a variable or per-item file. +1. Save each response to variable or per-item file. 2. Validate with `jq -e . >/dev/null 2>&1` before appending. -3. On validation failure, write a structured error line so the caller can - report partial results instead of crashing. -4. After the loop, `jq -s '.' results.ndjson` to produce a single array. +3. On validation failure, structured error line → partial results without crash. +4. After loop, `jq -s '.' results.ndjson` → single array. ```bash : >results.ndjson @@ -79,8 +64,7 @@ done < <(jq -r '.[].key' list.json) jq -s '.' results.ndjson > details.json ``` -Never pipe a loop of `jf api` calls directly into `jq -s` without -per-body validation. +Never pipe loop of `jf api` calls directly into `jq -s` without per-body validation. ## Where to find product specifics diff --git a/skills/jfrog/references/general-parallel-execution.md b/skills/jfrog/references/general-parallel-execution.md index a0bb9ba..42bb48d 100644 --- a/skills/jfrog/references/general-parallel-execution.md +++ b/skills/jfrog/references/general-parallel-execution.md @@ -1,20 +1,17 @@ # Batch and Parallel Execution -When a task requires multiple independent operations, use the lightest -parallelism mechanism that fits. Three tiers are available, from lightest to -heaviest: +Multiple independent operations → use lightest parallelism tier: | Tier | Mechanism | Best for | |------|-----------|----------| | 1 | Single Shell call with `&&` | Few commands, same credentials | -| 2 | Parallel Shell tool calls | Independent commands that can run concurrently | -| 3 | Parallel subagents (Task tool) | Large multi-step jobs where each branch needs its own reasoning | +| 2 | Parallel Shell tool calls | Independent commands, concurrency helps | +| 3 | Parallel subagents (Task tool) | Large multi-step jobs, each branch needs reasoning | ## Tier 1: Batch within a single Shell call -Combine independent commands with `&&`. All JFrog API calls go through the -same `jf api` command and the same `jf config` server, so batching them -together is both safe and efficient: +Combine independent commands with `&&`. All JFrog API calls share `jf api` + +`jf config` server — batching is safe and efficient: ```bash jf api /artifactory/api/repositories > /tmp/jf-repos-$$.json && \ @@ -32,8 +29,8 @@ jf api /access/api/v2/permissions/ > /tmp/jf-perms-$$.json ## Tier 2: Parallel Shell tool calls -Use multiple Shell tool calls in the same message when the commands are -independent and the total runtime benefits from concurrency: +Multiple Shell tool calls in one message when commands are independent and +concurrency cuts runtime: ```bash # Shell call 1 — echo the expanded path so the agent can reference it later @@ -45,20 +42,13 @@ OUT=/tmp/jf-users-$$.json jf api /access/api/v2/users/ > "$OUT" && echo "$OUT" ``` -Each parallel Shell call gets a different PID, so `$$` expands to different -values. Echo the path so the agent knows the literal filename for cross-call -use (see SKILL.md **Preserving command output**). +Each parallel Shell call gets different PID → `$$` differs. Echo path for +cross-call use (see SKILL.md **Preserving command output**). ## Tier 3: Parallel subagents -For tasks with multiple independent branches that each require several steps -or their own reasoning — such as generating a platform health report with -separate sections, auditing both repository config and security policies, or -comparing configurations across servers the user explicitly named — launch -parallel subagents using the Task tool. - -Each subagent runs autonomously, executes its own CLI/API calls, and returns -a structured result. The parent agent assembles the final answer. +Multi-branch tasks (health reports, audits, user-named cross-server compare) +→ Task tool subagents. Each runs autonomously; parent merges results. ### Example — platform audit with three parallel subagents @@ -80,26 +70,20 @@ Subagent 3 (shell): "Collect user and permission data" → Return user count, group count, admin users ``` -All three subagents run concurrently. Once all complete, the parent agent -merges their results into a unified report. +All three run concurrently. Parent merges into unified report. ### How to structure a subagent prompt -1. State the goal clearly (e.g. "Collect all Xray policies and watches"). -2. Provide the exact commands to run, or name the API tier and let the - subagent discover via `--help`. -3. Tell the subagent to save output to `/tmp/jf-