design: take the port from the sidecar binding #76

Merged
PerishFire merged 1 commit from land/design/sidecar-binding into main 2026-08-18 16:41:36 +00:00
Owner

Why

The manifest pinned port = 4290 and 4287, and vite/config.ts read
SIDECAR_PORT out of the environment and validated it by hand. Both existed
because the binding did not, and both are exactly what
perish.code/sidecar-closed-loop declared as its acceptance test.

What

  • sidecar.toml: both targets lease with port = 0. The trailing -- in each
    argument list is gone with the flag it used to guard.
  • packages/design/src/vite/config.ts: client.connect() from
    @perish/sidecar, then held.control.port(). The range check leaves with the
    parsing, because a caller of a binding does not restate the grant's own rules.
  • packages/design/src/vite/lib.ts: connect() is async, so the plugin's
    config hook awaits it once and every later hook reads the resolved value.
    Vite runs config before configResolved, buildStart, configureServer
    and generateBundle, so nothing observes the placeholder.
  • .npmrc: the @perish scope resolves from the Forgejo registry.

Tests

pnpm check, pnpm typecheck, pnpm test (28 design, 11 docs), pnpm build,
plumb doctor ., ectropy . — all green.

Verified against the published binding rather than a local build:

preview -> grants {broker: tcp://127.0.0.1:41761, port: "33259"}
           pid 2492265 (host), target 2492266
curl http://127.0.0.1:33259/health -> 200

port = 0 leased 33259, sidecar announced it, the binding read it, vite pinned
it, health_url resolved against it, and start --wait returned only after the
target answered. No process.env.SIDECAR_PORT remains anywhere.

Compatibility

Anyone who relied on the docs dev server answering on 4290, or preview on 4287,
now reads the port sidecar leased. sidecar status --format json reports it,
and the {port} template resolves it inside the manifest.

## Why The manifest pinned `port = 4290` and `4287`, and `vite/config.ts` read `SIDECAR_PORT` out of the environment and validated it by hand. Both existed because the binding did not, and both are exactly what `perish.code/sidecar-closed-loop` declared as its acceptance test. ## What - `sidecar.toml`: both targets lease with `port = 0`. The trailing `--` in each argument list is gone with the flag it used to guard. - `packages/design/src/vite/config.ts`: `client.connect()` from `@perish/sidecar`, then `held.control.port()`. The range check leaves with the parsing, because a caller of a binding does not restate the grant's own rules. - `packages/design/src/vite/lib.ts`: `connect()` is async, so the plugin's `config` hook awaits it once and every later hook reads the resolved value. Vite runs `config` before `configResolved`, `buildStart`, `configureServer` and `generateBundle`, so nothing observes the placeholder. - `.npmrc`: the `@perish` scope resolves from the Forgejo registry. ## Tests `pnpm check`, `pnpm typecheck`, `pnpm test` (28 design, 11 docs), `pnpm build`, `plumb doctor .`, `ectropy .` — all green. Verified against the published binding rather than a local build: ``` preview -> grants {broker: tcp://127.0.0.1:41761, port: "33259"} pid 2492265 (host), target 2492266 curl http://127.0.0.1:33259/health -> 200 ``` `port = 0` leased 33259, sidecar announced it, the binding read it, vite pinned it, `health_url` resolved against it, and `start --wait` returned only after the target answered. No `process.env.SIDECAR_PORT` remains anywhere. ## Compatibility Anyone who relied on the docs dev server answering on 4290, or preview on 4287, now reads the port sidecar leased. `sidecar status --format json` reports it, and the `{port}` template resolves it inside the manifest.
design: take the port from the sidecar binding
Some checks failed
guard / guard (pull_request) Failing after 53s
9786f6cee4
## Why

The manifest pinned `port = 4290` and `4287`, and `vite/config.ts` read
`SIDECAR_PORT` out of the environment and validated it by hand. Both existed
because the binding did not, and both are exactly what
`perish.code/sidecar-closed-loop` declared as its acceptance test.

## What

- `sidecar.toml`: both targets lease with `port = 0`. The trailing `--` in each
  argument list is gone with the flag it used to guard.
- `packages/design/src/vite/config.ts`: `client.connect()` from
  `@perish/sidecar`, then `held.control.port()`. The range check leaves with the
  parsing, because a caller of a binding does not restate the grant's own rules.
- `packages/design/src/vite/lib.ts`: `connect()` is async, so the plugin's
  `config` hook awaits it once and every later hook reads the resolved value.
  Vite runs `config` before `configResolved`, `buildStart`, `configureServer`
  and `generateBundle`, so nothing observes the placeholder.
- `.npmrc`: the `@perish` scope resolves from the Forgejo registry.

## Tests

`pnpm check`, `pnpm typecheck`, `pnpm test` (28 design, 11 docs), `pnpm build`,
`plumb doctor .`, `ectropy .` — all green.

Verified against the published binding rather than a local build:

```
preview -> grants {broker: tcp://127.0.0.1:41761, port: "33259"}
           pid 2492265 (host), target 2492266
curl http://127.0.0.1:33259/health -> 200
```

`port = 0` leased 33259, sidecar announced it, the binding read it, vite pinned
it, `health_url` resolved against it, and `start --wait` returned only after the
target answered. No `process.env.SIDECAR_PORT` remains anywhere.

## Compatibility

Anyone who relied on the docs dev server answering on 4290, or preview on 4287,
now reads the port sidecar leased. `sidecar status --format json` reports it,
and the `{port}` template resolves it inside the manifest.

Land-Source: design/sidecar-binding@3032c6fb0c
PerishFire force-pushed land/design/sidecar-binding from 9786f6cee4
Some checks failed
guard / guard (pull_request) Failing after 53s
to 4c98f85271
All checks were successful
guard / guard (pull_request) Successful in 1m45s
guard / guard (push) Successful in 1m48s
2026-08-18 16:37:48 +00:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
PerishFire/design!76
No description provided.