build(release): publish the vendored framework and the native packages publicly

The three release sequences shipped with publishConfig.access: restricted, so
nothing in the @deepseek-ai scope was installable from outside the organization.

A restricted dependency is what actually blocks a public consumer: every harness
package declares the vendored framework as a peerDependency, and
dsh-sandbox-local declares the Landlock entry as a dependency. Those two
sequences therefore go public first — the nine vendor/* packages and the three
native/landlock-run packages — while the dsh family stays restricted until its
own sequence is opened deliberately. No public package requires a restricted one
in this arrangement.

Access is now per sequence, so no publish path can pass --access: one flag
cannot express two levels and would override the manifest that owns the fact.
publish.ts stops passing it, matching the native workflow, and
check-workspace-constraints holds each manifest to its own sequence's level,
which is what stops the scope from drifting one package at a time.

Harness consumers reference the Landlock entry as workspace:^ instead of
workspace:*, so a published harness package accepts the entry's patch and minor
releases. The entry keeps workspace:* for its platform packages, where the
binary must match the entry version exactly.

Two rationales that named a private registry no longer describe the vendored
sequence; they now state the durable reason, which is that the verification must
not depend on the registry already carrying matching versions.
This commit is contained in:
imccyu
2026-08-13 13:55:05 +08:00
parent 1646b7617e
commit a213befd0f
29 changed files with 152 additions and 50 deletions

View File

@@ -231,8 +231,8 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
if (manifest.private === true) {
errors.push(`${label}: published Landlock package must not set "private": true`)
}
if (manifest.publishConfig?.access !== 'restricted') {
errors.push(`${label}: published Landlock package must set publishConfig.access to "restricted"`)
if (manifest.publishConfig?.access !== 'public') {
errors.push(`${label}: published Landlock package must set publishConfig.access to "public"`)
}
const expectedDirectory = dir
if (manifest.repository?.type !== 'git'
@@ -242,13 +242,21 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
}
} else if (releaseMemberDirectory.test(dir)) {
// Release members state that they are publishable: npm refuses a private
// package, the scope is published privately, and the repository field is
// how a consumer of a private package finds its source.
// package, and the repository field is how a consumer finds the source of
// the package it installed.
//
// Access is per release sequence, not per scope: the vendored framework and
// the Landlock packages publish publicly because outside consumers install
// them, while the dsh family stays restricted until its own sequence goes
// public. A mixed scope is why no publish path passes `--access` — one flag
// cannot serve both, so each packed manifest decides
// ([rationale](../.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.md)).
const expectedAccess = dir.startsWith('vendor/') ? 'public' : 'restricted'
if (manifest.private === true) {
errors.push(`${label}: release member must not set "private": true`)
}
if (manifest.publishConfig?.access !== 'restricted') {
errors.push(`${label}: release member must set publishConfig.access to "restricted"`)
if (manifest.publishConfig?.access !== expectedAccess) {
errors.push(`${label}: release member must set publishConfig.access to "${expectedAccess}"`)
}
if (manifest.repository?.type !== 'git'
|| manifest.repository.url !== publishedRepositoryUrl

View File

@@ -20,9 +20,6 @@ import { releaseFamily } from './families.ts'
import { attempt, isEntry, run } from './process.ts'
import { packedIdentity, readPublishOrder } from './tarball.ts'
/** npm access level for every package this repository publishes. */
const ACCESS = 'restricted'
/** What the registry knows about one version. */
type RegistryState =
| { readonly kind: 'absent' }
@@ -91,7 +88,11 @@ function main(): void {
}
// A prerelease version never takes the latest dist-tag.
const tagArgs = version.includes('-') ? ['--tag', 'next'] : []
run('npm', ['publish', tarball, '--access', ACCESS, ...tagArgs])
// No --access: the sequences do not share one access level, so a
// command-line flag could not serve both and would override the manifest
// that does. Each packed manifest decides, and
// check-workspace-constraints holds every manifest to its sequence's level.
run('npm', ['publish', tarball, ...tagArgs])
published += 1
}

View File

@@ -5,8 +5,9 @@
* Every tarball the installed tree needs comes from `--from`, so the only
* registry traffic is for external dependencies. That matters beyond hermetic
* verification: the harness packages declare the vendored framework as a peer,
* and those packages live in another release sequence that this credential-free
* job cannot fetch from a private registry — so a dsh verification passes the
* those packages live in another release sequence, and this job must not depend
* on the registry already carrying versions that match — one pull request may
* bump both families before either publishes — so a dsh verification passes the
* vendored family's pack output too, while publishing only its own
* ([rationale](../../.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md)).
*