TenantAtlas/specs/237-provider-boundary-hardening/quickstart.md
ahmido bd26e209de
Some checks failed
Main Confidence / confidence (push) Failing after 57s
feat: harden provider boundaries (#273)
## Summary
- add the provider boundary catalog, boundary support types, and guardrails for platform-core versus provider-owned seams
- harden provider gateway, identity resolution, operation registry, and start-gate behavior to require explicit provider bindings
- add unit and feature coverage for boundary classification, runtime preservation, unsupported paths, and platform-core leakage guards
- add the full Spec Kit artifact set for spec 237 and update roadmap/spec-candidate tracking

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Providers/ProviderBoundaryClassificationTest.php tests/Unit/Providers/ProviderBoundaryGuardrailTest.php tests/Feature/Providers/ProviderBoundaryHardeningTest.php tests/Feature/Providers/UnsupportedProviderBoundaryPathTest.php tests/Feature/Guards/ProviderBoundaryPlatformCoreGuardTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Providers/ProviderGatewayTest.php tests/Unit/Providers/ProviderIdentityResolverTest.php tests/Unit/Providers/ProviderOperationStartGateTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- browser smoke: `http://localhost/admin/provider-connections?tenant_id=18000000-0000-4000-8000-000000000180` loaded with the local smoke user, the empty-state CTA reached the canonical create route, and cancel returned to the scoped list

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #273
2026-04-24 21:05:37 +00:00

4.6 KiB

Quickstart: Provider Boundary Hardening

Goal

Implement the first provider-boundary hardening slice without introducing a second-provider runtime, schema churn, or new operator-facing UI.

Implementation Sequence

  1. Done: added the config-backed seam ownership catalog and the small boundary helper layer.
  2. Done: removed Graph request-option shaping from ProviderIdentityResolution and kept it inside provider-owned gateway/options resolver seams.
  3. Done: split shared operation definitions from provider bindings in ProviderOperationRegistry and made ProviderOperationStartGate consume explicit bindings.
  4. Done: kept remaining Microsoft-first identity details documented as explicit current-release exceptions instead of widening into schema and UI neutrality.
  5. Done: added focused unit and feature coverage proving current Microsoft behavior still works and unsupported shared-boundary paths fail explicitly.

Suggested Code Areas

apps/platform/app/Support/Providers/Boundary/
apps/platform/config/provider_boundaries.php
apps/platform/app/Services/Providers/
apps/platform/app/Services/Graph/
apps/platform/app/Models/ProviderConnection.php
apps/platform/tests/Unit/Providers/
apps/platform/tests/Feature/Providers/

Authoritative Seam Inventory

  • provider.gateway_runtime
  • provider.identity_resolution
  • provider.connection_resolution
  • provider.operation_registry
  • provider.operation_start_gate

Verification Commands

Run the narrowest proving lane first:

cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Providers/ProviderBoundaryClassificationTest.php tests/Unit/Providers/ProviderBoundaryGuardrailTest.php

Then run the bounded runtime and unsupported-path proof:

cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Providers/ProviderBoundaryHardeningTest.php tests/Feature/Providers/UnsupportedProviderBoundaryPathTest.php

Then run the feature-guard proof that blocks provider leakage in platform-core seams:

cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/ProviderBoundaryPlatformCoreGuardTest.php

If PHP files were added or changed, finish with formatting:

cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent

Review Focus

  • Confirm ProviderIdentityResolution no longer emits Graph-shaped request options directly.
  • Confirm ProviderGateway and MicrosoftGraphOptionsResolver are the provider-owned seams that now assemble Graph request options.
  • Confirm ProviderOperationRegistry keeps platform-core operation definition separate from provider binding.
  • Confirm unsupported touched seams fail explicitly instead of inheriting Microsoft default behavior.
  • Confirm entra_tenant_id and platform app identity remain explicit current-release exceptions, not silent platform-core truth.
  • Confirm no second-provider runtime, schema rewrite, or UI surface slipped into the slice.

Guardrail Close-Out

  • Validation completed before final handoff:
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Providers/ProviderBoundaryClassificationTest.php tests/Unit/Providers/ProviderBoundaryGuardrailTest.php tests/Feature/Providers/ProviderBoundaryHardeningTest.php tests/Feature/Providers/UnsupportedProviderBoundaryPathTest.php tests/Feature/Guards/ProviderBoundaryPlatformCoreGuardTest.php
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Providers/ProviderGatewayTest.php tests/Unit/Providers/ProviderIdentityResolverTest.php tests/Unit/Providers/ProviderOperationStartGateTest.php
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
  • Guardrails checked:
    • No new Graph contract path.
    • No new provider runtime or marketplace abstraction.
    • ProviderIdentityResolution no longer exposes graphOptions() or client_request_id.
    • ProviderOperationRegistry keeps platform-core definitions separate from explicit provider bindings.
    • ProviderOperationStartGate blocks unsupported provider bindings with provider_binding_unsupported instead of falling back to Microsoft.
    • No undocumented provider-shaped exception on touched platform-core seams.
  • Close-out decision: document-in-feature. The remaining Microsoft-first identity and target-scope details are bounded in provider_boundaries.php, covered by guardrails, and intentionally left for the next provider identity/target-scope neutrality spec.
  • Bounded follow-up: deeper provider identity and target-scope neutrality remains a separate next spec; no schema rewrite, UI vocabulary rewrite, or second-provider runtime is included here.