TenantAtlas/specs/237-provider-boundary-hardening/research.md
Ahmed Darrazi 079a7dcaf3
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 57s
feat: harden provider boundaries
2026-04-24 22:55:44 +02:00

42 lines
4.2 KiB
Markdown

# Research: Provider Boundary Hardening
## Decision 1: Use a small config-backed seam catalog instead of a provider framework
- **Decision**: Model first-slice provider-boundary ownership in one repository config catalog plus a small boundary helper layer, not as a speculative multi-provider framework.
- **Rationale**: The current release needs explicit ownership and guardrails across multiple real seams more than it needs connector plugins, provider registries, or generic runtime extension points. A config-backed catalog is reviewable, deterministic, and easy to enforce in tests.
- **Boundary model note**: The catalog keeps seam ownership binary as `provider_owned` or `platform_core`. Any retained Microsoft-first behavior is recorded as seam metadata with an explicit follow-up action, not as a third ownership state.
- **Alternatives considered**:
- Prose-only documentation and comments: rejected because reviewers cannot enforce it mechanically and the same drift can reappear on the next seam.
- Full provider-plugin architecture: rejected because there is still only one shipped provider runtime.
## Decision 2: Keep Graph request shaping inside provider-owned seams
- **Decision**: Remove Graph request-option shaping from `ProviderIdentityResolution` and keep it inside provider-owned seams such as `ProviderGateway` and `MicrosoftGraphOptionsResolver`.
- **Rationale**: A shared identity-resolution object currently knows Microsoft Graph request-option keys and request-id generation details. That is provider-owned behavior and should not live on a platform-core result type.
- **Alternatives considered**:
- Leave `graphOptions()` on `ProviderIdentityResolution`: rejected because it preserves Graph semantics in a shared runtime type.
- Introduce a broad provider request-context framework: rejected because the narrower extraction into existing provider-owned seams is sufficient.
## Decision 3: Split shared operation definition from provider binding
- **Decision**: Keep platform-core operation metadata separate from provider binding metadata in `ProviderOperationRegistry` and the `ProviderOperationStartGate` path.
- **Rationale**: Operation type, module, label, and capability are shared orchestration truth. The fact that the current runtime binds those operations to `microsoft` is provider-owned current-release behavior and should be explicit rather than silent default truth.
- **Alternatives considered**:
- Keep a single registry array with `provider => microsoft` on every entry: rejected because it makes the current first provider look like a permanent platform default.
- Fold this work into operation-type canonicalization: rejected because this spec is about ownership boundaries, not renaming operation codes.
## Decision 4: Treat target-scope and platform app identity details as bounded current-release exceptions
- **Decision**: Keep `entra_tenant_id`, platform app credential config, and callback-specific details as explicit current-release exceptions in this slice instead of widening into schema and UI neutrality.
- **Rationale**: These are real hotspots, but the next candidate `Provider Identity & Target Scope Neutrality` exists specifically to clean up the deeper persistence and operator-vocabulary consequences. This slice should harden the boundary before it rewrites identity truth.
- **Alternatives considered**:
- Rename storage and UI semantics now: rejected because it would widen the slice into a second spec.
- Ignore the hotspot entirely: rejected because the plan needs one documented exception boundary rather than pretending the issue is solved.
## Decision 5: Enforce the boundary with focused unit and feature guardrails
- **Decision**: Prove the hardening with narrow unit and feature tests that exercise seam classification, provider-binding behavior, unsupported-path behavior, and Microsoft runtime preservation.
- **Rationale**: The risk is architectural drift inside shared services, not browser behavior. Focused code-level tests are the narrowest proof that the boundary is explicit and enforceable.
- **Alternatives considered**:
- Browser or UI smoke coverage: rejected because the slice adds no new operator-facing surface.
- Manual review only: rejected because the feature exists specifically to remove dependence on reviewer memory.