# Gitea npm Package Registry Migration > **Goal:** Replace the `docker-prep.sh` + tarball workflow with Gitea's built-in npm package registry for `@bytelyst/*` shared packages. > > **Phase policy:** use **this Mac as the future single VM** and validate the entire flow locally first. No Azure rollout and no publishing to any external or corporate registry in this phase. --- ## 1. Decision We should adopt the local Gitea npm registry as the long-term package-distribution path for `@bytelyst/*` packages. We should **not** switch directly in Azure first. Instead, we should validate the exact end-to-end flow locally on this Mac: - local Gitea git hosting - local Gitea Actions - local Gitea npm package registry - local Docker / Docker Compose builds - local product repos consuming `@bytelyst/*` from local Gitea Once that is stable, we replicate the same validated shape on the Azure single VM. --- ## 2. Why We Want This ### Current pain Today many repos still depend on one of these Docker-time workarounds: - `file:` references to sibling `learning_ai_common_plat/packages/*` - `docker-prep.sh` - `.docker-deps` or older `.tarballs` copy steps - temporary `package.json` rewriting before builds This works, but it creates repeated operational drag: - every build may need prep - Dockerfiles become repo-specific and fragile - CI, local development, and Docker are not using one clean dependency source - path and build-context mismatches keep surfacing during ecosystem validation ### Target outcome We want one dependency source for shared packages: - local development - local CI via Gitea Actions - local Docker builds - later Azure single-VM builds That dependency source should be the **local Gitea npm registry**. --- ## 3. Local-First Target Architecture ### 3.1 This Mac as the rehearsal VM ```text This Mac ├── local Gitea (git + actions + npm registry) ├── local Docker / Docker Compose ├── learning_ai_common_plat └── product repos ``` Flow: ```text learning_ai_common_plat/packages/* ↓ build locally ↓ publish to local Gitea npm registry local Gitea npm registry (localhost:3300) ↓ install via semver refs product repos / Docker builds / local Gitea CI ``` ### 3.2 Future Azure single VM After the local rehearsal is proven, Azure should mirror the same shape: ```text Azure VM ├── Gitea ├── Gitea Actions runner ├── Gitea npm registry ├── Docker / Compose └── same repo + build flow ``` The Azure plan should reuse the validated local approach, not invent a second design. --- ## 4. What Is In Scope Right Now ### Included - validate local Gitea package-registry access - validate local Gitea Actions availability - define local-only package publish flow to local Gitea - define local-only consumer install flow from local Gitea - define local-only Docker build flow from local Gitea - define the later Azure single-VM replication steps ### Excluded - Azure changes right now - external npm registry publishing - corporate registry publishing - non-local deployment actions - K3s / Helm work --- ## 5. Current Local Readiness Snapshot Validated locally on this Mac: - local Gitea health endpoint responds - local Gitea version endpoint responds - local `bytelyst` user auth works - local Gitea Actions workflow exists for `learning_ai_common_plat` - local Gitea package registry endpoint is reachable - local pilot packages have been published to local Gitea successfully - a clean scratch consumer install from local Gitea works on the host That is enough to treat this Mac as the single-VM rehearsal environment. --- ## 5.1 Validation Results So Far ### Proven locally on this Mac - shared packages build cleanly in `learning_ai_common_plat` - a local-only Gitea package token was created and used successfully - pilot packages were published to local Gitea npm registry successfully - a clean scratch `pnpm install` from the local Gitea registry worked on the host - `learning_ai_flowmonk` was migrated on the host from tarball refs to semver `@bytelyst/*` refs - `learning_ai_flowmonk` host-side install, typecheck, and tests passed against the local Gitea registry ### Important implementation finding Publishing `@bytelyst/*` workspace packages with raw `npm publish` is not sufficient for this migration. Why: - packages with internal `workspace:*` dependencies can be published with unresolved workspace specifiers - those published artifacts break downstream consumers What worked: - `pnpm pack` produces normalized package metadata for workspace dependencies - publishing the normalized tarball to Gitea works This is now codified in the local-only helper script: `scripts/publish-local-gitea-packages.sh` That script is currently the authoritative local rehearsal path for publishing `@bytelyst/*` packages to local Gitea. ### Current blocker The remaining blocker is not host-side package publishing or host-side package consumption. The blocker is specifically: - Docker / BuildKit installs against the local Homebrew Gitea instance on this Mac - registry metadata and tarball fetch behavior across the Mac host ↔ Docker build boundary At the time of writing: - host-side registry usage is validated - FlowMonk host-side pilot migration is validated - Docker-side local-registry validation is still blocked That blocker must be resolved before we can claim full local E2E completion. --- ## 6. Migration Strategy ### Stage A — Local registry rehearsal Validate the package-registry path locally before changing every repo. Required outcomes: 1. local package token exists 2. a small pilot set of `@bytelyst/*` packages can be published to local Gitea 3. a local consumer can install them via semver refs 4. a Docker build can install them without `docker-prep.sh` 5. local Gitea Actions can run the same package build/publish path ### Stage B — Pilot repo migration Migrate one repo first. Recommended pilot: - `learning_ai_flowmonk` Reason: - recent Docker/build work already exposed its edge cases - both backend and web surfaces exist - it is a strong canary for dependency-distribution changes ### Stage C — Sequential ecosystem rollout After the pilot is stable, migrate remaining repos sequentially. --- ## 7. Local Implementation Plan ### 7.1 Verify package metadata in `learning_ai_common_plat` Every `packages/*/package.json` should have: - a valid `name` - a valid `version` - a valid `files` / `exports` setup - a successful local `build` Local validation command: ```bash cd /Users/sd9235/code/mygh/learning_ai_common_plat pnpm -r --filter './packages/*' build ``` ### 7.2 Create a local-only Gitea package token Use a token intended only for this Mac rehearsal. Required scopes: - package read - package write Do not use Azure or external registry credentials here. ### 7.3 Publish only to local Gitea In this phase, all `npm publish` activity must point only to: `http://localhost:3300/api/packages/bytelyst/npm/` No Azure Artifacts. No npmjs.org. No external corporate npm registry. Use the local-only helper script for this rehearsal: ```bash cd /Users/sd9235/code/mygh/learning_ai_common_plat GITEA_NPM_TOKEN='' bash ./scripts/publish-local-gitea-packages.sh ``` For a single package: ```bash cd /Users/sd9235/code/mygh/learning_ai_common_plat GITEA_NPM_TOKEN='' bash ./scripts/publish-local-gitea-packages.sh '@bytelyst/errors' ``` ### 7.4 Start with a minimal package pilot set Publish a small set first: - `@bytelyst/errors` - `@bytelyst/config` - `@bytelyst/api-client` Then expand once the local install path is proven. ### 7.5 Consumer dependency model after migration Consumers move from local file refs: ```json "@bytelyst/auth": "file:../../learning_ai_common_plat/packages/auth" ``` to semver refs: ```json "@bytelyst/auth": "^0.1.0" ``` And resolve via scoped `.npmrc` or `.pnpmrc` config pointing `@bytelyst` to local Gitea. ### 7.6 Docker model after migration After a repo is migrated to the registry model, its Dockerfiles should: - stop copying `.docker-deps` or `.tarballs` - stop depending on `docker-prep.sh` - install from local Gitea through scoped registry config That is the main operational simplification we want. --- ## 8. Local Validation Sequence ### Step 1 — Validate local Gitea surfaces Confirm locally: - Gitea UI is reachable - package registry API is reachable with auth - Actions workflow is visible and active ### Step 2 — Validate package build output Run local builds for the shared packages and confirm pack/publish inputs are clean. ### Step 3 — Publish a minimal package pilot set to local Gitea only Success means: - packages appear in local Gitea package list - metadata looks correct - no external registry interaction occurred ### Step 4 — Validate local install from Gitea Use a scratch consumer or a pilot repo surface and verify: - `pnpm install` resolves `@bytelyst/*` from local Gitea - lockfile updates are clean - no fallback to tarballs is required for the tested packages ### Step 5 — Validate Docker build from local Gitea For the pilot repo: - remove the tested surface's dependency on `docker-prep.sh` - add scoped registry config for Docker - build backend and web without tarball prep Success means: - image build works without `.docker-deps` or `.tarballs` - build does not require local package rewrite logic Current status on this Mac: - **not yet fully green** - the remaining issue is the local Homebrew Gitea instance serving package metadata/tarball URLs across the Docker build boundary - host-side validation is complete, Docker-side validation is still open ### Step 6 — Validate local Gitea Actions path Add or adapt a local-only workflow in `learning_ai_common_plat` that: - builds packages - optionally publishes to local Gitea npm registry - never targets an external registry ### Step 7 — Validate full local E2E At the end of the local rehearsal we should be able to say: - shared packages build locally - shared packages publish to local Gitea registry - a pilot consumer installs from local Gitea - a pilot Docker build succeeds from local Gitea - local Gitea Actions can drive the same path Only then should we expand repo-by-repo. --- ## 9. Recommended Rollout Order ### Pilot 1. `learning_ai_flowmonk` ### Then 2. `learning_ai_local_memory_gpt` 3. `learning_ai_notes` 4. `learning_ai_trails` 5. `learning_ai_fastgap` 6. `learning_ai_clock` 7. `learning_ai_jarvis_jr` 8. `learning_ai_peakpulse` 9. `learning_multimodal_memory_agents` 10. `learning_voice_ai_agent` The ordering prioritizes recently exercised Docker paths before higher blast-radius repos. --- ## 10. CI Model For The Local Rehearsal For the local rehearsal phase, Gitea Actions should do only local work: - build packages - test packages - typecheck packages - optionally publish to **local Gitea only** This is intentionally different from a final enterprise rollout. The objective is to prove the local VM pattern first. --- ## 11. Risks And Guardrails ### Risks - version drift between local source and published package versions - peer dependency mismatches hidden by current tarball workflow - Docker auth/config differences from shell installs - accidental publishing to the wrong registry - switching too many repos before the pilot is stable ### Guardrails - use local-only credentials for this phase - keep `@bytelyst` scoped registry config explicit - do not remove tarball fallback globally until the pilot is green - migrate one consumer repo at a time - keep rollback steps documented per repo --- ## 12. Rollback Plan If the registry-based flow fails during pilot migration: 1. revert the tested consumer back to its current working dependency mode 2. restore its `docker-prep.sh` path if needed 3. keep the Gitea registry work isolated to the local rehearsal branch/state 4. fix the issue locally before retrying No repo should lose its known-good build path until the registry model is proven. --- ## 13. Azure Single-VM Follow-Through After the local rehearsal is green, Azure should follow the same validated recipe: 1. provision one VM 2. install Docker and Gitea 3. enable Gitea Actions runner 4. enable Gitea packages 5. clone the same repos onto the VM 6. apply the same local registry/token/package flow 7. re-run the pilot repo first 8. then expand sequentially across the ecosystem Azure should be a replication step, not a redesign step. --- ## 14. Definition Of Done This migration plan is locally validated only when all are true: - [x] local Gitea package-registry auth verified - [x] local package publish path verified for a pilot package set - [x] local consumer install path verified - [ ] local Docker build path verified without `docker-prep.sh` - [ ] local Gitea Actions path verified - [ ] pilot repo migrated successfully end-to-end including Docker - [ ] rollback path documented and tested conceptually - [ ] Azure single-VM reproduction steps documented from the validated local process --- ## 15. Immediate Next Actions 1. create or verify a local-only Gitea package token 2. publish a minimal pilot `@bytelyst/*` package set to local Gitea only 3. validate install from local Gitea in one pilot consumer 4. validate Docker build from local Gitea in that pilot repo 5. validate the same path via local Gitea Actions 6. only then expand to broader ecosystem migration