Internal seams — not extension points¶
These are Protocols, and they are not for you.
They exist because the kernel was decomposed into collaborators (instance builder, query engine, write pipeline, …) and each collaborator's back-reference to the kernel was published as a narrow, typed slice instead of passing the whole kernel around. That keeps the decomposition honest and testable — a collaborator can only reach what its slice names.
They are listed here for one reason: invisible is worse than "this is not for you". If you go looking for the extension point and find twenty-two Protocols nobody explains, you cannot tell the seams from the scaffolding. Now you can. Implementing one of these means substituting a piece of the kernel for itself, which is a fork, not an extension.
Generated from the source
Names, signatures and docstrings are parsed out of packages/sdk-py/dna
by scripts/gen_ports_docs.py. The prose around each contract is
hand-written in scripts/ports_prose.py, and the generator fails
if a port has none — so a new port cannot ship undocumented.
BundleIOHost¶
dna.kernel.collaborator_ports.BundleIOHost · @runtime_checkable · internal seam
Composes KindLookup, DocStore.
Bundle-entry and instance (de)serialization I/O.
From the source
bundle_io — bundle-entry + instance (de)serialization I/O.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
CatalogCacheHost¶
dna.kernel.collaborator_ports.CatalogCacheHost · @runtime_checkable · internal seam
Composes RecordQuery.
The catalog-tier scope set. The cache dict is owned by the kernel and shared by identity.
From the source
CatalogCache — the Catalog-tier scope set (Phase 3b, i-112). The cache
dict (_catalog_cache) is OWNED by the kernel (shared by identity across
with_tenant copies — spec Risk #3, pinned by
test_kernel_catalog_tenant_characterization); the collaborator only
reads/writes it through the host, keeping per-tenant KEYS the isolation
boundary. Scans Genomes via query + reads the tenant lockfile via
source_metadata.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
list_scopes_async |
async def list_scopes_async(self) -> list[str] |
|
source_metadata |
def source_metadata(self) -> dict |
CompositionResolverHost¶
dna.kernel.collaborator_ports.CompositionResolverHost · @runtime_checkable · internal seam
Composes KindLookup, DocStore, InheritanceCtx, WriteOps, LayerObserverCtx.
Resolves and persists compositions, and registers the reverse-dependency observers cross-scope invalidation walks.
From the source
composition_resolver — resolves + persists compositions, and registers reverse-dep observers for cross-scope invalidation.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
DocStore¶
dna.kernel.collaborator_ports.DocStore · @runtime_checkable · internal seam
The source port, reader/writer lists, the tenant binding, the sync↔async bridge and the granular-instance cache, as one slice.
From the source
Doc reading surface: the source port, reader/writer lists, the tenant binding, the sync↔async bridge loop, the doc parser, and the granular-doc LRU. Consumed by instance_builder, query_engine, composition_resolver, bundle_io, source_sync.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
_parse_doc |
def _parse_doc(self, raw: dict[str, Any], origin: str='local') -> 'Instance' |
|
_granular_doc_cached |
async def _granular_doc_cached(self, key: tuple[str, str, str, str]) -> dict[str, Any] | None |
InheritanceCtx¶
dna.kernel.collaborator_ports.InheritanceCtx · @runtime_checkable · internal seam
Scope-inheritance constants, the catalog scope set, the base-instance cache and the resolution-chain computation.
From the source
Scope-inheritance constants + catalog scope set + base-instance cache + resolution-chain compute. Consumed by instance_builder, query_engine, composition_resolver, layer_policy.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
_base_instance_cached |
def _base_instance_cached(self, scope: str) -> Any |
|
_base_instance_cached_async |
async def _base_instance_cached_async(self, scope: str) -> Any |
|
_catalog_scopes |
async def _catalog_scopes(self, tenant: str | None, *, exclude: set[str] | None=None) -> list[tuple[str, str | None]] |
|
_compute_resolution_chain |
async def _compute_resolution_chain(self, scope: str, tenant: str | None) -> list |
InstanceBuildCtx¶
dna.kernel.collaborator_ports.InstanceBuildCtx · @runtime_checkable · internal seam
The cache port, composition profiles, the resolver map and the two lazy-registration hooks used while assembling a manifest instance.
From the source
MI-assembly internals beyond the shared roles: the CachePort, the CompositionProfile list, the ResolverPort map, and the two lazy-registration hooks. Consumed ONLY by instance_builder (the widest collaborator — building a ManifestInstance genuinely crosses much of the kernel).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
_register_kind_definitions |
def _register_kind_definitions(self, all_raws: list[dict[str, Any]], *, scope: str | None=..., inherited_from: str | None=...) -> bool |
|
_register_custom_kinds |
def _register_custom_kinds(self, manifest: dict[str, Any], *, scope: str | None=...) -> None |
InstanceBuilderHost¶
dna.kernel.collaborator_ports.InstanceBuilderHost · @runtime_checkable · internal seam
Composes KindLookup, DocStore, InheritanceCtx, InstanceBuildCtx.
The widest back-reference in the kernel — sixteen members across Kind lookup, instance reading, inheritance and assembly, because building a manifest instance crosses the whole kernel.
From the source
instance_builder — 16 members across kind-lookup, doc-read, inheritance, and MI-assembly internals. The widest back-ref (MI build crosses the kernel).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
InvalidationHost¶
dna.kernel.collaborator_ports.InvalidationHost · @runtime_checkable · internal seam
The cache-coherence state the invalidation controller fans out over. All of it stays on the kernel so with_tenant's shallow-copy semantics survive.
From the source
Cache-coherence state the InvalidationController fans out over. All state
stays on the kernel (preserves with_tenant shallow-copy semantics); the
controller is stateless and reaches it through this narrow host — NOT the
whole kernel. Consumed ONLY by invalidation.
Required (always present): the five below. The controller ALSO touches three
LAZY members — _write_observers, _holders, _layer_observers —
each read defensively via getattr(k, name, default) (they are created on
first on_write / register_holder / resolve_instance). Because the
getattr-with-default tolerates their absence, they are intentionally NOT
required Protocol attributes.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
kinds_with_trait |
def kinds_with_trait(self, trait: str) -> 'frozenset[str]' |
Which Kinds declare trait. The controller asks for record.is-evidence to decide what NOT to invalidate — it used to spell that kind == "Evidence" (i-107). |
KindLookup¶
dna.kernel.collaborator_ports.KindLookup · @runtime_checkable · internal seam
Registered-Kind identity, plane, storage descriptor, alias and port lookup.
From the source
Registered-Kind identity, plane, storage descriptor, alias, port lookup,
and the lazy generic reader/writer wiring. Consumed by instance_builder,
composition_resolver, bundle_io, source_sync, layer_policy (_alias_for
plus kind_port_for, to read the Kind's OVERLAYABLE_FIELDS).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
kinds_for_scope |
def kinds_for_scope(self, scope: str | None) -> 'dict[tuple[str, str], KindPort]' |
|
kind_plane |
def kind_plane(self, kind: str, *, api_version: str | None=None, scope: str | None=...) -> str |
|
kind_port_for |
def kind_port_for(self, kind: str, *, api_version: str | None=None, scope: str | None=...) -> 'KindPort | None' |
|
storage_for_kind |
def storage_for_kind(self, kind_name: str, *, api_version: str | None=..., scope: str | None=...) -> 'StorageDescriptor | None' |
|
_alias_for |
def _alias_for(self, kind: str) -> str |
|
_ensure_generic_readers_writers |
def _ensure_generic_readers_writers(self) -> None |
LayerObserverCtx¶
dna.kernel.collaborator_ports.LayerObserverCtx · @runtime_checkable · internal seam
The reverse-dependency graph used for cross-scope surgical invalidation. Attribute-shaped, so it declares no methods.
From the source
The Phase-17 reverse-dependency observer graph used for cross-scope surgical invalidation. Populated by composition_resolver.resolve_instance; drained by InvalidationController.invalidate_internal.
_layer_observers: dict is a LAZY member (created on first
resolve_instance, read via getattr(k, "_layer_observers", None)), so
it is NOT a required Protocol attribute — a fresh kernel lacks it. Only the
LRU bound below is always present (class constant).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No methods: this Protocol is satisfied by attributes, not calls (see the source docstring above).
LayerPolicyHost¶
dna.kernel.collaborator_ports.LayerPolicyHost · @runtime_checkable · internal seam
Composes KindLookup, InheritanceCtx.
LOCKED / RESTRICTED / OPEN enforcement over the base manifest instance.
From the source
layer_policy — LOCKED/RESTRICTED/OPEN enforcement over the base MI.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
NamespaceGateHost¶
dna.kernel.collaborator_ports.NamespaceGateHost · @runtime_checkable · internal seam
The write-time namespace-ownership check: three members, one per question the verdict has to answer.
From the source
NamespaceOwnershipGate — the write-time namespace-ownership check (i-080
item 1). Three members, one per question the verdict needs answered: which
namespaces are RESERVED (derived from the live registry, never a list), who
CLAIMS the target namespace (the _lib KindNamespace registry), and who
the scope declares as its owner when the write carries no tenant
(Genome.spec.owner_tenant on the base instance — the same read the
LayerPolicy check already makes).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
kind_ports |
def kind_ports(self) -> 'list[KindPort]' |
|
kind_namespaces |
async def kind_namespaces(self) -> list[dict[str, Any]] |
|
_base_instance_cached_async |
async def _base_instance_cached_async(self, scope: str) -> Any |
QueryEngineHost¶
dna.kernel.collaborator_ports.QueryEngineHost · @runtime_checkable · internal seam
Composes DocStore, InheritanceCtx.
Read push-down: the instance-reading surface plus the inheritance fallback.
From the source
query_engine — read push-down: doc-read surface + inheritance fallback.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
RecordQuery¶
dna.kernel.collaborator_ports.RecordQuery · @runtime_checkable · internal seam
The record-query push-down shared by the read-only satellites (search, catalog, registry, composition summary). Public in the sense that it is a cohesive slice — not in the sense that you implement it.
From the source
The public record-query push-down. A cohesive slice consumed by the
read-only Fase-5 satellites (search / catalog / registry / composition
summary) that scan records through the kernel's query facade rather
than re-implementing source push-down. query is an async generator.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
query |
def query(self, scope: str, kind: str, **kw: Any) -> Any |
RegistryAccessorHost¶
dna.kernel.collaborator_ports.RegistryAccessorHost · @runtime_checkable · internal seam
Composes RecordQuery.
The registry accessor's three global reads — model profile, voice policy, embedding profile.
From the source
RegistryAccessor — the three GLOBAL _lib-direct registry reads
(model_profile / voice_policy / embedding_profile). Needs only
the query push-down; the _lib scope constants live on the accessor.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
RegistryHost¶
dna.kernel.collaborator_ports.RegistryHost · @runtime_checkable · internal seam
The narrow slice the Kind registry's registration funnel needs. The registry dict itself is owned by the kernel.
From the source
The narrow slice of the Kernel the KindRegistry's registration funnel
needs (s-kernel-decomp-f3-kindregistry). The _kinds dict itself is
OWNED by the registry — not reached through the host; this host is only the
fan-out surface registration touches on the wider kernel: the hook registry
(kinddef_conflict / parse_error events), the _readers list (the
2-phase-load rescan return gate), the generic reader/writer wiring, and the
_generics_resolved flag it flips on every successful register. Every
member is a genuine registration dependency; widening it is a code-review
event (spec §3.1 / anti-goal §5.3).
_loading_ext_owner (the per-load() alias-owner context) is a LAZY
member — set only inside kernel.load() and read via
getattr(host, "_loading_ext_owner", None) — so it is intentionally NOT a
required Protocol attribute (a kernel outside a load() call lacks it).
_writers joined this contract with the UNregistration path (i-080 item
3): a Kind that is dropped must take its auto-synthesized
GenericBundleWriter with it, or the next registration of the same Kind
name is skipped by the "already has a writer" check in
_ensure_generic_readers_writers and the stale writer keeps claiming it.
It is the exact mirror of the _readers membership already here.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
_ensure_generic_readers_writers |
def _ensure_generic_readers_writers(self) -> None |
SearchEngineHost¶
dna.kernel.collaborator_ports.SearchEngineHost · @runtime_checkable · internal seam
Composes RecordQuery.
Record search plus the lexical fallback, the tenant binding, and the registered provider.
From the source
SearchEngine — record search + lexical fallback. Reads the tenant
binding (for the effective-tenant auto-stamp) and the registered provider +
its failure-warning damper. The provider/damper STATE stays on the kernel
(shared/per-copy exactly as before); the engine reaches it through the host.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
SourceFacadeHost¶
dna.kernel.collaborator_ports.SourceFacadeHost · @runtime_checkable · internal seam
Read-only source-adapter introspection — source type, scope list, metadata. Attribute-shaped, so it declares no methods.
From the source
SourceFacade — read-only source-adapter introspection (source_type /
list_scopes_async / source_metadata). Needs only the source port.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No methods: this Protocol is satisfied by attributes, not calls (see the source docstring above).
SourceSyncHost¶
dna.kernel.collaborator_ports.SourceSyncHost · @runtime_checkable · internal seam
Composes KindLookup, DocStore.
Digest, diff and push over the source.
From the source
source_sync — digest/diff/push over the source (s-sync-s1..s5).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
No members of its own — it is the union of the Protocols above.
WriteHost¶
dna.kernel.collaborator_ports.WriteHost · typing-only (not @runtime_checkable) · internal seam
Kind identity, the writable-source guard, layer policy, hooks, and the invalidation/observer fan-out.
From the source
The narrow slice of the Kernel the WritePipeline needs — Kind identity, the writable source guard, layer-policy, hooks, and the invalidation / observer / post-hook fan-out. Every member here is a genuine write-path dependency; widening this Protocol is a code-review event (spec §3.1).
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
_kind_scope |
def _kind_scope(self, kind: str, *, api_version: str | None=..., scope: str | None=...) -> 'TenantScope | None' |
|
kind_port_for |
def kind_port_for(self, kind: str, *, api_version: str | None=..., scope: str | None=...) -> 'KindPort | None' |
|
_require_writable_source |
def _require_writable_source(self) -> 'WritableSourcePort' |
|
_check_layer_policy_async |
async def _check_layer_policy_async(self, scope: str, kind: str, name: str, raw: dict, layer: tuple[str, str]) -> None |
|
_check_namespace_ownership_async |
async def _check_namespace_ownership_async(self, scope: str, kind: str, name: str, raw: dict, *, tenant: str | None) -> None |
|
_invalidate_granular_cache |
def _invalidate_granular_cache(self, scope: str, *, kind: str | None=..., name: str | None=...) -> None |
|
_invalidate_catalog_cache |
def _invalidate_catalog_cache(self, tenant: str | None=...) -> None |
|
invalidate |
def invalidate(self, *, scope: str, tenant: str=..., kind: str, name: str, op: str) -> None |
|
_fire_write_observers |
def _fire_write_observers(self, scope: str, kind: str, name: str, op: str, tenant: str=...) -> None |
WriteOps¶
dna.kernel.collaborator_ports.WriteOps · @runtime_checkable · internal seam
The two write entry points a collaborator may reach.
From the source
The write entry points. Consumed by composition_resolver (writes the
materialized composition back). Future write-side collaborators (Phase 2+
WritePipeline) compose this role rather than re-holding the whole kernel.
Not an extension point. A back-reference from one kernel collaborator to the narrow slice of the kernel it is allowed to reach. Published as a Protocol so the slice is typed and enforceable, not so anybody outside the kernel implements it.
The contract
| Member | Signature | What it must do |
|---|---|---|
write_instance |
async def write_instance(self, scope: str, kind: str, name: str, raw: dict, author: str | None=None, skip_hooks: bool=False, *, tenant: str | None=None, layer: tuple[str, str] | None=None, invalidate_mode: str='scope', write_class: str='substantive') -> str | None |
|
write_bundle_entry_async |
async def write_bundle_entry_async(self, scope: str, kind: str, name: str, entry: str, content: bytes | str, *, tenant: str | None=None) -> None |