RFC-0007: adapter workspace subcrates
Version: 0.1.2 | Status: normative | Phase: impl
1. Summary
[RFC-0007:C-SUMMARY] Summary (Informative)
This RFC specifies the extraction of built-in adapters from the main typub crate into separate workspace subcrates.
Scope:
- Defines the target workspace layout with adapter subcrates.
- Specifies the shared adapter types crate (
typub-adapters-core). - Specifies crate boundaries and dependency rules.
- Specifies feature gates for optional adapter inclusion.
Out of Scope:
- Third-party adapter crates (covered by RFC-0006).
- Runtime plugin loading.
- Migration path from current layout (covered by work items).
Rationale: The current monolithic layout has several drawbacks:
- All adapters share dependencies, even when only a subset is needed (e.g., Ghost requires JWT crates that others do not).
- Adding adapters requires modifying core files (
Adapterenum, registry factory array). - Compile times scale with total adapter count rather than enabled adapters.
- Testing adapters in isolation is difficult.
Extracting adapters into subcrates enables:
- Feature-gated inclusion for smaller binaries and faster compiles.
- Cleaner separation of concerns.
- First-party and third-party adapters follow the same patterns.
- Independent testing of each adapter.
References:
- RFC-0006 — adapter extension API (defines
AdapterRegistrar,Externalvariant) - ADR-0002 — shared types in
typub-core - ADR-0003 — extraction of
typub-htmlsubcrate
Since: v0.1.0
2. Specification
[RFC-0007:C-WORKSPACE-LAYOUT] Workspace Layout (Normative)
The workspace MUST include the following crates:
typub— main CLI binarytypub-core— capability types (existing)typub-html— HTML parsing/serialization (existing)typub-adapters-core— shared adapter abstractions (new)
Adapter crates MUST follow the naming convention typub-adapter-{platform_id}.
Adapter crates SHOULD be placed under crates/adapters/ to group related crates:
crates/
├── typub-core/
├── typub-html/
├── typub-adapters-core/
└── adapters/
├── typub-adapter-ghost/
├── typub-adapter-notion/
└── ...
The workspace Cargo.toml MUST list all adapter crates as members.
New first-party adapters MAY be added without modifying this RFC, provided they follow the naming convention and placement guidelines above.
Rationale:
Consistent naming enables tooling and documentation automation. The crates/adapters/ subdirectory groups related crates without polluting the top-level. Pattern-based rules avoid RFC churn when adding new adapters.
Since: v0.1.0
[RFC-0007:C-SHARED-TYPES] Shared Adapter Types Crate (Normative)
A new crate typub-adapters-core MUST be created to hold shared adapter abstractions.
This crate MUST export:
PlatformAdaptertrait (moved fromsrc/adapters/mod.rs)AdapterPayloadstructPublishContextstructRenderConfigstructOutputFormatenumAdapterCapabilitystruct (withCow<'static, str>fields per RFC-0006:C-REGISTRAR-API)AdapterRegistrarstruct andAdapterFactorytype alias per RFC-0006:C-REGISTRAR-API
This crate MUST re-export from dependencies:
- From
typub-core:AssetStrategy,MathRendering,MathDelimiters,DraftSupport,CapabilitySupport,CapabilityGapBehavior - From semantic IR crate (
typub-htmlat present): document IR surface required by adapters, includingDocument,Block, andInline(or equivalent top-level semantic IR types defined by current RFC baseline)
This crate MUST NOT depend on:
- Main
typubcrate (no circular dependency) - Any adapter implementation crate
Rationale: A shared types crate provides a stable interface that both the main crate and adapter crates depend on. This avoids circular dependencies and enables third-party adapters to compile against a minimal dependency set. Re-exporting semantic document IR types (instead of legacy HTML-structured node vectors) aligns adapter boundaries with semantic IR v2 and reduces duplicated migration logic.
Since: v0.1.0
[RFC-0007:C-ADAPTER-CRATE] Adapter Crate Structure (Normative)
Each adapter crate MUST:
-
Implement the
PlatformAdaptertrait fromtypub-adapters-core. -
Expose a public
register(registrar: &mut AdapterRegistrar)function that:- Calls
registrar.register_factory(platform_id, factory)for the adapter factory. - Calls
registrar.register_capability(platform_id, capability)for the adapter capability. - The
platform_idMUST match the crate’s platform identifier (e.g.,typub-adapter-ghost→"ghost").
- Calls
-
Have a
Cargo.tomlwith:name = "typub-adapter-{platform_id}"versionmatching the workspace version- Dependency on
typub-adapters-core(nottypub) - Adapter-specific dependencies (e.g.,
hmac,jwtfor Ghost)
-
Contain all adapter-specific logic:
- API client (if applicable)
- Semantic IR transformations
- Type definitions
Each adapter crate SHOULD include integration tests that can run independently of the main CLI.
Adding new first-party adapters: Create a new crate following the above structure, add it to workspace members, add a feature gate in main crate, and add the feature-gated register() call to CLI bootstrap.
Rationale:
Self-contained adapter crates enable independent testing, versioning, and optional inclusion. The register function provides a uniform entry point consistent with RFC-0006:C-CLI-BOOTSTRAP.
Since: v0.1.0
[RFC-0007:C-DEPENDENCY-RULES] Dependency Rules (Normative)
The following dependency rules MUST be enforced:
Allowed dependencies:
| Crate | May depend on |
|---|---|
typub-core | (none in workspace) |
typub-html | typub-core |
typub-adapters-core | typub-core, typub-html |
typub-adapter-* | typub-adapters-core |
typub (main) | all of the above |
Adapter crates SHOULD depend only on typub-adapters-core, which re-exports needed types from typub-core and typub-html. Direct dependencies on typub-core or typub-html MAY be added only when adapter-specific needs require types not re-exported by typub-adapters-core.
Forbidden dependencies:
| Crate | MUST NOT depend on |
|---|---|
typub-core | any other workspace crate |
typub-html | typub-adapters-core, typub-adapter-*, typub |
typub-adapters-core | typub-adapter-*, typub |
typub-adapter-* | typub, other typub-adapter-* crates |
Rationale:
Strict layering prevents circular dependencies and ensures adapter crates can compile without the full CLI. No adapter should depend on another adapter to maintain isolation. Preferring typub-adapters-core avoids redundant dependency declarations.
Since: v0.1.0
[RFC-0007:C-FEATURE-GATES] Feature Gates (Normative)
Adapter feature gates in the main typub crate are OPTIONAL.
Implementations MAY use Cargo features to control first-party adapter inclusion, but this RFC does not require a specific feature matrix (for example adapter-all / adapter-{platform}) for conformance.
If feature gates are used, the implementation MUST ensure:
- Disabled adapters are not registered at runtime.
- Enabled adapters preserve the same runtime semantics as non-feature-gated builds.
If feature gates are not used, the default runtime path MUST still support selective adapter activation via platform configuration (enabled = true/false) and adapter requires_config semantics.
A build with no optional adapter features enabled (when such features exist) SHOULD still compile and provide non-adapter CLI commands (--help, --version). Commands requiring unavailable adapters MUST fail with a clear diagnostic.
Rationale: The current implementation relies primarily on runtime registration/activation semantics. Making feature gates optional avoids constraining implementation to one packaging strategy while preserving behavior guarantees.
Since: v0.1.0
[RFC-0007:C-RFC-0006-COMPAT] RFC-0006 Compatibility (Normative)
This RFC MUST be compatible with RFC-0006 (adapter extension API).
Specifically:
- The
AdapterRegistrardefined in RFC-0006:C-REGISTRAR-API MUST be implemented intypub-adapters-core. - Each adapter crate’s
register()entrypoint (when provided) MUST use the sameAdapterRegistrarAPI surface as extension adapters. - Runtime adapter execution MUST be based on
PlatformAdaptertrait-object semantics, whether registry construction is registrar-based or factory-table-based. - First-party and extension adapter wiring MUST preserve stable platform-ID behavior and MUST NOT alter semantics for unrelated platform IDs.
Rationale: Compatibility is defined by shared adapter contracts and runtime behavior, not by a single mandatory bootstrap implementation shape.
Since: v0.1.0
Changelog
v0.1.2 (2026-02-22)
Make adapter feature-gate model optional
Added
- Relax C-FEATURE-GATES from mandatory adapter-all matrix to optional build strategy
- Update RFC-0006 compatibility clause to behavior-based compatibility
v0.1.1 (2026-02-21)
Adapter wording alignment
Added
- Replace remaining AST wording with semantic IR terminology in adapter crate responsibilities
v0.1.0 (2026-02-14)
Initial draft
Added
- Resolve versioning contradiction; loosen workspace layout clause