[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6N9RD0GSPRHHB1WGDPNDM69":3,"skill-same:01M6N9RD0GSPRHHB1WGDPNDM69":69},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":54,"install":55,"resources":68},"01M6N9RD0GSPRHHB1WGDPNDM69","bubbles-supply-chain-source-locking",null,"Lock build-time dependency resolution to an explicit allowlist of trusted registries\u002Fsources so dependencies can never be pulled from an arbitrary or implicit upstream. Use when adding or editing a dependency manifest or lockfile (Cargo.toml\u002FCargo.lock, package.json\u002Fpackage-lock.json, go.mod\u002Fgo.sum, requirements.txt\u002Fconstraints); when configuring a package-source file (cargo-deny config, .npmrc, GOPROXY\u002FGOFLAGS env, pip index config); when wiring or reviewing a lint\u002Fpre-push gate that touches dependency installation; when reviewing a PR that adds a new external dependency, a new registry, or a git\u002Fpath dependency; or when investigating dependency-confusion, typosquat, or malicious-mirror risk. Distinct from deploy-time artifact provenance (cosign\u002FSLSA\u002FSBOM\u002FTrivy) — see \"Two Axes\" below.","pkirsanov\u002Fsmackerel","pkirsanov","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F138962?v=4","01M6N8NAPD2KXMVC17X6GJ0WZ5","01M6N8NATQ9SAZ00H9D61R0TPV",1,"MIT","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-supply-chain-source-locking\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"bubbles supply chain source locking","source","supply","supply chain","chain","time","wiring","npmrc","lock","sum","sources","malicious","artifact","dependency","never","SBOM","lockfile","registry","git","config","2026-11-10 10:12:30",false,"---\nname: bubbles-supply-chain-source-locking\ndescription: Lock build-time dependency resolution to an explicit allowlist of trusted registries\u002Fsources so dependencies can never be pulled from an arbitrary or implicit upstream. Use when adding or editing a dependency manifest or lockfile (Cargo.toml\u002FCargo.lock, package.json\u002Fpackage-lock.json, go.mod\u002Fgo.sum, requirements.txt\u002Fconstraints); when configuring a package-source file (cargo-deny config, .npmrc, GOPROXY\u002FGOFLAGS env, pip index config); when wiring or reviewing a lint\u002Fpre-push gate that touches dependency installation; when reviewing a PR that adds a new external dependency, a new registry, or a git\u002Fpath dependency; or when investigating dependency-confusion, typosquat, or malicious-mirror risk. Distinct from deploy-time artifact provenance (cosign\u002FSLSA\u002FSBOM\u002FTrivy) — see \"Two Axes\" below.\n---\n\n# Bubbles Supply-Chain Source Locking\n\n## Goal\n\nMake every build resolve its dependencies from an **explicit, reviewed allowlist of\ntrusted sources** — never from an arbitrary, implicit, or fall-through upstream. The\nbuild inputs are as governed as the build outputs.\n\nThe single sentence: **a dependency can only enter the build from a source you\nexplicitly allowed.**\n\n## Use This Skill When\n\n- Adding or editing a dependency manifest or lockfile (`Cargo.toml`\u002F`Cargo.lock`,\n  `package.json`\u002F`package-lock.json`, `go.mod`\u002F`go.sum`, `requirements.txt`\u002Fconstraints).\n- Configuring a package-source file (`cargo-deny` config, `.npmrc`, `GOPROXY`\u002F`GOFLAGS`,\n  pip index configuration).\n- Wiring or reviewing a lint \u002F pre-push gate that installs or resolves dependencies.\n- Reviewing a PR that adds a new external dependency, a new registry, or a `git`\u002Fpath\n  dependency.\n- Investigating dependency-confusion, typosquatting, or malicious-mirror exposure.\n\n## Core Rule (NON-NEGOTIABLE)\n\n> Dependency resolution MUST be locked to an explicit allowlist of trusted\n> registries\u002Fsources. Arbitrary or implicit upstream sources are forbidden.\n> The enforcement is BLOCKING — there is no `--skip` \u002F `--force` \u002F `--allow-once`.\n\nA manifest that can silently resolve a package from an un-allowlisted index, a second\n(\"extra\") index, a `git`\u002F`path` source, or an implicit fall-through proxy is a blocking\nfinding — even if today's lockfile happens to point at a trusted source. The control is\nthe *source allowlist*, not the current pin.\n\n## Two Axes — Source Locking Is NOT Deploy-Time Provenance\n\nThese are **complementary controls on different axes**. A repo needs BOTH; one never\nsubstitutes for the other.\n\n| Axis | This skill (build-time SOURCE locking) | Deploy-time artifact PROVENANCE |\n|------|----------------------------------------|---------------------------------|\n| Question answered | *Where did the code enter the build from?* | *Is the built artifact authentic, signed, and scanned before it runs?* |\n| Failure it stops | Dependency-confusion, typosquat, malicious mirror, unexpected upstream, second-index fall-through | Tampered\u002Funsigned image, unknown provenance, unscanned CVEs at deploy |\n| Mechanism | Source allowlist in manifest\u002Flockfile config + blocking resolve-source check | Signature + attestation verification at the deploy boundary |\n| Typical tools | cargo-deny `[sources]`, pinned `.npmrc` registry, pinned `GOPROXY` + `go.sum`, pip `--index-url` + hashes | cosign keyless signing, SLSA build-provenance, SBOM attestation, image CVE scan |\n| Owned in Bubbles by | this skill + its instruction; wired into each repo's lint\u002Fpre-push gate | `bubbles-deployment-target-adapter` (see \"See Also\") |\n\nSource locking stops bad inputs from entering the build. Provenance proves the output is\nthe expected, signed, scanned artifact. Do not collapse them: a perfectly signed image\nbuilt from a typosquatted dependency still ships the compromised code.\n\n## Per-Ecosystem Guidance\n\nThe rule is toolchain-agnostic; the wiring is ecosystem-specific. In every case: pin the\nsource allowlist, commit the lockfile, deny implicit fall-through, and wire a **blocking**\ncheck into the repo's existing lint\u002Fpre-push gate.\n\n### Rust \u002F Cargo\n\nUse `cargo-deny`'s `[sources]` section as the source allowlist:\n\n```toml\n# deny.toml\n[sources]\nunknown-registry = \"deny\"        # any registry not in allow-registry => error\nunknown-git = \"deny\"             # any git source not in allow-git => error\nallow-registry = [\"sparse+https:\u002F\u002Findex.crates.io\u002F\"]   # exactly one trusted index\nallow-git = []                   # no git deps unless explicitly allowlisted here\n```\n\n- `allow-registry` SHOULD contain exactly one entry (the canonical first-party index, or\n  the operator's pinned mirror) — not a list of \"wherever it happens to be\".\n- `allow-git = []` by default; every git dependency is an explicit, reviewed exception.\n- Commit `Cargo.lock`.\n- Wire `cargo deny check sources` into the repo's blocking lint\u002Fpre-push gate.\n\n### Node \u002F npm\n\n- Pin the registry in a committed `.npmrc`: `registry=\u003Ctrusted-registry>` (the canonical\n  first-party registry or the operator's pinned mirror).\n- Forbid arbitrary per-package \u002F per-scope registry overrides (`@scope:registry=...`)\n  unless that scope is an explicitly reviewed allowlist entry.\n- Commit `package-lock.json` and install lockfile-strict (`npm ci`), never an unpinned\n  resolve.\n- No implicit fall-through to a second registry; a dependency that resolves only from an\n  un-pinned source is a finding.\n\n### Go\n\n- `GOFLAGS=-mod=readonly` so the build can never silently rewrite `go.mod`\u002F`go.sum`.\n- Pin `GOPROXY` to a single trusted proxy; do not append an open `,direct` fall-through\n  unless that direct fetch path is an explicit, reviewed exception.\n- Commit `go.sum` and verify it (`go mod verify`) in the gate.\n- The checksum-disable knobs `GONOSUMCHECK`, `GONOSUMDB`, `GOINSECURE`, and a permissive\n  `GOPRIVATE` covering public modules are FORBIDDEN — they defeat source verification.\n\n### Python \u002F pip\n\n- Pass an explicit `--index-url` (the trusted index); never rely on the implicit default.\n- FORBID `--extra-index-url` to an un-allowlisted host — it is the classic\n  dependency-confusion vector (pip resolves the highest version across all indexes).\n- Hash-pin every requirement (`--require-hashes` with pinned `==` versions) and commit\n  the locked requirements\u002Fconstraints file.\n\n## Forbidden vs Required\n\n| ❌ Forbidden | ✅ Required |\n|--------------|-------------|\n| Manifest\u002Fconfig that can resolve from any registry not on an allowlist | Explicit single-source (or reviewed multi-entry) allowlist |\n| cargo-deny `unknown-registry`\u002F`unknown-git` unset or `allow` | `unknown-registry = \"deny\"`, `unknown-git = \"deny\"`, populated `allow-registry` |\n| Implicit `,direct` \u002F second-index \u002F extra-index fall-through | One pinned source; every extra source is a reviewed allowlist entry |\n| pip `--extra-index-url` to an un-allowlisted host | Single `--index-url`; hash-pinned, version-pinned requirements |\n| Uncommitted lockfile, or unpinned resolve in CI | Committed lockfile + lockfile-strict install (`npm ci`, `-mod=readonly`) |\n| Checksum\u002Fverification disable knobs (`GONOSUMCHECK`, `GOINSECURE`, `--trusted-host`) | Verification ON; `go.sum`\u002Fhashes verified in the gate |\n| Un-reviewed `git`\u002F`path`\u002FURL dependency | Each such source is an explicit allowlist entry with a recorded reason |\n| A `--skip` \u002F `--force` \u002F `--allow-once` bypass on the source check | Blocking check, no bypass flag |\n\n## Enforcement\n\n- Each downstream repo wires the ecosystem-appropriate source check into its **existing**\n  blocking lint \u002F pre-push gate (the same gate that already runs format\u002Flint). Source\n  locking adds NO new framework gate — it is a policy that each repo's existing gate\n  enforces with the ecosystem's native tool.\n- The check MUST be blocking: an un-allowlisted source, a missing lockfile, a disabled\n  verification knob, or an un-reviewed extra index fails the gate.\n- There is NO bypass flag. A legitimately new trusted source is added by editing the\n  allowlist (a reviewed change), never by skipping the check for one run.\n- New trusted sources are a reviewed config change (allowlist edit), consistent with\n  `bubbles-config-sst` single-source-of-truth governance for registry\u002Flockfile config.\n\n## Verification Commands\n\n```bash\n# Rust: source allowlist is enforced and blocking\ngrep -nE 'unknown-(registry|git)|allow-(registry|git)' deny.toml\n# Expectation: unknown-registry = \"deny\", unknown-git = \"deny\", explicit allow-registry\n\n# Node: registry pinned, lockfile committed, no stray per-scope registry\ngrep -nE '^registry=|:registry=' .npmrc\nls -la package-lock.json\n\n# Go: read-only modules, pinned proxy, no checksum-disable knobs\ngrep -nE 'GOFLAGS|GOPROXY|GONOSUM|GOINSECURE|GOPRIVATE' .env* *.mk Makefile 2>\u002Fdev\u002Fnull\nls -la go.sum\n\n# Python: single index, hash-pinned, no extra index\ngrep -nE -- '--index-url|--extra-index-url|--require-hashes|--trusted-host' requirements*.txt pip.conf 2>\u002Fdev\u002Fnull\n```\n\n## Anti-Patterns (BLOCKING)\n\n| Anti-Pattern | Why It's Wrong | Fix |\n|--------------|---------------|-----|\n| \"The lockfile already points at the trusted source, so we're fine\" | The control is the *source allowlist*, not the current pin; the next resolve can drift | Lock the allowlist, not just today's pin |\n| Adding `--extra-index-url` \"to grab one internal package\" | Dependency-confusion: a public typosquat at a higher version wins | Allowlist the internal index explicitly; pin\u002Fhash the package |\n| Disabling `go.sum` verification to \"unblock a build\" | Defeats source verification entirely | Fix the source\u002Fpin; never disable verification |\n| Treating cosign\u002FSLSA\u002FSBOM as \"we already do supply chain\" | Provenance is a different axis; it does not govern build inputs | Add source locking AND keep provenance |\n| A `--skip-source-check` escape hatch in the gate | First skip becomes the permanent path | Blocking check; new sources via allowlist edit only |\n\n## Integration With Bubbles Governance\n\n| Bubbles Surface | Relevance |\n|-----------------|-----------|\n| `bubbles-config-sst` | Registry\u002Flockfile\u002Fsource config is single-source-of-truth; no scattered or hand-drifted source config |\n| Repo lint \u002F pre-push gate | Hosts the ecosystem source check; blocking, no bypass |\n| `bubbles-deployment-target-adapter` | The complementary deploy-time provenance axis (cosign\u002FSLSA\u002FSBOM\u002FTrivy) |\n| Spec \u002F design authoring | A spec that adds a new external dependency or registry declares the trusted source and any allowlist exception |\n\n## See Also\n\n- [bubbles-supply-chain-source-locking.instructions.md](..\u002F..\u002Finstructions\u002Fbubbles-supply-chain-source-locking.instructions.md) — binding, agent-loaded counterpart\n- [bubbles-deployment-target-adapter skill](..\u002Fbubbles-deployment-target-adapter\u002FSKILL.md) — deploy-time artifact provenance (cosign keyless signing, SLSA build-provenance, SBOM attestation, image CVE scan) — the complementary axis\n- [bubbles-backup-bcdr-doctrine skill](..\u002Fbubbles-backup-bcdr-doctrine\u002FSKILL.md) — offsite\u002Fbackup trust boundaries\n- [bubbles-config-sst skill](..\u002Fbubbles-config-sst\u002FSKILL.md) — single-source-of-truth governance for registry\u002Flockfile config\n","# Bubbles Supply-Chain Source Locking\n\n## Goal\n\nMake every build resolve its dependencies from an **explicit, reviewed allowlist of\ntrusted sources** — never from an arbitrary, implicit, or fall-through upstream. The\nbuild inputs are as governed as the build outputs.\n\nThe single sentence: **a dependency can only enter the build from a source you\nexplicitly allowed.**\n\n## Use This Skill When\n\n- Adding or editing a dependency manifest or lockfile (`Cargo.toml`\u002F`Cargo.lock`,\n  `package.json`\u002F`package-lock.json`, `go.mod`\u002F`go.sum`, `requirements.txt`\u002Fconstraints).\n- Configuring a package-source file (`cargo-deny` config, `.npmrc`, `GOPROXY`\u002F`GOFLAGS`,\n  pip index configuration).\n- Wiring or reviewing a lint \u002F pre-push gate that installs or resolves dependencies.\n- Reviewing a PR that adds a new external dependency, a new registry, or a `git`\u002Fpath\n  dependency.\n- Investigating dependency-confusion, typosquatting, or malicious-mirror exposure.\n\n## Core Rule (NON-NEGOTIABLE)\n\n> Dependency resolution MUST be locked to an explicit allowlist of trusted\n> registries\u002Fsources. Arbitrary or implicit upstream sources are forbidden.\n> The enforcement is BLOCKING — there is no `--skip` \u002F `--force` \u002F `--allow-once`.\n\nA manifest that can silently resolve a package from an un-allowlisted index, a second\n(\"extra\") index, a `git`\u002F`path` source, or an implicit fall-through proxy is a blocking\nfinding — even if today's lockfile happens to point at a trusted source. The control is\nthe *source allowlist*, not the current pin.\n\n## Two Axes — Source Locking Is NOT Deploy-Time Provenance\n\nThese are **complementary controls on different axes**. A repo needs BOTH; one never\nsubstitutes for the other.\n\n| Axis | This skill (build-time SOURCE locking) | Deploy-time artifact PROVENANCE |\n|------|----------------------------------------|---------------------------------|\n| Question answered | *Where did the code enter the build from?* | *Is the built artifact authentic, signed, and scanned before it runs?* |\n| Failure it stops | Dependency-confusion, typosquat, malicious mirror, unexpected upstream, second-index fall-through | Tampered\u002Funsigned image, unknown provenance, unscanned CVEs at deploy |\n| Mechanism | Source allowlist in manifest\u002Flockfile config + blocking resolve-source check | Signature + attestation verification at the deploy boundary |\n| Typical tools | cargo-deny `[sources]`, pinned `.npmrc` registry, pinned `GOPROXY` + `go.sum`, pip `--index-url` + hashes | cosign keyless signing, SLSA build-provenance, SBOM attestation, image CVE scan |\n| Owned in Bubbles by | this skill + its instruction; wired into each repo's lint\u002Fpre-push gate | `bubbles-deployment-target-adapter` (see \"See Also\") |\n\nSource locking stops bad inputs from entering the build. Provenance proves the output is\nthe expected, signed, scanned artifact. Do not collapse them: a perfectly signed image\nbuilt from a typosquatted dependency still ships the compromised code.\n\n## Per-Ecosystem Guidance\n\nThe rule is toolchain-agnostic; the wiring is ecosystem-specific. In every case: pin the\nsource allowlist, commit the lockfile, deny implicit fall-through, and wire a **blocking**\ncheck into the repo's existing lint\u002Fpre-push gate.\n\n### Rust \u002F Cargo\n\nUse `cargo-deny`'s `[sources]` section as the source allowlist:\n\n```toml\n# deny.toml\n[sources]\nunknown-registry = \"deny\"        # any registry not in allow-registry => error\nunknown-git = \"deny\"             # any git source not in allow-git => error\nallow-registry = [\"sparse+https:\u002F\u002Findex.crates.io\u002F\"]   # exactly one trusted index\nallow-git = []                   # no git deps unless explicitly allowlisted here\n```\n\n- `allow-registry` SHOULD contain exactly one entry (the canonical first-party index, or\n  the operator's pinned mirror) — not a list of \"wherever it happens to be\".\n- `allow-git = []` by default; every git dependency is an explicit, reviewed exception.\n- Commit `Cargo.lock`.\n- Wire `cargo deny check sources` into the repo's blocking lint\u002Fpre-push gate.\n\n### Node \u002F npm\n\n- Pin the registry in a committed `.npmrc`: `registry=\u003Ctrusted-registry>` (the canonical\n  first-party registry or the operator's pinned mirror).\n- Forbid arbitrary per-package \u002F per-scope registry overrides (`@scope:registry=...`)\n  unless that scope is an explicitly reviewed allowlist entry.\n- Commit `package-lock.json` and install lockfile-strict (`npm ci`), never an unpinned\n  resolve.\n- No implicit fall-through to a second registry; a dependency that resolves only from an\n  un-pinned source is a finding.\n\n### Go\n\n- `GOFLAGS=-mod=readonly` so the build can never silently rewrite `go.mod`\u002F`go.sum`.\n- Pin `GOPROXY` to a single trusted proxy; do not append an open `,direct` fall-through\n  unless that direct fetch path is an explicit, reviewed exception.\n- Commit `go.sum` and verify it (`go mod verify`) in the gate.\n- The checksum-disable knobs `GONOSUMCHECK`, `GONOSUMDB`, `GOINSECURE`, and a permissive\n  `GOPRIVATE` covering public modules are FORBIDDEN — they defeat source verification.\n\n### Python \u002F pip\n\n- Pass an explicit `--index-url` (the trusted index); never rely on the implicit default.\n- FORBID `--extra-index-url` to an un-allowlisted host — it is the classic\n  dependency-confusion vector (pip resolves the highest version across all indexes).\n- Hash-pin every requirement (`--require-hashes` with pinned `==` versions) and commit\n  the locked requirements\u002Fconstraints file.\n\n## Forbidden vs Required\n\n| ❌ Forbidden | ✅ Required |\n|--------------|-------------|\n| Manifest\u002Fconfig that can resolve from any registry not on an allowlist | Explicit single-source (or reviewed multi-entry) allowlist |\n| cargo-deny `unknown-registry`\u002F`unknown-git` unset or `allow` | `unknown-registry = \"deny\"`, `unknown-git = \"deny\"`, populated `allow-registry` |\n| Implicit `,direct` \u002F second-index \u002F extra-index fall-through | One pinned source; every extra source is a reviewed allowlist entry |\n| pip `--extra-index-url` to an un-allowlisted host | Single `--index-url`; hash-pinned, version-pinned requirements |\n| Uncommitted lockfile, or unpinned resolve in CI | Committed lockfile + lockfile-strict install (`npm ci`, `-mod=readonly`) |\n| Checksum\u002Fverification disable knobs (`GONOSUMCHECK`, `GOINSECURE`, `--trusted-host`) | Verification ON; `go.sum`\u002Fhashes verified in the gate |\n| Un-reviewed `git`\u002F`path`\u002FURL dependency | Each such source is an explicit allowlist entry with a recorded reason |\n| A `--skip` \u002F `--force` \u002F `--allow-once` bypass on the source check | Blocking check, no bypass flag |\n\n## Enforcement\n\n- Each downstream repo wires the ecosystem-appropriate source check into its **existing**\n  blocking lint \u002F pre-push gate (the same gate that already runs format\u002Flint). Source\n  locking adds NO new framework gate — it is a policy that each repo's existing gate\n  enforces with the ecosystem's native tool.\n- The check MUST be blocking: an un-allowlisted source, a missing lockfile, a disabled\n  verification knob, or an un-reviewed extra index fails the gate.\n- There is NO bypass flag. A legitimately new trusted source is added by editing the\n  allowlist (a reviewed change), never by skipping the check for one run.\n- New trusted sources are a reviewed config change (allowlist edit), consistent with\n  `bubbles-config-sst` single-source-of-truth governance for registry\u002Flockfile config.\n\n## Verification Commands\n\n```bash\n# Rust: source allowlist is enforced and blocking\ngrep -nE 'unknown-(registry|git)|allow-(registry|git)' deny.toml\n# Expectation: unknown-registry = \"deny\", unknown-git = \"deny\", explicit allow-registry\n\n# Node: registry pinned, lockfile committed, no stray per-scope registry\ngrep -nE '^registry=|:registry=' .npmrc\nls -la package-lock.json\n\n# Go: read-only modules, pinned proxy, no checksum-disable knobs\ngrep -nE 'GOFLAGS|GOPROXY|GONOSUM|GOINSECURE|GOPRIVATE' .env* *.mk Makefile 2>\u002Fdev\u002Fnull\nls -la go.sum\n\n# Python: single index, hash-pinned, no extra index\ngrep -nE -- '--index-url|--extra-index-url|--require-hashes|--trusted-host' requirements*.txt pip.conf 2>\u002Fdev\u002Fnull\n```\n\n## Anti-Patterns (BLOCKING)\n\n| Anti-Pattern | Why It's Wrong | Fix |\n|--------------|---------------|-----|\n| \"The lockfile already points at the trusted source, so we're fine\" | The control is the *source allowlist*, not the current pin; the next resolve can drift | Lock the allowlist, not just today's pin |\n| Adding `--extra-index-url` \"to grab one internal package\" | Dependency-confusion: a public typosquat at a higher version wins | Allowlist the internal index explicitly; pin\u002Fhash the package |\n| Disabling `go.sum` verification to \"unblock a build\" | Defeats source verification entirely | Fix the source\u002Fpin; never disable verification |\n| Treating cosign\u002FSLSA\u002FSBOM as \"we already do supply chain\" | Provenance is a different axis; it does not govern build inputs | Add source locking AND keep provenance |\n| A `--skip-source-check` escape hatch in the gate | First skip becomes the permanent path | Blocking check; new sources via allowlist edit only |\n\n## Integration With Bubbles Governance\n\n| Bubbles Surface | Relevance |\n|-----------------|-----------|\n| `bubbles-config-sst` | Registry\u002Flockfile\u002Fsource config is single-source-of-truth; no scattered or hand-drifted source config |\n| Repo lint \u002F pre-push gate | Hosts the ecosystem source check; blocking, no bypass |\n| `bubbles-deployment-target-adapter` | The complementary deploy-time provenance axis (cosign\u002FSLSA\u002FSBOM\u002FTrivy) |\n| Spec \u002F design authoring | A spec that adds a new external dependency or registry declares the trusted source and any allowlist exception |\n\n## See Also\n\n- [bubbles-supply-chain-source-locking.instructions.md](..\u002F..\u002Finstructions\u002Fbubbles-supply-chain-source-locking.instructions.md) — binding, agent-loaded counterpart\n- [bubbles-deployment-target-adapter skill](..\u002Fbubbles-deployment-target-adapter\u002FSKILL.md) — deploy-time artifact provenance (cosign keyless signing, SLSA build-provenance, SBOM attestation, image CVE scan) — the complementary axis\n- [bubbles-backup-bcdr-doctrine skill](..\u002Fbubbles-backup-bcdr-doctrine\u002FSKILL.md) — offsite\u002Fbackup trust boundaries\n- [bubbles-config-sst skill](..\u002Fbubbles-config-sst\u002FSKILL.md) — single-source-of-truth governance for registry\u002Flockfile config\n",{"name":5,"description":7},"main","ed893cc338281a0bb9bb9ecf3415716cb242bb3f",".github\u002Fskills\u002Fbubbles-supply-chain-source-locking",0,"https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel","https:\u002F\u002Fgithub.com\u002Fpkirsanov","2026-11-07 02:54:37",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add pkirsanov\u002Fsmackerel --skill bubbles-supply-chain-source-locking",{"tool":61,"command":62},"bunx","bunx skills add pkirsanov\u002Fsmackerel --skill bubbles-supply-chain-source-locking",{"tool":64,"command":65},"pnpm","pnpm dlx skills add pkirsanov\u002Fsmackerel --skill bubbles-supply-chain-source-locking","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-supply-chain-source-locking\u002FSKILL.md",true,[],[70,100,125,152,173,201],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":79,"publishedAt":43},"01M6N9V5TBHQT20V5SCCJ1VRBC","smackerel-trace-capture","Wire Smackerel's concrete validate-plane stack into the framework trace-driven defect-discovery method. Use when running live-category tests (integration\u002Fe2e\u002Fe2e-ui\u002Fstress) against the ephemeral test stack; capturing SLO or trace evidence; hunting latency\u002Ferror\u002Fperf bugs from spans; querying the test-stack Jaeger or Prometheus; or touching `.specify\u002Fruntime\u002Fobservability`. Concrete smackerel endpoints + the exact `capture-slo.sh` command; do NOT duplicate `bubbles-observability-adapter` — this only adds the wiring.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsmackerel-trace-capture\u002FSKILL.md",[76],{"categoryNo":77,"categoryName":78,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",[80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],"trace","capture","smackerel trace capture","perf","observability","prometheus","specify","e2e","discovery","use","slo","only","evidence","do","latency","runtime","tests","adapter","error","bugs",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":107,"publishedAt":43},"01M6N9TZDEV26RZ7W34HEFPQE9","smackerel-no-defaults","Enforce Smackerel's NO-DEFAULTS \u002F fail-loud SST policy. Use when editing config, Docker Compose, deploy adapters, docs, instructions, skills, env handling, host bind addresses, or any runtime value that could be hidden by fallback syntax.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fsmackerel-no-defaults\u002FSKILL.md",[106],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[108,109,110,42,111,112,113,114,115,89,116,117,95,118,119,120,121,122,123,124],"smackerel no defaults","docker","policy","deploy","docker compose","syntax","editing","instructions","compose","enforce","bind","env","host","Adapters","sst","addresses","value",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":134,"publishedAt":43},"01M6N9TJRS5PF83JH2W4614D4W","bubbles-workflow-mode-resolution","Resolve a Bubbles workflow mode against `bubbles\u002Fworkflows.yaml`, including template inheritance, status ceilings, gate wiring, and decision policy. Use when picking a mode for a request, when a guard reports a mode-related failure, or when extending workflows.yaml with a new mode or template. Covers natural-language intent routing and the workflow registry consistency rules.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-workflow-mode-resolution\u002FSKILL.md",[131],{"categoryNo":132,"categoryName":133,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[135,136,137,138,110,139,140,141,142,143,144,89,145,146,147,148,149,150,151,29],"workflow","resolution","mode","bubbles workflow mode resolution","workflows","routing","guard","template","decision","Rules","reports","intent","inheritance","with","consistency","natural-language","for",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":159,"publishedAt":43},"01M6N9TC98D6DJR0D64SSN0SN3","bubbles-workflow-execution-loops","Run per-round synchronous workflow execution loops correctly. Use when orchestrating a multi-round workflow, dispatching specialist subagents, handling round-based remediation, or interpreting a workflow mode's execution policy. Covers authorized direct execution, dispatch-and-wait, batch-then-summarize prohibition, and mapped-mode execution.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-workflow-execution-loops\u002FSKILL.md",[158],{"categoryNo":132,"categoryName":133,"taxonomyType":20,"taxonomyTypeDesc":21},[135,160,161,162,163,110,164,165,166,167,168,89,169,170,171,172,137],"execution","loops","bubbles workflow execution loops","summarize","run","batch","remediation","direct","subagents","dispatch","wait","multi","multi-round",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":183,"publishedAt":43},"01M6N9SYXQNJDQ1T1YT81JH2BG","bubbles-vscode-agent-constraints","Design agents that fit the VS Code Copilot Chat runtime instead of fighting it. Use when authoring or editing any `*.agent.md`; when adding `tools:`, `agents:`, `handoffs:`, `model:`, `user-invocable:`, or `disable-model-invocation:` frontmatter; when designing an orchestrator that dispatches specialists; when a design implies agent-calls-agent-calls-agent chaining; when a subagent dispatch silently no-ops or an agent cannot be selected in the dropdown; or when writing a governance rule about delegation that the runtime cannot actually enforce. Prevents multi-level-subagent designs, prose-only dispatch laws, and frontmatter\u002Fbody contradictions.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-vscode-agent-constraints\u002FSKILL.md",[179,182],{"categoryNo":180,"categoryName":181,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":132,"categoryName":133,"taxonomyType":20,"taxonomyTypeDesc":21},[184,185,186,187,188,189,190,191,192,193,194,195,114,196,91,95,197,198,199,200],"vscode","constraints","bubbles vscode agent constraints","design","writing","copilot","code","delegation","Tools","subagent","model","chaining","orchestrator","authoring","fit","subagent dispatch","frontmatter",{"skillNo":202,"name":203,"nameZh":6,"description":204,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":205,"categories":206,"keywords":207,"publishedAt":43},"01M6N9SD78SK12PRT9KBRZ6TB3","bubbles-upkeep-cadence","How to schedule, dispatch, and record recurring operational upkeep tasks (backup, restore-drill, BCDR-drill, patch-cycle, secret-rotation, flag-cleanup, compliance-sweep). Use when authoring or modifying `config\u002Fupkeep-calendar.yaml`, when investigating a missed task, when reading the upkeep ledger, or when adding a new task type.","https:\u002F\u002Fgithub.com\u002Fpkirsanov\u002Fsmackerel\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fbubbles-upkeep-cadence\u002FSKILL.md",[],[208,209,210,211,212,213,214,215,89,216,217,218,219,220,221,222,223,224,225,226],"cadence","bubbles upkeep cadence","tasks","cleanup","backup","sweep","schedule","recurring","patch","restore","task","cycle","record","missed","type","drill","how to","new task","rotation"]