// gitea's provisioner — the adapter that makes gitea a provider of the mesh `package-registry` // interface. The reconcile loop, the contributions file, and reading the mesh's minted password are // the sdk harness's; this writes only the per-service half: how gitea creates and removes a // consumer's npm credential (novox/hq ADR 0048/0076). // // The `package-registry` interface: a consumer authenticates to the npm registry at // `/api/packages/novox/npm/` with basic auth, as `as` with the password the mesh minted, and can // read and write packages under the `@novox` scope. The registry's npm owner is the gitea org // `novox`; a consumer is a gitea *user* placed on that org's package team. // // **The user name and password are the mesh's, not the provisioner's (ADR 0048).** The mesh derives // the login and hands it to both ends, and mints the password. gitea creates a user under exactly // that login and sets exactly that password every run — so a rotation takes — and seals nothing: the // consumer already has its copy through the mesh's own channel. // // The admin calls run through GiteaAdmin (basic auth as the mesh's gitea admin), which is the // module's one boundary to the forge's admin API (see client.ts). import { runProvisioner, type Provision } from "@novox/mesh-sdk/provisioner"; import { GiteaAdmin } from "../client.js"; // The npm registry owner: a gitea org named `novox`, whose package team every consumer joins so it // can read and write packages under the `@novox` scope (ADR 0076). const ORG = "novox"; const PACKAGE_TEAM = "packages"; const gitea = GiteaAdmin.fromEnv(); runProvisioner("package-registry", { async create(p: Provision): Promise { // The org and its package team are the same for every consumer; ensuring them per-create is // idempotent and needs no separate bootstrap step. await gitea.ensureOrg(ORG); const teamId = await gitea.ensureTeam(ORG, PACKAGE_TEAM, true); // The user carries the consumer's login and the mesh's minted password, set every run so a // rotation takes. Membership of the package team is what grants read+write on packages. await gitea.ensureUser(p.as, p.password, `${p.as}@localhost`); await gitea.addUserToTeam(teamId, p.as); }, async remove(p: { as: string }): Promise { await gitea.deleteUser(p.as); }, });