# Registry Forwarding Behavior {#registry-forwarding}

This page describes how Takumi Guard currently forwards requests to each registry and what it responds with. Use it, for example, when you configure a proxy or firewall that restricts outbound traffic.

:::warning Subject to change
The behavior described here is what Takumi Guard does today. Changes are announced in the release notes, except where an urgent security fix requires changing it without notice.
:::

## Traffic Flow {#communication-flow}

Takumi Guard does not relay package artifacts. Metadata goes through Takumi Guard, but for an artifact request it returns an HTTP 302 and the client connects directly to the public host to download it. See [Package Blocking](/docs/t/guard/features/package-blocking.md#request-flow) for the full flow.

## Destinations {#destinations}

On a public registry host, the paths listed below sit alongside paths that receive no traffic because Takumi Guard handles them. **The two cannot be told apart by host name.**

### Takumi Guard {#guard-hosts}

Takumi Guard is served on a separate host per ecosystem, and traffic goes to the host for the ecosystem you use.

| Host                   | Ecosystem |
| ---------------------- | --------- |
| `npm.flatt.tech`       | npm       |
| `pypi.flatt.tech`      | PyPI      |
| `rubygems.flatt.tech`  | RubyGems  |
| `golang.flatt.tech`    | Go        |
| `packagist.flatt.tech` | Packagist |

### Public Registries (Artifact Download) {#official-artifact-hosts}

Package artifacts are downloaded directly from the host Takumi Guard redirects to.

| Host                     | Paths used                                                                                                                                      | Purpose                   |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `registry.npmjs.org`     | `GET /{package}/-/*.tgz`<br />`GET /@{scope}/{package}/-/*.tgz`                                                                                 | npm package artifact      |
| `files.pythonhosted.org` | `GET /packages/**`                                                                                                                              | wheel and sdist artifacts |
| `rubygems.org`           | `GET /gems/*.gem`<br />`GET /quick/Marshal.4.8/**`<br />`GET /specs.4.8.gz`<br />`GET /latest_specs.4.8.gz`<br />`GET /prerelease_specs.4.8.gz` | gem artifact and index    |
| `proxy.golang.org`       | `GET /**/@v/*.zip`                                                                                                                              | Go module artifact        |

For RubyGems, Bundler falls back to the legacy index (`/specs.4.8.gz` and `/quick/Marshal.4.8/`) when the Compact Index is unavailable. Takumi Guard redirects those requests too.

For Composer, the artifact host is whatever the package metadata names as its distribution source. A package hosted on GitHub redirects to `api.github.com` and from there to `codeload.github.com`. If a dependency is distributed from somewhere else, traffic goes to that host instead. `dist.url` in `https://packagist.flatt.tech/p2/{vendor}/{package}.json` shows the source for each dependency.

### Traffic Other Than Artifact Redirects {#other-required-hosts}

The following traffic also occurs, although it is not an artifact redirect.

#### Go Checksum Database {#go-checksum-database}

Where checksum verification is enabled, the Go toolchain queries the checksum database before fetching a module. Takumi Guard does not proxy this verification, so the client connects directly to `sum.golang.org` (all paths).

## URLs by Ecosystem {#url-inventory}

The traffic that occurs per ecosystem.

### npm {#npm-urls}

Shared across npm, pnpm, yarn, and bun.

- **`GET https://npm.flatt.tech/{package}`**
  - **Purpose**: Fetch metadata
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200 / 304
- **`POST https://npm.flatt.tech/-/npm/v1/security/advisories/bulk`**
  - **Purpose**: Query advisories (npm only)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`POST https://npm.flatt.tech/-/npm/v1/security/audits`**, **`/-/npm/v1/security/audits/quick`**
  - **Purpose**: Query advisories (pnpm and yarn)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://npm.flatt.tech/-/npm/v1/keys`**, **`GET https://npm.flatt.tech/-/npm/v1/attestations/{path}`**
  - **Purpose**: Verify signing keys and provenance
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://npm.flatt.tech/-/v1/search`**
  - **Purpose**: Search for packages (`npm search`)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://npm.flatt.tech/{package}/-/{file}.tgz`**
  - **Purpose**: Request the artifact
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to `registry.npmjs.org`)
- **`GET https://registry.npmjs.org/{package}/-/{file}.tgz`**
  - **Purpose**: Download the artifact
  - **Destination**: Public registry
  - **Status**: 200

For scoped packages the path is `/@{scope}/{package}`. yarn, pnpm and bun URL-encode the slash when fetching metadata, sending `/@{scope}%2f{package}`. `%2F` is handled the same way, so a path rule needs to match either case.

:::info Using bun
On a first install with no lockfile, the artifact is requested from `registry.npmjs.org` directly rather than through Takumi Guard. Metadata is still fetched through Takumi Guard, and the hosts involved are the same as above.
:::

### PyPI {#pypi-urls}

Shared across pip and uv.

- **`GET https://pypi.flatt.tech/simple/{project}/`**
  - **Purpose**: Fetch metadata
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://pypi.flatt.tech/files/packages/{hash-path}/{file}`**
  - **Purpose**: Request the artifact
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to `files.pythonhosted.org`)
- **`GET https://files.pythonhosted.org/packages/{hash-path}/{file}`**
  - **Purpose**: Download the artifact
  - **Destination**: Public distribution host
  - **Status**: 200

:::warning Using Poetry
A project with the per-repository setup goes through `pypi.flatt.tech` just like pip and uv. Without it, metadata is not fetched through Takumi Guard and the following requests occur instead.

See [poetry in the quickstart](/docs/t/guard/quickstart/pypi.md#quick-reference-poetry) for how to configure it.

- **`GET https://pypi.org/simple/{project}/`**
  - **Purpose**: Fetch metadata
  - **Destination**: Public registry
  - **Status**: 200
- **`GET https://pypi.org/pypi/{project}/{version}/json`**
  - **Purpose**: Fetch metadata
  - **Destination**: Public registry
  - **Status**: 200

:::

### RubyGems {#rubygems-urls}

Traffic from Bundler.

- **`GET https://rubygems.flatt.tech/versions`**
  - **Purpose**: Fetch the index
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200 / 206 / 304 (206 for an incremental fetch)
- **`GET https://rubygems.flatt.tech/info/{gem}`**
  - **Purpose**: Fetch metadata
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://rubygems.flatt.tech/gems/{gem}-{version}.gem`**
  - **Purpose**: Request the artifact
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to `rubygems.org`)
- **`GET https://rubygems.org/gems/{gem}-{version}.gem`**
  - **Purpose**: Download the artifact
  - **Destination**: Public registry
  - **Status**: 200
- **`GET https://rubygems.flatt.tech/specs.4.8.gz`**, **`/latest_specs.4.8.gz`**, **`/prerelease_specs.4.8.gz`**, **`/quick/Marshal.4.8/{gem}-{version}.gemspec.rz`**
  - **Purpose**: Fetch the legacy index, when the Compact Index is unavailable
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to the same path on `rubygems.org`)
- **`GET https://rubygems.org/specs.4.8.gz`** and the other redirect targets above
  - **Purpose**: Download the legacy index
  - **Destination**: Public registry
  - **Status**: 200

### Go {#golang-urls}

Traffic from the Go toolchain.

- **`GET https://golang.flatt.tech/sumdb/sum.golang.org/supported`**
  - **Purpose**: Check whether the checksum database can be queried through the proxy
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 404 (expected response; the client connects to `sum.golang.org` directly)
- **`GET https://golang.flatt.tech/{module}/@v/list`**
  - **Purpose**: List versions
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: passes the upstream status through
- **`GET https://golang.flatt.tech/{module}/@latest`**
  - **Purpose**: Resolve the latest version (`go get module@latest` and similar)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: passes the upstream status through
- **`GET https://golang.flatt.tech/{module}/@v/{version}.info`**
  - **Purpose**: Fetch metadata
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: passes the upstream status through
- **`GET https://golang.flatt.tech/{module}/@v/{version}.mod`**
  - **Purpose**: Fetch metadata
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: passes the upstream status through
- **`GET https://golang.flatt.tech/{module}/@v/{version}.zip`**
  - **Purpose**: Request the artifact
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to `proxy.golang.org`)
- **`GET https://proxy.golang.org/{module}/@v/{version}.zip`**
  - **Purpose**: Download the artifact
  - **Destination**: Public proxy
  - **Status**: 200
- **`GET https://sum.golang.org/lookup/{module}@{version}`**
  - **Purpose**: Verify checksums
  - **Destination**: Checksum database
  - **Status**: 200
- **`GET https://sum.golang.org/tile/{tile-path}`**
  - **Purpose**: Verify checksums
  - **Destination**: Checksum database
  - **Status**: 200

### Packagist {#packagist-urls}

Traffic from Composer.

- **`GET https://packagist.flatt.tech/packages.json`**
  - **Purpose**: Fetch the repository definition
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200 / 304
- **`GET https://packagist.flatt.tech/p2/{vendor}/{package}.json`**, **`/p2/{vendor}/{package}~dev.json`**
  - **Purpose**: Fetch metadata (Composer 2 fetches both)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200 / 304
- **`POST https://packagist.flatt.tech/api/filter`**
  - **Purpose**: Query the packages to install (`composer install` and `composer audit`)
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 200
- **`GET https://packagist.flatt.tech/dist/{vendor}/{package}/{version}/{reference}.{type}`**
  - **Purpose**: Request the artifact
  - **Destination**: <GuardIcon /> Takumi Guard
  - **Status**: 302 (redirects to the distribution source named in the metadata; `api.github.com` for a package hosted on GitHub)
- **`GET https://api.github.com/repos/{owner}/{repo}/zipball/{reference}`**
  - **Purpose**: Request the artifact
  - **Destination**: GitHub
  - **Status**: 302 (redirects to `codeload.github.com`)
- **`GET https://codeload.github.com/{owner}/{repo}/legacy.zip/{reference}`**
  - **Purpose**: Download the artifact
  - **Destination**: GitHub
  - **Status**: 200
- **`POST https://packagist.org/downloads/`**
  - **Purpose**: Report install statistics (**does not affect whether an install succeeds**)
  - **Destination**: Public site
  - **Status**: 201

:::info Versions verified
This page reflects the following versions, as of September 2026.

- npm v10.8 / v11.19 / v12.0, pnpm v10.33 / v11.25, yarn v1.22 / v4.12 / v4.18, bun v1.4
- pip v22.0 / v26.2, uv v0.12, Poetry v2.4
- Bundler v2.5 / v4.0
- Go v1.23 / v1.27
- Composer v2.10

:::

## Reference {#reference}

### Configuring a Proxy or Firewall {#proxy-and-firewall}

The forwarding uses the following destinations besides Takumi Guard. Each is used to download a package artifact or to verify checksums, and installs do not complete if they cannot be reached.

| Host                     | Paths                                                                                                                       |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| `registry.npmjs.org`     | `/{package}/-/*.tgz`<br />`/@{scope}/{package}/-/*.tgz`                                                                     |
| `files.pythonhosted.org` | `/packages/**`                                                                                                              |
| `rubygems.org`           | `/gems/*.gem`<br />`/quick/Marshal.4.8/**`<br />`/specs.4.8.gz`<br />`/latest_specs.4.8.gz`<br />`/prerelease_specs.4.8.gz` |
| `proxy.golang.org`       | `/**/@v/*.zip`                                                                                                              |
| `sum.golang.org`         | All paths                                                                                                                   |

#### Using Composer {#composer-case}

With Composer, the distribution source differs per dependency. You therefore need to check `dist.url` in `https://packagist.flatt.tech/p2/{vendor}/{package}.json` and work out the destinations for each dependency.

For a package published on GitHub, for example, the destinations are as follows.

| Host                  | Paths                  |
| --------------------- | ---------------------- |
| `api.github.com`      | `/repos/*/*/zipball/*` |
| `codeload.github.com` | `/*/*/legacy.zip/*`    |

If a dependency is distributed from somewhere other than GitHub, traffic goes to that source as well.

#### Private Packages (npm, PyPI, RubyGems, Packagist) {#private-packages}

Where a separate registry is configured, the client connects to that registry directly. How it is configured differs per ecosystem.

- [Private packages on npm](/docs/t/guard/quickstart/npm.md#private-packages) (a registry per scope)
- [Private packages on PyPI](/docs/t/guard/quickstart/pypi.md#private-packages) (an extra index URL)
- [Private gems on RubyGems](/docs/t/guard/quickstart/rubygems.md#private-gems) (a `source` block in the `Gemfile`)
- [Private packages on Packagist](/docs/t/guard/quickstart/packagist.md#private-packages) (a repository declaration)

#### Private Modules (Go) {#private-go-modules}

A module matching `GOPRIVATE` is fetched with `git` from the host in its module path, going through neither Takumi Guard nor the checksum database. See [Using with Private Modules](/docs/t/guard/quickstart/golang.md#private-modules).

#### Hosts That Receive No Traffic {#no-traffic-hosts}

With Takumi Guard configured, no traffic reaches the following hosts.

| Host                 | Reason                                                                        |
| -------------------- | ----------------------------------------------------------------------------- |
| `repo.packagist.org` | Takumi Guard fetches the metadata on its own side                             |
| `pypi.org`           | pip, uv, and a Poetry project with the per-repository setup do not contact it |
| `index.rubygems.org` | Bundler does not contact it                                                   |

`packagist.org` receives only the install statistics report. An install completes even when that request does not get through.

:::warning Support scope
If blocking any of this traffic causes a problem, we will help investigate as far as we can, but it may fall outside the scope of support.
:::
