> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentfacets.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Publishing

> How CircleCI authenticates with npm using OIDC tokens, and how to configure it for new packages.

## What is OIDC trusted publishing?

OIDC trusted publishing lets CircleCI publish packages to npm without storing npm auth tokens. Instead, CircleCI provides a short-lived OIDC token (`$CIRCLE_OIDC_TOKEN_V2`) that npm validates against a trusted publisher configuration on each package. If the token's claims match (organization, project, pipeline, context), npm accepts the publish.

<Info>
  **Trusted publishing vs. provenance attestation** — these are different things. Trusted publishing is an
  **authentication** mechanism (how CI proves it's allowed to publish). Provenance attestation is a **supply-chain
  security** feature (cryptographically linking a package to its source). npm's `--provenance` flag only works on GitHub
  Actions and GitLab CI — it is not supported on CircleCI. This project uses OIDC for authentication only.
</Info>

## When to configure

Whenever a new public `@agent-facets/*` package is added to the monorepo. Each new package needs its own trusted publisher entry on npm before CI can publish it. There are two seed scripts depending on the kind of package:

| Seed script         | Scope                                                           |
| ------------------- | --------------------------------------------------------------- |
| `bun seed:cli`      | The 12 CLI platform packages (`@agent-facets/cli-*`)            |
| `bun seed:adapters` | Library/adapter packages (`@agent-facets/adapter`, `adapter-*`) |

## Setup steps

<Steps>
  <Step title="Seed the package on npm">
    ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
    npm login # one-time, uses your personal npm account
    bun seed:cli       # for new @agent-facets/cli-* platform targets
    bun seed:adapters  # for new @agent-facets/adapter* or other library packages
    ```

    The seed script will print out a list of packages that need to be configured.
  </Step>

  <Step title="Configure trusted publishing on npm for each package that was listed">
    <Steps>
      <Step>
        Open the package's npm settings page (URLs are printed by the seed script)
      </Step>

      <Step>
        Under **Publishing access**, add a new trusted publisher
      </Step>

      <Step>
        Enter the CircleCI OIDC values:

        | Field                      | Value                                  |
        | -------------------------- | -------------------------------------- |
        | **Organization ID**        | `bfa561da-d33e-4a2a-a46d-48e096a828e0` |
        | **Project ID**             | `46274a40-97ed-41fd-a745-9702a7131ccc` |
        | **Pipeline Definition ID** | `15756499-9950-43b5-b2d3-ac4086d9aa48` |
        | **Context IDs**            | `691cddb9-b839-41e8-bc5c-ebb4484a2a1f` |
        | **VCS Origin**             | `github.com/agent-facets/facets`       |
      </Step>
    </Steps>
  </Step>

  <Step title="Verify">
    Re-run the seed script to confirm all packages exist on npm. The script reports "All packages already exist on npm"
    if seeding was successful.
  </Step>
</Steps>

The CLI package (`agent-facets`), existing platform packages, and the library packages that are already on npm all have OIDC configured.

## Where to find these values

| Value                  | Location                                          |
| ---------------------- | ------------------------------------------------- |
| Organization ID        | CircleCI org settings                             |
| Project ID             | CircleCI project settings                         |
| Pipeline Definition ID | CircleCI project pipeline settings                |
| Context IDs            | CircleCI context settings (`bot-context` context) |
| VCS Origin             | GitHub repository URL (without `https://`)        |

## Platform packages

The 12 platform packages that need OIDC configuration:

```
@agent-facets/cli-darwin-arm64
@agent-facets/cli-darwin-x64
@agent-facets/cli-darwin-x64-baseline
@agent-facets/cli-linux-arm64
@agent-facets/cli-linux-arm64-musl
@agent-facets/cli-linux-x64
@agent-facets/cli-linux-x64-baseline
@agent-facets/cli-linux-x64-baseline-musl
@agent-facets/cli-linux-x64-musl
@agent-facets/cli-windows-arm64
@agent-facets/cli-windows-x64
@agent-facets/cli-windows-x64-baseline
```

## How it works

1. Each publish script calls `mintNpmToken()` which runs `circleci run oidc get` to fetch a fresh OIDC JWT and sets it as `NPM_ID_TOKEN`.
2. When `npm publish` runs, npm exchanges the token with the registry. The registry validates the token's claims against the package's trusted publisher configuration.
3. If the claims match, the publish succeeds. No long-lived npm tokens are involved.

All CLI packages publish directly to the `latest` dist-tag. Platform binaries are published first via a matrix workflow (one per executor), verified on the registry, then the CLI package publishes last. This ordering ensures users never see a partial release — the CLI package (`agent-facets`) is the entry point, and it only appears on `latest` after all its platform dependencies are confirmed available.

<Note>
  npm's OIDC trusted publishing only supports `npm publish`. Other operations like `npm dist-tag add` cannot
  authenticate via OIDC ([npm/cli#8547](https://github.com/npm/cli/issues/8547)). This is why we publish directly to
  `latest` instead of publishing to a staging tag and promoting — the promote step would require a static npm token.
</Note>
