Skip to content

Track: Packaging & distribution — the package unit, workspaces, the dependency surface, and the publish backbone #843

Description

@accuser

The theme

Bynk has no way to share code across a package boundary — every project is an
island: a bynk.toml, a src/ tree, and whatever it authors itself. This track
gives Bynk a package unit and the machinery to publish and consume it: a
four-tier identity (organisation/workspace/package/unit) with flat, dotted,
cross-package names; workspaces; a dependency + resolution surface with a
bynk.lock; and a distribution backbone — a dedicated Bynk registry for the
Bynk layer, npm retained for the adapter layer, git/URL as the bootstrap + private
hatch.

When the track retires, a Bynk package can be published under an owned namespace
and mixed into a consumer's build source-level, no separate ABI — taking Bynk
from "one team, one repo" to an ecosystem, at the moment the language is
feature-complete and approaching the ~1.0 runtime-ABI freeze.

  • Realises: design/bynk-design-notes.md §3 (bounded context as "a rough
    analogue of a module/package"), §19 (project structure; first-party caps
    "depending on packaging"), §21 (commons vendored / source-level mixin); and the
    deferrals ADR 0086 (first-party publish, gated on the ABI freeze) and ADR 0012
    (ambient bynk surface "splittable later") parked.
  • Track doc (already a committed Draft): design/tracks/packaging.md

Why a track (the ADR 0076 trigger)

  • Multi-increment — the flat-name cutover, the manifest/workspace surface,
    the resolver, npm-dependency propagation, the registry, adapter trust,
    behavioural units, and the first-party lift are eight ordered slices (§9); a
    single delete-on-merge proposal cannot carry the connective identity/resolver/
    backbone design across them.
  • Surface not yet settled (at draft time) — the package payload, the
    four-tier identity model, the version-selection algorithm, and the distribution
    backbone were all genuinely open; they are settled in the doc (§8) and land as
    front-loaded ADRs.
  • Security/safety boundary — the track distributes code the consumer
    compiles and ships; the adapters' transitive npm dependencies are a
    supply-chain surface, and this track finally closes the still-Open ADR 0020
    (adapter dependency trust).

Open design questions

Settled in the doc (§8); listed here as the settling agenda, with disposition:

  • Distribution backbone (Q1) — DECIDED: dedicated Bynk registry for the Bynk
    layer, npm retained for adapters, git/URL bootstrap + private hatch (§6).
  • Shareable-unit set (Q2) — DECIDED: commons + adapters + behavioural library
    units; the context-as-deployment-unit wrapper excluded.
  • Identity & namespacing (Q3) — DECIDED: organisation.package.unit; flat unit
    names unique within a package; reserved org bynk; flat source layout.
  • Version selection (Q6) — DECIDED: single-version resolution; version_conflict
    the honest failure.
  • First-party publish timing (Q5) — DECIDED: runtime/bindings vendored forever;
    ambient/stdlib publish post-ABI-freeze (~1.0).
  • Platform dimension & reserved-org home (Q10/Q11) — DECIDED: bynk.cloudflare
    is one cohesive multi-unit package under reserved org bynk.
  • Behavioural-unit declaration site (Q9) — scoped out of settle: distribution is
    in; the language-surface change is slice 6's own ADR, gated on the
    agent-capability-encapsulation track.
  • Mixin semantics (Q4), lockfile schema (Q7) — deferred to slice 2 by design
    (spec-write / serialised format, not hard-to-reverse calls).

Candidate slice decomposition

  • Slice 0 — flat-name cutover (identity-model ADR; codemod; breaking, pre-1.0).
  • Slice 1 — manifest & workspace surface (parse/validate the manifest tables +
    a lock skeleton; no resolution yet).
  • Slice 2 — resolver + cross-package source loading (git/URL first;
    single-version resolution; Q4 spec'd here).
  • Slice 3 — npm-dependency propagation (fold transitive adapter npm requires;
    integrity in the lock, Q7).
  • Slice 4 — dedicated registry (client + API contract; the service likely its
    own track).
  • Slice 5 — adapter package trust (closes ADR 0020; approve/diff npm deps).
  • Slice 6 — behavioural library units (declaration-site change, Q9; gated on the
    agent-capability-encapsulation track).
  • Slice 7 — first-party bynk.* workspace (deferred ~1.0; ambient + stdlib +
    bynk.cloudflare lift; gated on the ABI freeze).

Slice status

  • Slice 0 — flat-name cutover
  • Slice 1 — manifest & workspace surface
  • Slice 2 — resolver + cross-package source loading
  • Slice 3 — npm-dependency propagation
  • Slice 4 — dedicated registry (client + API contract)
  • Slice 5 — adapter package trust
  • Slice 6 — behavioural library units (gated)
  • Slice 7 — first-party bynk.* workspace (deferred ~1.0)

Front-loaded ADR candidates

  • The shareable-unit set (what a package may contain).
  • The identity model — flat names + organisation/workspace/package/unit.
  • Workspaces (members, the root lock, inheritance).
  • The distribution backbone (dedicated registry; npm for adapters; git/URL
    bootstrap/escape).
  • Single-version resolution + the lockfile.
  • Adapter package trust (supersedes ADR 0020).

(Numbers taken at merge, per ADR 0076 — not pre-allocated.)

Threat model

The track distributes code the consumer compiles and ships, so it is a
supply-chain surface:

  • The executable risk is the adapters' transitive npm deps, which run install
    scripts and ship JS into the Worker. Bynk source itself has no install
    scripts and no build step
    — resolving a Bynk package executes no
    dependency-authored code. Mitigation: close ADR 0020 (slice 5) — a consumer
    reviews/approves/diffs the npm deps a dependency's adapters would add, pinned in
    bynk.lock, before they enter the build.
  • Integrity & pinning: bynk.lock pins exact versions + content hashes; the
    dedicated registry adds authenticated, immutable, content-addressed publishes;
    hermetic builds verify the lock before compiling.
  • Namespace safety: organisation.package.unit makes cross-package collisions
    structural; reserved org bynk means no third party can impersonate the stdlib,
    ambient, or platform surface.
  • No widening of the type-boundary trust model: opaque/transparent export and
    sealed construction hold across a package boundary exactly as across a context
    boundary; a dependency cannot construct a consumer's sealed types nor expose its
    own beyond its declared exports.
  • Platform lock is part of a package's contract: a Cloudflare-locked
    behavioural unit's lock is surfaced at resolve time, not discovered at deploy.
  • No resolve-time code execution in the Bynk layer — the only executable risk
    is the npm sub-layer, fenced by the ADR 0020 closure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions