plugins/lt-dev/skills/nest-server-core-vendoring/SKILL.md
Provides knowledge and resources for projects that have vendored the @lenne.tech/nest-server core directly into their source tree (under projects/api/src/core/ instead of consuming via npm). Covers the vendor model, the flatten-fix pattern, the Upstream-to-Project sync workflow, the Project-to-Upstream PR workflow, typical conflicts, and how cosmetic changes are distinguished from substantial upstream candidates. Activates for vendored nest-server core discussions, "sync core from upstream", "port local core change to upstream", conflict resolution during vendor sync, or questions about the vendor pattern. Delegates execution to lt-dev:nest-server-core-updater (for syncs) and lt-dev:nest-server-core-contributor (for upstream PR preparation). NOT for npm-based nest-server updates (use nest-server-updating). NOT for writing new NestJS code (use generating-nest-servers).
npx skillsauth add lennetech/claude-code nest-server-core-vendoringInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
core-persistence-model.interface.ts — During flatten-fix, most files get '../../..' rewritten to '../..'. This file is an exception: it sits one directory deeper and needs '../../..' → '../..' → '..'. Missing this step causes a silent Cannot find module at runtime, not compile-time.migrate CLI disappears after vendoring — The upstream @lenne.tech/nest-server package exports a migrate binary in its package.json. When vendored (no longer a dependency), this binary is gone. Projects that relied on pnpm migrate will need to run the migration script directly from src/core/.src/core/ are invisible to future /update-nest-server-core runs — The updater does AI-driven curation but cannot read your intent. Document every intentional local deviation in src/core/LOCAL-PATCHES.md so the next sync doesn't silently undo your work.This skill provides knowledge and resources for lenne.tech projects that have vendored the @lenne.tech/nest-server core into their source tree. For automated execution, use the matching agents:
lt-dev:nest-server-core-updater via /lt-dev:backend:update-nest-server-core —
pulls upstream changes into the vendored core, with AI-driven curation against
local patcheslt-dev:nest-server-core-contributor via /lt-dev:backend:contribute-nest-server-core —
identifies substantial local changes to the vendored core and prepares them as
Upstream-Pull-Requests to the nest-server repository| User Intent | Correct Skill | | ---------------------------------------------------------- | ------------------------------ | | "Sync vendored core from upstream v11.26.0" | THIS SKILL | | "Port this CrudService fix back to nest-server" | THIS SKILL | | "Apply flatten-fix after upstream copy" | THIS SKILL | | "Update nest-server via npm" | nest-server-updating | | "Migrate from nest-server 11.17 to 11.24" | nest-server-updating | | "Create a new NestJS module" | generating-nest-servers | | "Fix a CVE via npm audit" | maintaining-npm-packages | | "Modify @lenne.tech/nest-server itself and test via pnpm link" | contributing-to-lt-framework |
A project is considered vendored if all of the following are true:
projects/api/src/core/VENDOR.md existsprojects/api/package.json does not list @lenne.tech/nest-server in
dependencies or devDependenciesprojects/api/src/core/ contains at least common/, modules/, index.ts,
core.module.tsA project is npm-based (classic) if:
@lenne.tech/nest-server is a regular dependency in package.jsonVENDOR.md under src/core/The nest-server-updater (classic agent) detects this automatically and delegates
to nest-server-core-updater for vendored projects.
src/core/)Vendoring copies the framework source into the project tree so Claude Code can read it directly — this is a comprehension aid, not an invitation to fork. The policy:
src/core/ ONLY when the change is generally useful to all
nest-server consumers. Valid reasons:
src/core/),
via modification, inheritance, extension, or ICoreModuleOverrides.
Project-specific business rules, customer enums, or proprietary
integration adapters must never live in the vendored core.github.com/lenneTech/nest-server. Use
/lt-dev:backend:contribute-nest-server-core to prepare the PR. Do not
let useful fixes rot in a single project's vendor tree — they belong
upstream so every consumer benefits and the local patch disappears on
the next sync.src/core/. The contributor
agent exists precisely to keep the vendor tree close to upstream.The nest-server-core-contributor agent enforces this distinction by
categorizing every local commit as upstream-candidate (generic) vs.
project-specific (stays local) vs. unclear (asks the human).
The vendored core lives as first-class project code. Flow is:
Upstream (github.com/lenneTech/nest-server)
|
| /lt-dev:backend:update-nest-server-core (curated, one-way)
v
Project vendor (projects/api/src/core/)
|
| /lt-dev:backend:contribute-nest-server-core (manual review, cherry-pick)
v
Upstream PR (via normal GitHub review process)
Local patches are expected. Projects legitimately modify the vendored core when business rules, integration adapters, or bugfixes are needed before upstream ships them. Those patches persist through syncs.
Changes are never auto-pushed. The contributor agent prepares PR drafts — a human reviews and submits them through normal GitHub workflow. No git-subtree push, no automatic upstream replay.
Upstream organizes its tree as:
nest-server/
├── src/
│ ├── index.ts ← re-export hub (imports './core/common/...')
│ ├── core.module.ts ← CoreModule factory (imports './core/modules/...')
│ ├── core/
│ │ ├── common/
│ │ └── modules/
│ ├── test/
│ │ └── test.helper.ts ← imports '../core/common/helpers/db.helper'
│ ├── templates/
│ ├── types/
│ └── ...
└── LICENSE
When vendored, the project gets a flat structure under src/core/:
projects/api/src/core/
├── VENDOR.md ← NEW
├── LICENSE ← copied for provenance
├── index.ts ← moved up from upstream src/, imports rewritten
├── core.module.ts ← moved up from upstream src/, imports rewritten
├── common/ ← copied as-is
├── modules/ ← copied as-is
├── test/ ← test.helper.ts, with imports rewritten
├── templates/
└── types/
This requires a single one-shot import-path rewrite on exactly three files:
index.ts — strip ./core/ prefix from every relative import/export
specifier. About 161 rewrites. (ts-morph AST-based.)core.module.ts — same strip pattern, about 27 rewrites.test/test.helper.ts — upstream uses ../core/common/helpers/db.helper;
after flatten the correct path is ../common/helpers/db.helper. The
../core/ prefix gets stripped here too, exactly once.Internal imports inside common/, modules/, etc. are not touched —
their relative paths between each other are identical before and after
the flatten.
One additional edge case:
src/core/common/interfaces/core-persistence-model.interface.ts imports
CorePersistenceModel from '../../..'. Upstream that reached src/index.ts
(three levels up), but after the flatten it should be '../..' (two levels up
to src/core/index.ts). Manual fix, documented in VENDOR.md.
The nest-server-core-updater agent knows all three of these edge cases and
reapplies them idempotently on every upstream sync.
Vendoring pulls upstream TypeScript that may use modern language features or
imports that the consumer project's tsconfig.json does not yet allow.
Common adjustments on the consumer side:
| Symptom | Fix |
| -------------------------------------------------------- | -------------------------------------------- |
| new Error(msg, { cause: e }) flagged | target: "es2022" in tsconfig |
| vite.config.ts cannot find vite module | Exclude vite.config.ts from tsc compile |
| migration-project.template.ts flags bad imports | Exclude src/core/modules/migrate/templates/**/*.template.ts |
| jsonTransport: true rejected in smtp config | Widen vendor smtp? union to include JSONTransport.Options |
| @types/supertest old types mismatch test.helper.ts | Bump @types/supertest to match upstream |
All of these are legitimate upstream-candidate patches — they fix
problems that every consumer will hit. The nest-server-core-contributor
agent should recognize them and suggest them as Upstream-PR candidates.
Upstream ships a migrate CLI as a bin field in @lenne.tech/nest-server
package.json. Since we drop that package, the CLI is no longer auto-installed
into node_modules/.bin/. Two workarounds:
migrate CLI available
(npm i -g @lenne.tech/nest-server once per dev machine). The vendored
store/compiler files are resolved locally — the CLI itself is a thin
wrapper.migrations-utils/cli.js
that imports the vendored migrate-runner directly. More robust, more work.The migrate:* scripts in package.json should use a local ts-node bootstrap
because the project-level tsconfig.json usually restricts types to
vitest/globals only, which strips out @types/node and crashes the ts-node
compile of vendored core files:
// migrations-utils/ts-compiler.js
const tsNode = require('ts-node');
tsNode.register({
transpileOnly: true,
compilerOptions: {
module: 'commonjs',
target: 'es2022',
esModuleInterop: true,
experimentalDecorators: true,
emitDecoratorMetadata: true,
skipLibCheck: true,
types: ['node'],
},
});
Then in package.json scripts: --compiler ts:./migrations-utils/ts-compiler.js.
When a new upstream version is available, the nest-server-core-updater agent:
VENDOR.md baseline version and baseline commit SHA/tmp/upstream-delta.patch: upstream baseline → upstream targetlocal-changes.patch: upstream baseline → current project vendorconflicts.json: file-level intersection of both diffsindex.ts, core.module.ts,
test/test.helper.ts, and any edge-case files documented in VENDOR.mdpnpm run test — commits if greenCLAUDE.md into projects/api/CLAUDE.md — the
nest-server CLAUDE.md contains framework-specific instructions that Claude
Code needs to work correctly with the vendored source. Section-level merge:
new upstream sections are added, existing project-specific sections are
preserved. The vendor-mode notice block (<!-- lt-vendor-marker -->) is
always kept.VENDOR.md with new baseline + sync history entryWhen a local change in the vendored core looks generally useful, the
nest-server-core-contributor agent:
VENDOR.md baseline versiongit log --oneline src/core/ since baselinechore: format, style:, oxfmt, lint:fix, prettierupdate-nest-server-core run will pick up the
change as upstream-delivered and can remove the local patch from
VENDOR.md's local-changes logRunning pnpm run format and pnpm run lint on a freshly vendored upstream
often produces a formatting-only commit if the project's formatter config
differs from upstream's. These commits have real line changes but zero
semantic content. Without filtering, the contributor agent would suggest
them as upstream-PRs — wasting reviewer time on upstream and creating
unwanted churn.
The filter lives in the agent, not in .oxlintignore or .prettierignore.
The vendored code should always stay format-compliant with project standards.
In the lenne.tech ecosystem, nest-server and nest-server-starter use the
same oxfmt configuration, so the initial format-commit after vendoring
is usually a no-op anyway. If the target consumer uses a different formatter,
the first format-commit may be substantial — and it should be one isolated
commit with a clear chore: format prefix so the filter recognizes it.
If the vendor pilot fails or needs to be reverted:
# In the consumer project (e.g. imo):
cd projects/api
git log --oneline | grep -E "vendor|framework" | head -20
# Identify the vendor commit range
git revert <first-vendor-commit>..<last-commit> --no-edit
pnpm install
pnpm run test
This restores @lenne.tech/nest-server as an npm dependency and removes the
src/core/ tree. No data loss, no upstream impact.
cli/src/extensions/server.ts#convertCloneToVendored (https://github.com/lenneTech/cli)development
Single source of truth for the lenne.tech fullstack production-readiness checklist. Defines the eight pillars (configuration & secrets, observability & logging, health & lifecycle, security hardening, data durability, resilience under load, deployment hygiene, runbook & rollback) with concrete file/line evidence requirements per pillar, severity classification (Critical / Major / Minor), and a canonical machine-parseable report block. Activates whenever an agent or command needs to gate a release on production-readiness — currently used by /lt-dev:production-ready, lt-dev:production-readiness-orchestrator, and the devops-reviewer (read-only). NOT for OWASP-style code-level security review (use security-reviewer). NOT for npm dependency audits (use maintaining-npm-packages).
development
Single source of truth for executing GitLab CI/CD pipelines locally with the same image, env vars, and service containers as the real runner — so pipeline failures are caught before push. Defines pipeline discovery (.gitlab-ci.yml + includes), per-job execution via gitlab-runner exec, service-container orchestration (Mongo, Redis, MailHog), env injection without secrets, cache/artifact handling, and a job-by-job verdict report. Also describes the GitHub Actions equivalent via act for projects that mirror to GitHub. Activates whenever an agent or command needs to validate that the CI pipeline will pass — currently used by /lt-dev:production-ready and lt-dev:production-readiness-orchestrator. NOT for running the local check script (use running-check-script). NOT for writing or refactoring CI configs (use the devops agent).
development
Single source of truth for designing, running, and interpreting k6 load tests against lenne.tech fullstack APIs. Defines installation paths (brew, docker, npm), the three canonical scenarios (smoke / load / soak), endpoint discovery from the generated SDK, realistic Better-Auth login flows, threshold defaults for ~10 concurrent users (p95 < 500ms, error rate < 1%, http_req_failed < 1%), result interpretation, and the optimisation ladder when the system fails (DB indices, query rewrites, caching, connection pool sizing, rate-limit relaxation, payload trimming). Activates whenever an agent or command needs to validate that the API is stable for ~10 concurrent users performing many actions in short time, or to detect performance regressions via k6. Currently used by /lt-dev:production-ready, lt-dev:production-readiness-orchestrator, and lt-dev:performance-reviewer. NOT for Lighthouse frontend performance (use a11y-reviewer). NOT for unit performance assertions (use the test runner directly).
tools
Migrates lenne.tech projects from the legacy jest+eslint+prettier toolchain to the current vitest+oxlint+oxfmt baseline used by nest-server-starter and nuxt-base-starter. Covers swc decoratorMetadata config, the @Prop union-type fix for SWC, supertest default-import correction, ESM/CJS interop, the Nitro PORT-vs-NITRO_PORT bug, ANSI escape stripping in workspace runners (lerna/nx), free-port logic for check-server-start.sh, the offers-pattern config.env.ts (NSC__-only + fail-fast + auto-derived appUrl), and the multi-phase check-envs.sh smoke test. Activates whenever someone is migrating an existing project to the new toolchain, debugging "Cannot determine a type for the X field" Mongoose errors, ERR_SOCKET_BAD_PORT crashes from check-server-start, or wants to align an existing project with the current starter conventions.