Files
LocalAI/AGENTS.md
Richard Palethorpe 5d0b549049 feat(gallery): verify backend OCI images with keyless cosign (#9823)
* feat(gallery): verify backend OCI images with keyless cosign

Close a trust gap where a registry compromise or MITM could silently
replace a backend image: the gallery YAML tells LocalAI which image to
pull, but until now nothing verified the bytes came from our CI.

Consumer (pkg/oci/cosignverify):
- New package using sigstore-go to verify keyless-cosign signatures.
- OCI 1.1 referrers API + new bundle format (no legacy :tag.sig).
- Policy fields: Issuer / IssuerRegex / Identity / IdentityRegex /
  NotBefore. NotBefore is the revocation lever — keyless Fulcio certs
  are ephemeral so revocation is policy-side; advancing not_before in
  the gallery YAML invalidates every signature predating the cutoff.
- TUF trusted root cached process-wide so N backends from one gallery
  do 1 fetch, not N.

Plumbing:
- pkg/downloader: ImageVerifier interface + WithImageVerifier option
  threaded through DownloadFileWithContext. Verification runs between
  oci.GetImage and oci.ExtractOCIImage, with digest pinning via
  pinnedImageRef to close the TOCTOU window. Skips the verifier's HEAD
  when the ref is already digest-pinned.
- core/config: Gallery.Verification YAML block.
- core/gallery: backendDownloadOptions builds the verifier from the
  policy; applied on initial URI, mirrors, and tag fallbacks.
- core/gallery/upgrade: the upgrade path now routes through the same
  options builder. A regression Ginkgo spec pins this contract —
  without it, UpgradeBackend silently bypassed verification.
- core/cli: --require-backend-integrity (LOCALAI_REQUIRE_BACKEND_INTEGRITY)
  escalates missing policy / empty SHA256 from warn to hard-fail.

Producer (.github/workflows/backend_merge.yml):
- id-token: write at job scope (PR-fork-safe via existing event gate).
- sigstore/cosign-installer@v3 pinned to v2.4.1.
- After each docker buildx imagetools create, resolve the manifest
  list digest and run cosign sign --recursive --new-bundle-format
  --registry-referrers-mode=oci-1-1 against repo@digest. --recursive
  signs the index and every per-arch entry, matching how the consumer
  resolves a tag to a platform-specific manifest before verifying.

Rollout: backend/index.yaml has no `verification:` block yet, so this
PR is backward-compatible — installs proceed with a warning until the
gallery is populated. Strict mode is opt-in.

Assisted-by: claude-code:claude-opus-4-7 [Bash] [Edit] [Read] [Write] [WebSearch] [WebFetch]
Signed-off-by: Richard Palethorpe <io@richiejp.com>

* refactor(gallery): plumb RequireBackendIntegrity through config instead of env

The previous implementation re-exported the --require-backend-integrity
CLI flag into LOCALAI_REQUIRE_BACKEND_INTEGRITY via os.Setenv, then
re-read it in core/gallery via os.Getenv. This leaked process state
into the gallery package and made the flag impossible to override
per-call or test without touching the env.

Add RequireBackendIntegrity to ApplicationConfig (with a matching
WithRequireBackendIntegrity AppOption) and thread the bool through
every install/upgrade path: InstallBackend, InstallBackendFromGallery,
UpgradeBackend, InstallModelFromGallery, InstallExternalBackend,
ApplyGalleryFromString/File, startup.InstallModels. Worker subcommands
gain the same env-bound flag on WorkerFlags so distributed-worker
installs honor it consistently with the worker daemon path.

Add a forbidigo lint rule against os.Getenv / os.LookupEnv / os.Environ
to keep the env-leak pattern from creeping back. Existing offenders
(p2p, config loaders, etc.) are baseline-grandfathered by the existing
new-from-merge-base: origin/master setting; targeted path exclusions
cover the legitimate cases — kong CLI entry points, backend
subprocesses, system capability probes, gRPC AUTH_TOKEN inheritance,
test gating env vars.

Assisted-by: claude-code:claude-opus-4-7
Signed-off-by: Richard Palethorpe <io@richiejp.com>

---------

Signed-off-by: Richard Palethorpe <io@richiejp.com>
2026-05-18 08:02:20 +02:00

5.3 KiB

LocalAI Agent Instructions

This file is the entry point for AI coding assistants (Claude Code, Cursor, Copilot, Codex, Aider, etc.) working on LocalAI. It is an index to detailed topic guides in the .agents/ directory. Read the relevant file(s) for the task at hand — you don't need to load all of them.

Human contributors: see CONTRIBUTING.md for the development workflow.

Policy for AI-Assisted Contributions

LocalAI follows the Linux kernel project's guidelines for AI coding assistants. Before submitting AI-assisted code, read .agents/ai-coding-assistants.md. Key rules:

  • No Signed-off-by from AI. Only the human submitter may sign off on the Developer Certificate of Origin.
  • No Co-Authored-By: <AI> trailers. The human contributor owns the change.
  • Use an Assisted-by: trailer to attribute AI involvement. Format: Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2].
  • The human submitter is responsible for reviewing, testing, and understanding every line of generated code.

Topics

File When to read
.agents/ai-coding-assistants.md Policy for AI-assisted contributions — licensing, DCO, attribution
.agents/building-and-testing.md Building the project, running tests, Docker builds for specific platforms
.agents/ci-caching.md CI build cache layout (registry-backed BuildKit cache on quay.io/go-skynet/ci-cache, per-arch keys), DEPS_REFRESH weekly cache-buster for unpinned Python deps, prebuilt base-grpc-* images for llama.cpp variants, per-arch native + manifest-merge pattern, setup-build-disk /mnt relocation, path filter on master push, manual eviction
.agents/adding-backends.md Adding a new backend (Python, Go, or C++) — full step-by-step checklist, including importer integration (the /import-model dropdown is server-driven from GET /backends/known)
.agents/coding-style.md Code style, editorconfig, logging, documentation conventions
.agents/llama-cpp-backend.md Working on the llama.cpp backend — architecture, updating, tool call parsing
.agents/vllm-backend.md Working on the vLLM / vLLM-omni backends — native parsers, ChatDelta, CPU build, libnuma packaging, backend hooks
.agents/sglang-backend.md Working on the SGLang backend — engine_args validation against ServerArgs, speculative-decoding (EAGLE/EAGLE3/DFLASH/MTP) recipes, parser handling
.agents/ds4-backend.md Working on the ds4 backend - DSML state machine, thinking modes, KV cache, Metal+CUDA matrix
.agents/testing-mcp-apps.md Testing MCP Apps (interactive tool UIs) in the React UI
.agents/api-endpoints-and-auth.md Adding API endpoints, auth middleware, feature permissions, user access control
.agents/debugging-backends.md Debugging runtime backend failures, dependency conflicts, rebuilding backends
.agents/adding-gallery-models.md Adding GGUF models from HuggingFace to the model gallery
.agents/localai-assistant-mcp.md LocalAI Assistant chat modality — adding admin tools to the in-process MCP server, editing skill prompts, keeping REST + MCP + skills in sync
.agents/backend-signing.md Backend OCI image signing (keyless cosign + sigstore-go) — producer-side CI setup, consumer-side gallery verification: block, strict mode (LOCALAI_REQUIRE_BACKEND_INTEGRITY), revocation via not_before

Quick Reference

  • Logging: Use github.com/mudler/xlog (same API as slog)
  • Go style: Prefer any over interface{}
  • Comments: Explain why, not what
  • Docs: Update docs/content/ when adding features or changing config
  • New API endpoints: LocalAI advertises its capability surface in several independent places — swagger @Tags, /api/instructions registry, auth RouteFeatureRegistry, React UI capabilities.js, docs. Read .agents/api-endpoints-and-auth.md and follow its checklist — missing any surface means clients, admins, and the UI won't know the endpoint exists.
  • Admin endpoints → MCP tool: every admin endpoint that an admin would manage conversationally (install/list/edit/toggle/upgrade) MUST also be exposed as an MCP tool in pkg/mcp/localaitools/. The LocalAI Assistant chat modality and the standalone local-ai mcp-server consume that package; drift between REST and MCP is a real risk. Read .agents/localai-assistant-mcp.md — the TestToolHTTPRouteMappingComplete test fails until you wire the new tool and update the route map.
  • Build: Inspect Makefile and .github/workflows/ — ask the user before running long builds
  • UI: The active UI is the React app in core/http/react-ui/. The older Alpine.js/HTML UI in core/http/static/ is pending deprecation — all new UI work goes in the React UI