Skip to content

Offline bundles

Export bundles from the portal, use them in air-gap CI, set up an internal mirror, and understand signature verification.

Offline bundles let you use platform profiles and your own profiles in environments that have no direct internet access, such as air-gap CI systems or internal artifact repositories.

Why offline bundles

In some environments your CI runner is not allowed to reach the internet directly:

  • Air-gap CI: Isolated build infrastructure without outbound connectivity to the portal.
  • Internal artifact repository: Bundles are downloaded once and mirrored internally so every team accesses the same version.
  • Regulatory requirements: Audited environments where external network connections from CI are prohibited or restricted.

Exporting a bundle from the portal

You can download a bundle for any published profile version from the portal:

  1. Open the profile list or the platform rules overview.
  2. On the profile list, click the kebab menu (⋮) on the desired profile card and select Download bundle. On the platform rules overview, click the Download bundle button directly on the profile card.
  3. Choose the version and download the signed .cgbundle file.

The bundle contains all rule files (.cgr) for the pinned version, a manifest file with metadata and a content hash, and an Ed25519 signature.

Referencing a bundle file in .codecharter/config.yml

Instead of an API call to the portal you can reference a locally available bundle directly. The path key accepts both local file paths and HTTPS mirror URLs:

# .codecharter/config.yml
version: 1
profiles:
  - path: ".codecharter/bundles/dotnet-standard-2.1.0.cgbundle"

The CLI verifies the bundle signature each time the bundle is loaded and caches it under .codecharter/cache/. CODECHARTER_API_KEY does not need to be set for file-based usage. If a referenced bundle file does not exist, the CLI reports an error for that entry and skips it; a failed signature check, by contrast, aborts the run.

Recommendation: do not commit the bundle directly to the repository. Instead, download it from your internal mirror in a preceding CI step.

Setting up an internal mirror

You can mirror bundles behind an internal HTTPS URL using the same path key:

# .codecharter/config.yml
version: 1
profiles:
  - path: "https://artifacts.internal.example.com/codecharter/dotnet-standard-2.1.0.cgbundle"

Mirror requirements:

  • HTTPS only -- http:// URLs are rejected. The certificate must be trusted by the operating system's certificate store; there is no CLI option to override certificate validation.
  • Immutable URLs per version -- the CLI downloads each URL once and reuses the cached file afterwards.
  • The mirror URL must be reachable without authentication. The CLI does not send any credentials or authentication headers to mirror URLs.

Signature verification

Every bundle is signed with the portal's Ed25519 signing key. The CLI verifies the signature before use. If verification fails, the build aborts with an error such as:

Bundle 'dotnet-standard-2.1.0.cgbundle': Bundle signature is invalid (key '<key-id>').
  The bundle may have been tampered with.

CodeCharter fetches the portal's public signing keys from the portal and caches them locally at .codecharter/cache/signing-keys.json, refreshing them automatically when they are absent or older than 24 hours. There is no manual key command. When the portal is unreachable, the CLI falls back to the cached keys even if they are stale. For a fully offline runner this means the key cache must be primed beforehand: run the CLI once with portal connectivity (or copy a populated .codecharter/cache/signing-keys.json onto the runner) so that signature verification can succeed without network access.

Update workflow in air-gap environments

In a fully isolated environment we recommend the following process:

  1. On a machine with internet access: download the new bundle from the portal.
  2. Upload the bundle to your internal artifact repository.
  3. Update the version in .codecharter/config.yml.
  4. On the internet-connected machine, run codecharter update --portal-url <url> --api-key <key> to refresh the lockfile. This command requires portal connectivity and cannot run inside the air gap.
  5. Merge .codecharter/config.yml and .codecharter/codecharter.lock.json in a PR.
  6. On the CI runner: reference the mirrored bundle via a path: entry in .codecharter/config.yml (local file or internal HTTPS URL) and run codecharter analyze as usual.

Bundles referenced via path: are downloaded, verified, and cached automatically when the analysis runs; no separate restore step is needed for them.

Further reading