# `@platform-modules` registry gateway

This is a deliberately small, read-only npm registry for one scope. It serves
admitted packuments and content-addressed tarballs from disk. It has no upstream
proxy or credential code, rejects every registry method except `GET` and `HEAD`,
and returns 404 for anything outside `@platform-modules` and `/tarballs`. Its one
`CONNECT` seam accepts only the configured published registry authority and tunnels
back into the same read-only handler; every other destination is refused.

## Mechanics proof

Run:

```bash
bash modules/sandbox/registry-gateway/test-gateway.sh
```

The proof creates all temporary data outside the repository. Because this sandbox
intentionally has no GitHub Packages credential, it synthesizes minimal valid
archives for `ui-primitives@0.5.0`, `query-react@0.1.0`, and `ui-tokens@0.2.0`, then
admits them through the production admission command. It proves the CONNECT tunnel
refuses every authority except the published registry, a frozen install through that
tunnel from a cold store, locked-URL and cached-byte tamper rejection, 50 concurrent
cold installs with isolated stores, and HTTP publish denial. Set
`REGISTRY_PROOF_CONCURRENCY` to run a smaller diagnostic on a process-limited host;
the acceptance protocol uses the default of 50. The synthetic archives are
mechanics evidence only and must never be deployed as the real mirror.

## Operator deployment

On the trusted host, obtain each exact archive from GitHub Packages using a
server-side read token. Do not put that token in this service, its mirror, a repo,
or a sandbox. Admit each downloaded archive (the command validates its manifest):

```bash
node modules/sandbox/registry-gateway/admit-package.mjs ARCHIVE.tgz \
  @platform-modules/ui-primitives 0.5.0 /srv/platform-registry/mirror \
  http://HOST_INTERFACE:4873 2026-08-05T12:01:34Z
```

The final value is the authenticated registry's publication timestamp for that exact
version (`npm view PACKAGE@VERSION time`). It preserves pnpm's minimum-release-age
check; never invent it or omit it. Repeat for `query-react@0.1.0` and
`ui-tokens@0.2.0`. Review the emitted immutable
filenames and packuments, make the mirror directory read-only to the service user,
then start `server.mjs` with `REGISTRY_MIRROR`, `REGISTRY_HOST` set to the intended
host/tailnet interface (never a public interface), `REGISTRY_PORT`, and
`REGISTRY_PUBLIC_AUTHORITY` set to the exact host and port written into admitted
packuments. Firewall the listener to sandbox consumers. Availability/TLS supervision
is an operator deployment concern; the gateway process itself needs no upstream
network access.

The Overdeck k3s installation packages those verified archives and these two source
files into an immutable ConfigMap, runs the gateway without credentials or egress,
and exposes it only on debian3's Tailnet address. From a trusted host with the three
exact `npm pack` outputs:

```bash
modules/sandbox/registry-gateway/deploy-k3s.sh ARCHIVE_DIRECTORY
```

The script verifies all three archive hashes, copies only the existing GHCR pull
credential needed for the pinned runtime image, and waits for the deployed gateway
to become ready. It never reads or stores a GitHub Packages token.

For each consuming repository, commit only this routing change (public packages
continue using the normal registry):

```ini
@platform-modules:registry=http://HOST_INTERFACE:4873/
```

When a pod cannot route the published Tailnet address directly, keep that `.npmrc`
and lockfile identity unchanged and set `HTTP_PROXY` only for the pnpm install step
to the credential-free in-cluster gateway Service. pnpm then tunnels only the exact
published authority through the gateway; the gateway refuses all other destinations.
Do not add a package token or disable lockfile URL verification.

Then, once, regenerate that repository's lockfile against the gateway and review
that the three `dist.tarball` URLs point to its immutable `/tarballs/...` paths.
Commit the `.npmrc` and lockfile together. Subsequent sandbox installs use
`pnpm install --frozen-lockfile`; no GitHub token enters the sandbox.
