# ADR 0252: A bundle carries no build-machine path

> Source: https://github.com/max-listov/stitchkit/blob/master/docs/decisions/0252-a-bundle-carries-no-build-machine-path.md

---

# ADR 0252 — A bundle carries no build-machine path

**Invariants:** I7, I8, I13, I14. Amends ADR 0235 (decisions 1 and 3) and ADR 0233 (embedded inputs).

## Context

ADR 0235 made the default Darwin loader compute its addon path at run time,
`require(__dirname + '/native/darwin-<arch>.node')`, so a bundler would not follow it. It did not
follow it, but Bun inlines `__dirname` and `__filename` of a bundled CommonJS module as string
literals. Every bundle and compiled executable built from `stitchkit/files`, `stitchkit/server` or
`stitchkit/process` without the packaging plugin therefore carried the absolute path of the package
on the build machine: the builder's user name, directory layout and install hash went out with a
distributed artifact, and on another Mac the loader looked for the addon at that foreign path.
The failure surfaced only on macOS, and only at the first call that needed the addon.

Two further costs sat on the same path. Every chunk of the package was assumed to have import side
effects, so a bundle that took only the managed file boundary from `stitchkit/files` still carried
the lock, process identity and the Darwin loader, and had to decide about native packaging for an
addon it never loads. And the embedded form of `createNativePackaging` required `entryPath` and
`assetPath`, which change nothing in a compiled executable, so callers invented values to pass the
schema.

## Decision

1. **The default loader locates itself through `module.filename`.** It never reads `__dirname` or
   `__filename`. Run from the installed package, `module.filename` is the loader's absolute path and
   the addon is loaded beside it, exactly as before. Inside a bundle it is not an absolute path (Bun
   rewrites it to a relative name; a module wrapper that does not provide it leaves it undefined), so
   the loader requires nothing and
   throws `STITCHKIT_NATIVE_NOT_PACKAGED`, whose message names `createNativePackaging`. No path of the
   build machine becomes a literal of the artifact. This replaces decision 1 of ADR 0235.
2. **An unpackaged bundle is its own failure stage.** The Darwin backend reports `unavailable` with
   stage `packaging` and that native code, separate from `resolve` (an installed addon that is
   missing) and `load`. This replaces the "not found beside the original package files" wording of
   decision 3 of ADR 0235; the rest of that decision stands: the packaging plugin is the only way an
   addon enters an artifact, and an unavailable backend is never evidence that an owner died.
3. **The package declares `"sideEffects": false`.** No module of `stitchkit` acts on import, so a
   bundler may drop what a consumer does not use; a bundle of the managed file boundary carries no
   Darwin loader. A module that needs an import side effect is a defect of that module, not a reason
   to withdraw the declaration.
4. **Embedded packaging names no layout.** `delivery: 'embedded'` takes `platform`, one
   `architecture` and `delivery`; a path is refused by the type and by a strict schema rather than
   ignored. Its asset is `bytes`, `size` and `sha256`, without `outputPath`. Companion delivery keeps
   its inputs. This amends the embedded inputs of ADR 0233.

## Rejected alternatives

- **A separate `stitchkit/files/boundary` leaf** for consumers that need only the boundary. It adds
  a second import path for names `stitchkit/files` already exports, and leaves every other partial
  import (`stitchkit/server` without a lock, for one) with the same dead weight. The side-effect
  declaration fixes the cause for all of them.
- **Detect a bundle by comparing `__dirname` with something known.** Inside a bundle `__dirname` is
  a valid-looking absolute path; reading it is exactly what puts the path into the artifact.
- **A build-time warning when the loader enters an unpackaged bundle.** Only a plugin can see the
  build, and a build without the plugin is the case to detect; the named runtime refusal and the
  documented artifact check cover it without a second mechanism. (Amended by ADR 0254: the check is
  `inspectNativeArtifact`, which reads a loader marker; the error code alone is in every bundle with a
  lock and proves nothing.)
- **Keep `entryPath`/`assetPath` optional for embedded delivery and ignore them.** An accepted input
  that does nothing is the confusion being removed.

## Consequences

- An artifact built without the plugin by 0.105.0–0.106.1 must be rebuilt to drop the build path.
- An embedded build drops its two paths; the migration is in `docs/guide/upgrading.md` (0.107.0).
- `tests/portable-entrypoints-bundle.test.ts` proves on Linux that lock bundles (Bun and Node
  targets) and a compiled executable contain no absolute path of the package in latin1 or UTF-16LE,
  that a boundary-only bundle contains no Darwin loader, and, as a negative control, that a loader
  reading `__dirname` does put the path into a bundle. Loading the addon from an installed package
  and from a packaged artifact remains qualified by the Darwin lanes.
