61270bf3 feat: Solid 2 support (#2)
* feat: Solid 2 support
* feat(solid-virtual): publish as @rigelbuild/solid-virtual with a fork-owned workflow (RIG-2187)
Publish a Solid-2-compatible `@tanstack/solid-virtual` fork to npm as `@rigelbuild/solid-virtual`, so `compass` can drop its unresolvable `github:` pin (`github:RigelBuild/virtual#solid-2-support` resolves the monorepo root — no package export) and consume a real published package on the Solid-1→2 migration (RIG-2187).
Frozen design record: `docs/designs/platform/rigelbuild-solid-virtual-publish.md` (orion, DL-015).
## What this branch contains
Two commits, kept separate so the Solid-2 work stays upstreamable to `TanStack/virtual`:
- **`feat: Solid 2 support`** — the Solid-2 API port (`packages/solid-virtual/{src,tests,package.json}` + lockfile), unchanged from the `solid-2-support` branch. Kept as its own commit so it stays a clean, contributable diff for the eventual upstream PR (branch from upstream `main` + cherry-pick this commit).
- **this commit (publish-only)** — renames the package and wires the fork-owned publish:
- `packages/solid-virtual/package.json`: `name` `@tanstack/solid-virtual` → `@rigelbuild/solid-virtual`, `version` → `3.0.0-rc.0`. The `@tanstack/virtual-core` dep stays `workspace:*` — `pnpm publish` rewrites the `workspace:` protocol to the resolved range (`3.17.8`) at pack time, so no committed dep edit and no republish of `virtual-core` (it is unchanged from upstream). `repository`/`funding` metadata left as upstream (honest for a fork; keeps this commit minimal).
- `.github/workflows/publish-rigelbuild.yml`: a fork-owned publish gated `if: github.repository_owner == 'RigelBuild'`, firing on a `v*` tag or manual dispatch. Runs the monorepo `test:ci` (nx `run-many`, not `affected` — a tag push has no affected base, so `affected` would run nothing and could ship an unbuilt dist; `run-many` builds every package in dependency order), then a direct `pnpm publish --filter @rigelbuild/solid-virtual --tag <disttag> --no-git-checks`. The dist-tag is computed from the version (prerelease → `next`, GA → `latest`), mirroring the solid-markdown fork's `publish.yml`. Authenticated by the `NPM_TOKEN` Actions secret provisioned via orion Pulumi (separate PR).
Upstream `release.yml` (gated `if: github.repository_owner == 'TanStack'`) is left untouched. `changeset publish` is deliberately not used: it ignores `config.ignore`, rejects ignoring `virtual-core` while a non-ignored package depends on it, and mis-tags a prerelease as `latest` — the direct filtered publish scopes the one renamed package cleanly while still reusing the pnpm monorepo build/test infra (frozen record D2).
The publish itself (tag + workflow run + npm verify) is a follow-up once this and the orion token PR merge.
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build>
* fix(solid-virtual): make the publish workflow actually authenticate + publish (RIG-2187)
Fold review findings on the fork-owned publish workflow — three runtime-only failures a local build can't surface, all in the publish/auth plumbing:
- **HIGH — provenance needs `id-token: write`.** The fork root `.npmrc` sets `provenance=true`, so `pnpm publish` generates an npm provenance attestation signed via GitHub OIDC, which requires the job to hold `id-token: write`. The job had only `contents: read`, so the first `v*` tag would fail at the publish step. Added job-level `permissions: { contents: read, id-token: write }`, mirroring upstream `release.yml`. The NPM_TOKEN still authenticates the upload; provenance is the attestation, not the auth (this is not trusted publishing).
- **MEDIUM — first scoped publish needs public access.** `@rigelbuild/solid-virtual` is a new scoped package; npm defaults scoped packages to `restricted`, so the first publish would 402 (or publish privately, breaking the compass consumer contract). Added `"publishConfig": { "access": "public" }` to `packages/solid-virtual/package.json`, matching the proven `@rigelbuild/solid-markdown` precedent.
- **MEDIUM — pnpm auth was wired to inert env vars.** `NPM_CONFIG_TOKEN` maps to the legacy global `token` config registry.npmjs.org no longer accepts, and `NODE_AUTH_TOKEN` is a setup-node convention pnpm doesn't read natively — so the publish would 401/ENEEDAUTH. Replaced both with the per-registry URL-scoped env var `pnpm_config_//registry.npmjs.org/:_authToken`, which pnpm (>=11.6) honors natively: file-free, and un-redirectable since the registry is baked into the key.
Spec-impact: none
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build>
* fix(solid-virtual): publish without provenance to match the fork's upstream-pointed manifest (RIG-2187)
Round-2 review HIGH: the previous review-fix added `id-token: write` to
let `pnpm publish` sign a provenance attestation, but the package's
`repository.url` points at the upstream `TanStack/virtual` repo (frozen
in DL-015 as "honest for a fork"), while the workflow publishes from
`RigelBuild/virtual`. npm provenance requires `repository.url` to match
the publishing repo (OIDC-derived) or the registry rejects the upload
(422/EPROVENANCE) — so the first `v*` tag would fail at publish.
The design-consistent resolution is to publish WITHOUT provenance,
exactly like the `@rigelbuild/solid-markdown` precedent (no provenance,
no id-token, `repository.url` left as-is), keeping DL-015's frozen
decision to leave `repository.url` pointing upstream:
- Force provenance off at publish time via `pnpm_config_provenance:
"false"` on the Publish step. This is the only surface pnpm 11 reads
provenance from: `isNpmrcReadableKey` (pnpm11 config/reader
localConfig.ts) admits only auth/network keys, so a `provenance` line
in any `.npmrc` (including the repo-root `provenance=true`) is silently
ignored — the env var (`pnpm_config_*`, lowercase; pnpm 11 dropped
`npm_config_*`) makes OFF explicit and version-proof rather than
relying on that default. No `.npmrc` edit (which pnpm ignores) and no
CLI flag (pnpm exposes none) can do this.
- Drop the now-dead `id-token: write`, reverting the job to
`permissions: { contents: read }` — no OIDC token is minted, matching
the solid-markdown precedent and avoiding an orphaned permission
widening on a token-handling workflow.
Spec-impact: none
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build>
---------
Co-authored-by: Matt Wilkinson <matt@rigel.build> b49d3d97 fix(solid-virtual): publish without provenance to match the fork's upstream-pointed manifest (RIG-2187)
Round-2 review HIGH: the previous review-fix added `id-token: write` to
let `pnpm publish` sign a provenance attestation, but the package's
`repository.url` points at the upstream `TanStack/virtual` repo (frozen
in DL-015 as "honest for a fork"), while the workflow publishes from
`RigelBuild/virtual`. npm provenance requires `repository.url` to match
the publishing repo (OIDC-derived) or the registry rejects the upload
(422/EPROVENANCE) — so the first `v*` tag would fail at publish.
The design-consistent resolution is to publish WITHOUT provenance,
exactly like the `@rigelbuild/solid-markdown` precedent (no provenance,
no id-token, `repository.url` left as-is), keeping DL-015's frozen
decision to leave `repository.url` pointing upstream:
- Force provenance off at publish time via `pnpm_config_provenance:
"false"` on the Publish step. This is the only surface pnpm 11 reads
provenance from: `isNpmrcReadableKey` (pnpm11 config/reader
localConfig.ts) admits only auth/network keys, so a `provenance` line
in any `.npmrc` (including the repo-root `provenance=true`) is silently
ignored — the env var (`pnpm_config_*`, lowercase; pnpm 11 dropped
`npm_config_*`) makes OFF explicit and version-proof rather than
relying on that default. No `.npmrc` edit (which pnpm ignores) and no
CLI flag (pnpm exposes none) can do this.
- Drop the now-dead `id-token: write`, reverting the job to
`permissions: { contents: read }` — no OIDC token is minted, matching
the solid-markdown precedent and avoiding an orphaned permission
widening on a token-handling workflow.
Spec-impact: none
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build> 8cd85146 fix(solid-virtual): make the publish workflow actually authenticate + publish (RIG-2187)
Fold review findings on the fork-owned publish workflow — three runtime-only failures a local build can't surface, all in the publish/auth plumbing:
- **HIGH — provenance needs `id-token: write`.** The fork root `.npmrc` sets `provenance=true`, so `pnpm publish` generates an npm provenance attestation signed via GitHub OIDC, which requires the job to hold `id-token: write`. The job had only `contents: read`, so the first `v*` tag would fail at the publish step. Added job-level `permissions: { contents: read, id-token: write }`, mirroring upstream `release.yml`. The NPM_TOKEN still authenticates the upload; provenance is the attestation, not the auth (this is not trusted publishing).
- **MEDIUM — first scoped publish needs public access.** `@rigelbuild/solid-virtual` is a new scoped package; npm defaults scoped packages to `restricted`, so the first publish would 402 (or publish privately, breaking the compass consumer contract). Added `"publishConfig": { "access": "public" }` to `packages/solid-virtual/package.json`, matching the proven `@rigelbuild/solid-markdown` precedent.
- **MEDIUM — pnpm auth was wired to inert env vars.** `NPM_CONFIG_TOKEN` maps to the legacy global `token` config registry.npmjs.org no longer accepts, and `NODE_AUTH_TOKEN` is a setup-node convention pnpm doesn't read natively — so the publish would 401/ENEEDAUTH. Replaced both with the per-registry URL-scoped env var `pnpm_config_//registry.npmjs.org/:_authToken`, which pnpm (>=11.6) honors natively: file-free, and un-redirectable since the registry is baked into the key.
Spec-impact: none
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build> 1855335b feat(solid-virtual): publish as @rigelbuild/solid-virtual with a fork-owned workflow (RIG-2187)
Publish a Solid-2-compatible `@tanstack/solid-virtual` fork to npm as `@rigelbuild/solid-virtual`, so `compass` can drop its unresolvable `github:` pin (`github:RigelBuild/virtual#solid-2-support` resolves the monorepo root — no package export) and consume a real published package on the Solid-1→2 migration (RIG-2187).
Frozen design record: `docs/designs/platform/rigelbuild-solid-virtual-publish.md` (orion, DL-015).
## What this branch contains
Two commits, kept separate so the Solid-2 work stays upstreamable to `TanStack/virtual`:
- **`feat: Solid 2 support`** — the Solid-2 API port (`packages/solid-virtual/{src,tests,package.json}` + lockfile), unchanged from the `solid-2-support` branch. Kept as its own commit so it stays a clean, contributable diff for the eventual upstream PR (branch from upstream `main` + cherry-pick this commit).
- **this commit (publish-only)** — renames the package and wires the fork-owned publish:
- `packages/solid-virtual/package.json`: `name` `@tanstack/solid-virtual` → `@rigelbuild/solid-virtual`, `version` → `3.0.0-rc.0`. The `@tanstack/virtual-core` dep stays `workspace:*` — `pnpm publish` rewrites the `workspace:` protocol to the resolved range (`3.17.8`) at pack time, so no committed dep edit and no republish of `virtual-core` (it is unchanged from upstream). `repository`/`funding` metadata left as upstream (honest for a fork; keeps this commit minimal).
- `.github/workflows/publish-rigelbuild.yml`: a fork-owned publish gated `if: github.repository_owner == 'RigelBuild'`, firing on a `v*` tag or manual dispatch. Runs the monorepo `test:ci` (nx `run-many`, not `affected` — a tag push has no affected base, so `affected` would run nothing and could ship an unbuilt dist; `run-many` builds every package in dependency order), then a direct `pnpm publish --filter @rigelbuild/solid-virtual --tag <disttag> --no-git-checks`. The dist-tag is computed from the version (prerelease → `next`, GA → `latest`), mirroring the solid-markdown fork's `publish.yml`. Authenticated by the `NPM_TOKEN` Actions secret provisioned via orion Pulumi (separate PR).
Upstream `release.yml` (gated `if: github.repository_owner == 'TanStack'`) is left untouched. `changeset publish` is deliberately not used: it ignores `config.ignore`, rejects ignoring `virtual-core` while a non-ignored package depends on it, and mis-tags a prerelease as `latest` — the direct filtered publish scopes the one renamed package cleanly while still reusing the pnpm monorepo build/test infra (frozen record D2).
The publish itself (tag + workflow run + npm verify) is a follow-up once this and the orion token PR merge.
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build> 3477a35a feat(solid-virtual): publish as @rigelbuild/solid-virtual with a fork-owned workflow (RIG-2187)
Publish a Solid-2-compatible `@tanstack/solid-virtual` fork to npm as `@rigelbuild/solid-virtual`, so `compass` can drop its unresolvable `github:` pin (`github:RigelBuild/virtual#solid-2-support` resolves the monorepo root — no package export) and consume a real published package on the Solid-1→2 migration (RIG-2187).
Frozen design record: `docs/designs/platform/rigelbuild-solid-virtual-publish.md` (orion, DL-015).
## What this branch contains
Two commits, kept separate so the Solid-2 work stays upstreamable to `TanStack/virtual`:
- **`feat: Solid 2 support`** — the Solid-2 API port (`packages/solid-virtual/{src,tests,package.json}` + lockfile), unchanged from the `solid-2-support` branch. Kept as its own commit so it stays a clean, contributable diff for the eventual upstream PR (branch from upstream `main` + cherry-pick this commit).
- **this commit (publish-only)** — renames the package and wires the fork-owned publish:
- `packages/solid-virtual/package.json`: `name` `@tanstack/solid-virtual` → `@rigelbuild/solid-virtual`, `version` → `3.0.0-rc.0`. The `@tanstack/virtual-core` dep stays `workspace:*` — `pnpm publish` rewrites the `workspace:` protocol to the resolved range (`3.17.8`) at pack time, so no committed dep edit and no republish of `virtual-core` (it is unchanged from upstream). `repository`/`funding` metadata left as upstream (honest for a fork; keeps this commit minimal).
- `.github/workflows/publish-rigelbuild.yml`: a fork-owned publish gated `if: github.repository_owner == 'RigelBuild'`, firing on a `v*` tag or manual dispatch. Runs the monorepo `test:ci` (nx `run-many`, not `affected` — a tag push has no affected base, so `affected` would run nothing and could ship an unbuilt dist; `run-many` builds every package in dependency order), then a direct `pnpm publish --filter @rigelbuild/solid-virtual --tag <disttag> --no-git-checks`. The dist-tag is computed from the version (prerelease → `next`, GA → `latest`), mirroring the solid-markdown fork's `publish.yml`. Authenticated by the `NPM_TOKEN` Actions secret provisioned via orion Pulumi (separate PR).
Upstream `release.yml` (gated `if: github.repository_owner == 'TanStack'`) is left untouched. `changeset publish` is deliberately not used: it ignores `config.ignore`, rejects ignoring `virtual-core` while a non-ignored package depends on it, and mis-tags a prerelease as `latest` — the direct filtered publish scopes the one renamed package cleanly while still reusing the pnpm monorepo build/test infra (frozen record D2).
The publish itself (tag + workflow run + npm verify) is a follow-up once this and the orion token PR merge.
Refs RIG-2187
Co-authored-by: Matt Wilkinson <matt@rigel.build>