# gitea The forge, and the mesh's npm package registry: it claims the `git` and `npm-package-registry` seats. Its tools, its events and the provisioner of registry accounts are the TypeScript bundle (`index.ts`, `tools/`, `provisioner/`). This README covers the Go bundle beside it. ## The package registry's retention (novox/hq ADR 0251 §4, to-be 51) Every publish adds a version to the registry, and until this nothing removed one. The Go bundle `cmd/npm-registry` says which versions each package holds, what keeps each one, and — asked with a why — deletes the versions nothing keeps. | tool | | what | |---|---|---| | `npm_packages` | r | every package of the registry's owner, each version newest first with its publish time, its size and why it is kept | | `npm_retention` | a | the versions retention would delete, and the bytes. **A dry run unless `dry_run` is false**; a real run needs `why` | **A version is kept when:** - a lockfile on the default branch of any repository on the forge names it — `package-lock.json` (every lockfile version), `npm-shrinkwrap.json`, `yarn.lock` (classic and berry) and `pnpm-lock.yaml` (by each resolved `name@version` or `name/version`), whatever the version's age; - it is the highest published version satisfying a range that a `package.json` there names in its dependencies, development, peer or optional dependencies (an `npm:` alias counts for the package it stands for; a path, a URL, git or a workspace is not a range on this registry). npm itself installs the `latest` dist-tag when it satisfies the range; that version is kept by its dist-tag; - a dist-tag names it — and a range that *is* a dist-tag's name keeps that tag's version; - it is among the newest `keep` of its package, five by default (the artifact store's five builds, ADR 0189 §3), by semantic-version order. **Pre-releases count** among the newest. A version that is not a semantic version is never ordered, so it is kept. A range that cannot be read, or a package whose dist-tags cannot be read, keeps **every** version of its package, and the answer says why under `keeps_all`. **Nothing is deleted on partial knowledge.** A repository whose files could not be listed, or a manifest or lockfile that could not be fetched, is named under `repositories_unread` in every answer, and a real run then deletes nothing at all. A file that was fetched but is not readable (broken JSON) is named under `files_not_read`, and so is a lockfile entry of a shape the reader does not know (the rest of that file is still read); what it would have named is not known, so a real run then deletes nothing at all either. Under `node_modules` nothing is read: that is what a lockfile already says. An empty repository, or one without its default branch, holds nothing to read and is not a failure. A real run deletes each version through the forge's own interface (`DELETE /api/v1/packages/{owner}/npm/{name}/{version}`), says what it deleted and what the forge refused, and a version already gone counts as deleted. ### How it reaches the forge Over the forge's HTTP interface on the machine (`MESH_GITEA_URL`), as the admin account the vault delivered (`MESH_GITEA_ADMIN_USER`, the password in `MESH_GITEA_ADMIN_PASSWORD_FILE` — the same file the TypeScript bundle mints its token with), by basic authentication: this bundle mints no token and keeps nothing. The password is read per call and never logged, answered or put in an error. The registry's owner is `MESH_NPM_OWNER`, the owner in the seat's `npm-path`. Calls to the forge run eight at a time, and one tool call reads for at most 50 seconds, inside a module's 60-second ask. ### Why the manifest lists no `tools` The TypeScript bundle's tools are served without a `tools` list, and a claim without `serves` offers the module's `tools` as the seat's verbs — so a list here would make these two tools verbs of both the `git` and the `npm-package-registry` seats. The two names are kept in `ToolNames`, and a test holds them to this README and to what the bundle serves. ### Tests ``` go test ./... ``` Against a fake forge (`httptest`): what keeps a version (a lockfile whatever its age, the highest version satisfying a range, a dist-tag, the newest `keep`); a dry run deleting nothing; a real run without why refused; a real run deleting only what nothing keeps; an unread repository stopping a real run before anything is deleted; an unreadable range keeping its whole package; a wrong password failing without saying the password. And the range matcher against npm's rules — exact, `^`, `~`, `x` and `*`, comparisons with partial versions, hyphen ranges, `||`, and the pre-release rule — and each lockfile format.