Ports
Mirrors
packages/hub/src/port/in thenoy-dbrepo. The one-way law it enforces is an invariant of the nested-cores frame; the family-level view is Families.
A port is a named import subpath of @noy-db/hub — today exactly one, @noy-db/hub/to —
that a satellite family binds instead of reaching into hub internals. A family is one of
the preposition-named groups of external packages (to-* storage backends, on-* unlock
methods, …; see Families). A port's export surface is
golden-frozen: a checked-in JSON snapshot that a test compares against the real exports, so
the contract can only change deliberately — never by accident.
Only /to is still a family port. The model once gave seven more families a subpath of
their own (/on, /at, /as, /by, /in, /with, /ui). A consumer census found all seven
had zero importers — against 252 for the root @noy-db/hub barrel, 29 for /team and 9 for
/to — so they were pruned in noy-db#866 after
0.4.0-pre.5, taking the hub from 41 published subpaths to 34. Stores keep /to because they do
bind a narrow ciphertext contract, one check:architecture enforces; every other family depends
on the root @noy-db/hub package instead.
// A to-* store binds the /to port — never a hub-internal path:
import type { NoydbStore, EncryptedEnvelope } from '@noy-db/hub/to'
The port table
Physically, packages/hub/src/port/ holds six sibling folders. Five are published
family ports, each frozen by a golden and backed by a conformance kit; with/ is internal.
| Subpath | Physical home | Bound by | Frozen by (golden) | Conformance kit |
|---|---|---|---|---|
/to | port/to/ | to-* stores | to-surface.golden.json | @noy-db/ports/to |
/at | port/at/ | at-* sealing-key providers | at-surface.golden.json | @noy-db/ports/at |
/by | port/by/ | by-* session-share transports | by-surface.golden.json | @noy-db/ports/by |
/on | port/on/ | on-* unlock primitives | on-surface.golden.json | @noy-db/ports/on |
/as | port/as/ | as-* export/import formats | as-surface.golden.json | @noy-db/ports/as |
| (unpublished) | port/with/ | the kernel spine's hook seam into the with-* services | — | — |
These four came back, and why that is not a reversal
An earlier revision of this page recorded the 0.4 prune: /as, /at, /in, /on and /ui
were deleted outright because no family bound them, and /by was demoted to internal for
the same reason. That was correct — a subpath with zero importers is a promise nobody is
keeping.
Four of them returned in the 0.7 pre line, and the difference is the bar they had to clear: a contract, a published conformance kit, and real binders. Every one of those kits found a defect in a binding it was written against, which is the argument for writing the kit before shipping the seam rather than after.
/in and /ui did not return, and for different reasons:
/inwas never re-proposed;in-*framework bindings consume the root barrel./uiwill not exist. A UI is a driving adapter — it calls hub, and hub never invokes a UI — so a locator or factory would have no caller.ui-*binds/introspection, which is golden-frozen like a port. Seedocs/adr/0005-no-ui-port.mdin thenoy-dbrepo.
The rule the sequence teaches: the seam follows the port, never precedes it. Extract the contract from two working consumers, publish a kit, then ship the subpath.
Two more ports are physical layer ports rather than port/ siblings — /cargo
(with-cargo/, klum-db lobby) and /pod (with-pod/, klum-db + backup consumers), frozen
the same way (cargo-surface.golden.json, pod-surface.golden.json) — see
Service layers for those two folders.
Three contracts that aren't family ports are golden-frozen by the same mechanism:
- the root barrel (
src/index.ts, the flat app-developer API) —root-barrel-surface.golden.json, 472 values / 427 types; - the enclave barrel (
capsule/enclave-aes/index.ts, the fork-swap contract a sister project replaces wholesale; the enclave is the hub's self-contained crypto interior, see Enclave) —enclave-surface.golden.json; - the kernel API manifest (the
Noydb/Vault/Collectionpublic prototype surface) —kernel-api.golden.json: Noydb 53 / Vault 83 / Collection 86 methods.
Imports point inward only
family → port → service layer → kernel spine → enclave.
This is the nested-cores one-way law: at every seam the periphery binds the core's frozen contract and the core never imports outward — with exactly one deliberate arrow-flip at the innermost seam. The kernel spine consumes the enclave's frozen barrel (the last hop above), because the crypto is the innermost core, protected from everything outside it — including the rest of the kernel.
- The kernel spine — everything under
packages/hub/src/kernel/outside the enclave: the flat orchestration files (noydb.ts,vault.ts,collection.ts,types.ts,errors.ts, …) plus thequery/,cache/, andutil/sub-folders (see Kernel for the full list) — is restricted: it may importport/with/(the hook seam) andcapsule/enclave-aes/(only via its barrel), but never another port folder and never awith-*service directly (a dynamicimport()is the sanctioned escape hatch). - Ports are views, not new code paths. A port re-exports a contract whose implementation
lives in the kernel or a service — importing the port is the opt-in, so this costs nothing
in tree-shaking. Port folders may not import each other;
port/with/is the one exception, always an allowed target. - Enforced mechanically by two
check:architecturechecks:port-layering(the spine/port import-direction rules above) andenclave-barrel-only(nothing outsidecapsule/enclave-aes/**reaches past its barrel).
Removed and deprecated aliases
Three old subpaths were removed in 0.3.0-pre.11 — import the canonical seams instead:
/adapter→/to(the store contract)./describe→/ui(thedescribe()contract) — but/uihas since been pruned in turn, so the current home is the root@noy-db/hubbarrel, which is what@noy-db/uibinds./kernel→/cargo, which carries the same surface plus the orchestration delta.
One deprecated alias remains, kept working out of src/legacy/ (@deprecated JSDoc naming the
replacement, removed only on a coordinated version bump once klum-db migrates off it):
/bundle(legacy/bundle.ts) → split in two: the.noydbartifact format lives at/pod, the partition-transfer ops at/cargo.
There is no /store subpath: store plumbing (routing, middleware, lazy loading) lives in
with-store/ and is exported only through the root barrel.
Next
Service layers → — the 10 with-* folders each port's
/with hook seam gates into.