|
| 1 | +# Design: Bridge Registry for Cross-Module Service Interoperability |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +`arch-04-core-contracts-interfaces` establishes module IO contracts and core/module isolation, but it does not define how modules publish reusable schema converters for external services. The internal analysis dated 2026-02-08 and the implementation plan identify this as the next architectural step (arch-05) required before marketplace-grade module decoupling. |
| 6 | + |
| 7 | +Current state: |
| 8 | + |
| 9 | +- Service mapping logic is module-local and not discoverable through a common registry contract. |
| 10 | +- Module manifests support dependencies and core compatibility, but not converter bridge declarations. |
| 11 | +- Core must stay decoupled from module internals while still enabling dynamic bridge usage. |
| 12 | + |
| 13 | +## Goals / Non-Goals |
| 14 | + |
| 15 | +**Goals:** |
| 16 | + |
| 17 | +- Introduce a registry-level bridge abstraction (`SchemaConverter`, `BridgeRegistry`) for bidirectional schema conversion. |
| 18 | +- Make bridge declarations manifest-driven (`service_bridges`) and validated at module registration time. |
| 19 | +- Keep core/module isolation intact: no hardcoded core imports of module adapter implementations. |
| 20 | +- Deliver backlog reference converters (ADO, Jira, Linear, GitHub) as first adopters. |
| 21 | +- Document extension points for custom enterprise bridge mappings. |
| 22 | + |
| 23 | +**Non-Goals:** |
| 24 | + |
| 25 | +- Cryptographic signature validation and trust chain (arch-06). |
| 26 | +- Marketplace install/uninstall UX and remote registry APIs (marketplace-01/02). |
| 27 | +- Per-module Python environment isolation. |
| 28 | +- Breaking existing module registration APIs. |
| 29 | + |
| 30 | +## Decisions |
| 31 | + |
| 32 | +### Decision 1: Protocol + Registry Pattern for Bridges |
| 33 | + |
| 34 | +**Choice:** Define a `SchemaConverter` Protocol and a centralized `BridgeRegistry` with `register_converter()` and `get_converter()` methods. |
| 35 | + |
| 36 | +**Rationale:** |
| 37 | + |
| 38 | +- Preserves plugin-style extensibility already used in module discovery. |
| 39 | +- Keeps conversion contract explicit and testable. |
| 40 | +- Avoids hardcoded adapter branching in sync/backlog flows. |
| 41 | + |
| 42 | +**Alternatives considered:** |
| 43 | + |
| 44 | +- Inline converter logic in each command path: duplicates logic and increases coupling. |
| 45 | +- Abstract base class with strict inheritance: less flexible than protocol-based structural typing. |
| 46 | + |
| 47 | +### Decision 2: Manifest-Driven Bridge Registration |
| 48 | + |
| 49 | +**Choice:** Extend `module-package.yaml` metadata with `service_bridges` entries containing bridge id, description, and converter class path. |
| 50 | + |
| 51 | +**Rationale:** |
| 52 | + |
| 53 | +- Keeps registration declarative and discoverable. |
| 54 | +- Allows lifecycle validation before registration. |
| 55 | +- Supports future marketplace metadata verification without changing runtime architecture. |
| 56 | + |
| 57 | +**Alternatives considered:** |
| 58 | + |
| 59 | +- Hardcoded module-specific bridge lists in core: violates core isolation. |
| 60 | +- Runtime classpath scanning without manifest declarations: less deterministic and harder to validate. |
| 61 | + |
| 62 | +### Decision 3: Graceful Degradation on Bridge Registration Failures |
| 63 | + |
| 64 | +**Choice:** If a bridge declaration is invalid or import fails, skip that bridge with warning/debug logging; do not crash CLI startup. |
| 65 | + |
| 66 | +**Rationale:** |
| 67 | + |
| 68 | +- Matches existing module lifecycle behavior for compatibility/dependency issues. |
| 69 | +- Supports parallel module evolution without blocking unrelated workflows. |
| 70 | + |
| 71 | +**Alternatives considered:** |
| 72 | + |
| 73 | +- Fail-fast for any invalid bridge: safer but too disruptive for modular incremental rollout. |
| 74 | + |
| 75 | +### Decision 4: Backlog Module as Reference Bridge Provider |
| 76 | + |
| 77 | +**Choice:** Implement first converter set in backlog module (`ado`, `jira`, `linear`, `github`) and register through metadata. |
| 78 | + |
| 79 | +**Rationale:** |
| 80 | + |
| 81 | +- Backlog already contains major external service integration surface. |
| 82 | +- Provides concrete pattern for future modules to follow. |
| 83 | + |
| 84 | +## Risks / Trade-offs |
| 85 | + |
| 86 | +- **Risk:** Converter class import paths drift from code layout. |
| 87 | + - **Mitigation:** Add registration-time path validation tests and clear startup warnings. |
| 88 | +- **Risk:** Bridge IDs collide across modules. |
| 89 | + - **Mitigation:** Deterministic registration rules and explicit duplicate handling with warnings. |
| 90 | +- **Risk:** Converter logic divergence across modules. |
| 91 | + - **Mitigation:** Publish docs and contract tests against the `SchemaConverter` protocol. |
| 92 | +- **Trade-off:** Non-fatal bridge failures improve resilience but can hide misconfiguration. |
| 93 | + - **Mitigation:** Elevated warning logs and dedicated validation tests in CI. |
| 94 | + |
| 95 | +## Migration Plan |
| 96 | + |
| 97 | +1. Add bridge registry and converter protocol with unit tests. |
| 98 | +2. Extend manifest schema and parser for `service_bridges` metadata. |
| 99 | +3. Add lifecycle registration hooks for bridge declaration validation and registry insertion. |
| 100 | +4. Add backlog reference converters and manifest declarations. |
| 101 | +5. Update docs and run quality gates. |
| 102 | + |
| 103 | +Rollback strategy: |
| 104 | + |
| 105 | +- Remove bridge registration calls from module lifecycle. |
| 106 | +- Remove `service_bridges` metadata usage while keeping manifests backward compatible. |
| 107 | +- Keep backlog adapters functional through existing direct paths until reintroduced. |
| 108 | + |
| 109 | +## Open Questions |
| 110 | + |
| 111 | +- Should duplicate bridge IDs fail registration or use first-wins semantics with warnings? |
| 112 | +- Should converter registration support versioned bridge contracts in arch-06 or later? |
| 113 | +- Should enterprise custom mappings be loaded at bridge-level registration or adapter execution time? |
| 114 | + |
| 115 | +## Sequence Diagram: Manifest-Driven Bridge Registration |
| 116 | + |
| 117 | +```text |
| 118 | +CLI Startup -> ModuleRegistry: discover module packages |
| 119 | +ModuleRegistry -> ManifestParser: parse module-package.yaml |
| 120 | +ManifestParser --> ModuleRegistry: metadata (+service_bridges) |
| 121 | +ModuleRegistry -> BridgeRegistry: register_converter(bridge_id, converter_class) |
| 122 | +BridgeRegistry --> ModuleRegistry: success or warning |
| 123 | +ModuleRegistry --> CLI Startup: module commands + bridges available |
| 124 | +CLI Command -> BridgeRegistry: get_converter(service_id) |
| 125 | +BridgeRegistry --> CLI Command: SchemaConverter implementation |
| 126 | +``` |
0 commit comments