Repository navigation
feat(cli): add maven and nuget dependency transports to meta deps - #541
Merged
Merged
Conversation
…(FR-023)
A shared model published as a jar or nupkg is now a declared dependency:
{ name, maven: groupId:artifactId, version, dir? } and { name, nuget, version, dir? }.
Resolution reads the local Maven repository (honouring MAVEN_REPO_LOCAL,
maven.repo.local and settings.xml) or the NuGet global packages folder
(NUGET_PACKAGES), never downloads, and names the GAV or package id plus the
fetch command when the package is missing. Java, C# and Python config and lock
readers accept the new keys.
…admap FR-023 line; llms mirrors left for release cut
…roadmap.md FR-023 line; README, CLI doc, metadata-dependencies and CHANGELOG already match the change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Design decision: declaration field names
The design doc does not settle them. Chosen, following the
path/npm/pythonshape:{ "name": "x", "maven": "groupId:artifactId", "version": "1.0.0", "dir"?: "..." }{ "name": "x", "nuget": "Id", "version": "1.0.0", "dir"?: "..." }versionis required for these two transports and illegal beside the others.diris allowed beside every transport exceptpath; the default for maven and nuget ismetaobjects.resolvedFromcarries the declaration minusname(maven/nuget,version, optionaldir), socheckdetects a version change as well as a content change.checkreports such a dependency as unresolved and points at the Nodemeta deps check; per-port sync is out of scope.metaobjects/in the jar or nupkg.Gate runs
One no-mistakes run (with review, test and document fix rounds inside it). Two ask-user gates were escalated to the supervising orchestrator and answered there: the test-step agent timeout (the unvalidated help-text commit was then validated with the ts-unit lane) and the two release-tagged
docs/llmsmirrors, which are left for the release cut. Local lanests-fast,ts-unitandgateswere green before the run.What Changed
meta deps syncandmeta deps checkaccept{ "name", "maven": "groupId:artifactId", "version" }and{ "name", "nuget": "Id", "version" }. They read the artifact and manifest from the package'smetaobjects/directory (diroverrides it) in the local Maven repository ($MAVEN_REPO_LOCAL,-Dmaven.repo.local,settings.xml, then$HOME/.m2/repository) or the NuGet global packages folder ($NUGET_PACKAGES, else$HOME/.nuget/packages). Neither downloads. A package missing from the cache fails naming the GAV or package id and the fetch command.lib/zip-read.ts, a minimal read-only ZIP reader (stored and deflate; refuses ZIP64, encryption and zip-slip entries) used to read jars and nupkgs.checkreports such a dependencyunresolvedand points to the Nodemeta deps check. Per-port sync is not changed.dependency-conformancecorpus gains 2 resolution cases and 18 transport cases. Node tests build a jar and a nupkg with the same layout as the publishers' output and cover current, drift and missing-package states.docs/features/metadata-dependencies.mdanddocs/features/cli.md; CHANGELOG entry under Unreleased.Validation
Risk Assessment
✅ Low: The three round-1 fixes check out against the code: zip-slip guard now refuses
\and:,packagedDirnormalizes and refuses escaping paths, andmeta deps --helplists maven and nuget. The JDK-built jar fixture is an independent oracle for the reader. The Java, C# and Python reader changes match the Node declaration shape. I did not run tests, per the review rules.Testing
Validated 88fe5a4 with the ts-unit lane only, as the operator directed. Live: drove
meta deps --helpthrough the real CLI entry. Help text interpolates PACKAGED_MODEL_DIR, so the default dir reads "metaobjects" with maven/nuget rows and cache sources. That scenario passed live. The ts-unit suite result is recorded as a regression check, not a live scenario, and is marked untested. The full ci-local run and the complete regression suite were not run because the operator narrowed scope to ts-unit; this is a gap the operator chose.meta deps --helpshows the packaged default dir from the PACKAGED_MODEL_DIR constant, with maven and nuget rowsEvidence: meta deps --help live output
Pipeline
Updates from git push no-mistakes
✅ **Intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 4 issues found → auto-fixed ✅
server/typescript/packages/cli/src/lib/zip-read.ts:65- The zip-slip guard splits entry names on '/' only. The extractor then writes each entry withjoin(target, ...name.split('/'))(dependency-transports.ts:333). On Windows,path.joinalso treats '&feat(codegen-csharp): non-TPH entity inheritance chain via DirectMappedParent #39; as a separator, and Windows is a supported platform: the docs describepythonon Windows. Example: a jar or nupkg in the local cache holds the entrymetaobjects/..\..\..\Users\me\x.json. That name passes the prefix check and theincludes('..')check, because no '/'-separated segment equals '..'.writeFileSyncthen writes outside the temp directory. The intent requires that the reader refuse zip-slip, so this case breaks that requirement. Fix: in readZipEntries, also refuse a name that contains '&feat(codegen-csharp): non-TPH entity inheritance chain via DirectMappedParent #39; or a drive-letter colon. Better, add a final check in unpackZipDir thatrelative(target, dest)does not start with '..' and is not absolute, so every caller is covered.server/typescript/packages/cli/src/index.ts:306- Themeta depshelp text still says three transports exist: "path", "npm" and "python". It also says "dir" names the directory inside "an npm or python package (default: the package root)". The change does not touch this text. A user who runsmeta deps --helpdoes not seemavenornuget, the requiredversion, themetaobjectsdefaultdir, or the fact that sync never downloads. The intent lists the CLI doc in scope, and docs/features/cli.md was updated, but this built-in help text was not. Add the maven and nuget rows to the help text, and also say where each one reads its cache from.server/typescript/packages/cli/src/lib/dependency-transports.ts:319- The comment on packagedDir says it applies "the same rules as applyDir's dir", but the rules differ. applyDir (npm and python) resolves the path, so"dir": "./shared"and"dir": "a/../shared"both work there. packagedDir only strips trailing slashes. For"./shared", maven looks for the jar prefix./shared/and finds nothing, so it reports a misleading "has no &test(conformance): combined multi-package extends + overlay + cross-package references fixture #34;./shared/&test(conformance): combined multi-package extends + overlay + cross-package references fixture #34; directory" error. nuget behaves differently for the same value: its extracted-folder branch works throughjoin, but its .nupkg fallback fails.a/../sharedis refused outright. Fix: normalize withpath.posix.normalize, strip a leading './', and refuse only a result that is '..', starts with '../' or is absolute.server/typescript/packages/cli/test/deps-packaged-transports.test.ts:223- Every jar and nupkg in the tests and in transport-cases.json comes from the test-onlywriteZiphelper, written next to the reader. That helper always writes real sizes in the local header, never sets the data-descriptor bit (0x08), and writes no extra fields. So no test proves the reader handles archives that real tools produce. The JDKjartool and many archivers use data descriptors with zeroed local sizes, and JarOutputStream puts a 0xCAFE extra field in the first local header. The reader looks correct for these cases, because it takes sizes from the central directory and reads the local extra length on its own. But a shared misreading of the spec would pass both helper and reader. Add one small committed fixture built by a real tool (jar/zip -rordotnet pack) as an independent oracle. It would reject a reader that trusted the local-header sizes.🔧 Fix applied.
✅ Re-checked - no issues remain.
🔧 **Test** - 2 issues found → auto-fixed → no changes applied ✅
meta deps --helphard-coded the packaged directory name, which the metadata-directory guard rejected. It now interpolatesPACKAGED_MODEL_DIR, and the guard is green.scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsscripts/ci-local.sh --only ts-unit --strict-toolchains (failed before fix: no-hardcoded-metadata-dir guard; passes after fix, LOCAL CI PASSED)bun test test/no-hardcoded-metadata-dir.test.ts (sdk) - 5 passbun test test/help-and-exit.test.ts test/help-lists-every-flag.test.ts test/deps-packaged-transports.test.ts (cli) - 42 passbun test (server/typescript/packages/cli, full suite) - 1998 tests, 0 failbun server/typescript/packages/cli/bin/meta.ts deps --help - live: help lists maven and nuget transports, version requirement, default dirLive maven scenario in disposable /tmp project with JDKjar-built jar at isolated MAVEN_REPO_LOCAL and HOME:meta deps syncwrites lock (transport+version+integrity) and snapshot;meta deps checkreports currentLive drift scenario: republished jar with widened model,meta deps checkreports drifted and ERR_DEPENDENCY_UPSTREAM_DRIFTLive missing-package scenario: empty MAVEN_REPO_LOCAL,meta deps syncexits 2 naming GAV com.acme:acme-common-model:1.0.0, expected jar path, andmvn dependency:getfetch command; states it does not downloadNot run: full ts-fast lane (includes 30-min mutation gate). Another ci-local run (pid 3393490) was already active in this worktree; I did not start or kill it.🔧 Fix applied.
3 issues were open at that point; all are resolved, as noted:
meta deps --helphard-coded the packaged directory name, which the metadata-directory guard rejected. It now interpolatesPACKAGED_MODEL_DIR, and the guard is green.scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsscripts/ci-local.sh --only ts-unit --strict-toolchains (failed before fix: no-hardcoded-metadata-dir guard; passes after fix, LOCAL CI PASSED)bun test test/no-hardcoded-metadata-dir.test.ts (sdk) - 5 passbun test test/help-and-exit.test.ts test/help-lists-every-flag.test.ts test/deps-packaged-transports.test.ts (cli) - 42 passbun test (server/typescript/packages/cli, full suite) - 1998 tests, 0 failbun server/typescript/packages/cli/bin/meta.ts deps --help - live: help lists maven and nuget transports, version requirement, default dirLive maven scenario in disposable /tmp project with JDKjar-built jar at isolated MAVEN_REPO_LOCAL and HOME:meta deps syncwrites lock (transport+version+integrity) and snapshot;meta deps checkreports currentLive drift scenario: republished jar with widened model,meta deps checkreports drifted and ERR_DEPENDENCY_UPSTREAM_DRIFTLive missing-package scenario: empty MAVEN_REPO_LOCAL,meta deps syncexits 2 naming GAV com.acme:acme-common-model:1.0.0, expected jar path, andmvn dependency:getfetch command; states it does not downloadNot run: full ts-fast lane (includes 30-min mutation gate). Another ci-local run (pid 3393490) was already active in this worktree; I did not start or kill it.🔧 No changes applied.
✅ Re-checked - no issues remain.
meta deps --helpshows the packaged default dir from the PACKAGED_MODEL_DIR constant, with maven and nuget rowsscripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainscd server/typescript/packages/cli && bun ./bin/meta.ts deps --help (live CLI run; output shows maven and nuget transports,dirdefault "metaobjects" for maven/nuget, and the $MAVEN_REPO_LOCAL / $NUGET_PACKAGES cache paths)scripts/ci-local.sh --only ts-unit (run on commit 88fe5a46c, per operator guidance; reported LOCAL CI PASSED; not a live product scenario)git status after testing: clean tree, no transient artifacts left in the worktree🔧 **Document** - 2 issues found → auto-fixed ✅
docs/llms/llms.txt:66- llms.txt and llms-full.txt still say Maven and NuGet transports are design only; they are release-tagged mirrors, so left for the release cut.docs/llms/llms-full.txt:120- Same stale 'design only' sentence in llms-full.txt; left with llms.txt for the release cut.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.