TenantAtlas/specs/381-provider-resource-identity-binding/spec.md
ahmido 04d0d6184f feat(resources): implement provider resource identity binding (#452)
Added `ProviderResourceBinding` model, migrations, policies, and supporting framework for canonical resource identity mapping as defined in Spec 381. This provides the structural capability to resolve baseline and posture discrepancies by binding logical entities across source providers to canonical identities.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #452
2026-06-15 18:45:38 +00:00

40 KiB

Feature Specification: Spec 381 - Provider Resource Identity and Binding Foundation v1

Feature Branch: 381-provider-resource-identity-binding Created: 2026-06-15 Status: Draft / Ready for implementation preparation review Input: User-provided draft candidate "Spec 381 - Provider Resource Identity & Binding Foundation v1" from /Users/ahmeddarrazi/.codex/attachments/6b3f1f8d-d672-4e3a-a862-51fc5707afb9/pasted-text.txt.

Repo-Truth Adjustment

The active automatic candidate queue in docs/product/spec-candidates.md currently says no safe automatic next-best-prep target remains. This package is therefore treated as an explicit user-provided manual candidate, not an auto-selected queue item.

The source draft proposes a broad provider-agnostic identity and binding foundation. This prepared Spec 381 intentionally narrows it to the smallest implementation-ready foundation that fits current repo truth and the constitution:

  • V1 is managed-environment scoped only. Workspace-wide, baseline-profile-specific, and subject-only binding scopes are deferred until a concrete current workflow requires them.
  • V1 reuses and extends App\Support\Baselines\BaselineSubjectKey rather than creating a parallel CanonicalSubjectKey class by default.
  • V1 reuses existing baseline management capabilities for binding decisions unless implementation proves a separate capability is necessary and the spec/plan are updated first.
  • V1 does not add a Filament resource, resolution UI, matching pipeline rewrite, automatic Microsoft built-in mapping, evidence readiness change, or review-pack behavior change.
  • V1 removes duplicate is_active state from the source draft. binding_status=active is the single active-binding truth.

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: Baseline compare and future governance flows still risk treating mutable display names and overloaded policy_type + subject_key values as durable identity for governed subjects.
  • Today's failure: Provider built-ins, virtual assignment targets, tenant-owned duplicates, restored/test objects, and inventory-only foundation resources can collapse into ambiguous display-name-derived subjects, creating false red outcomes, false green outcomes, or non-auditable operator workarounds.
  • User-visible improvement: Future compare, review, and evidence surfaces can identify whether a governed subject is a concrete provider resource, provider built-in, virtual target, tenant-owned duplicate, accepted limitation, excluded object, unsupported coverage, or missing expected resource without relying on display names as identity.
  • Smallest enterprise-capable version: Add provider-agnostic identity primitives, extend the existing baseline subject-key foundation, add a provider resource descriptor shape, persist managed-environment-scoped provider resource bindings, enforce active uniqueness, authorize and audit manual decisions, and prove the foundation without changing compare/evidence/review runtime behavior.
  • Explicit non-goals: No full matching pipeline, no automatic Microsoft built-in canonicalization, no resolution UI, no evidence/review readiness changes, no customer-facing output changes, no generic workflow engine, no multi-provider framework, no Graph calls, no historical OperationRun backfill, and no workspace/baseline-profile binding scopes in v1.
  • Permanent complexity imported: One new managed-environment-scoped binding table/model/factory/policy/service, two small identity/descriptor support classes, two focused enum families for binding status and resolution mode, migration/index tests, service/audit tests, and terminology that future baseline identity specs must preserve.
  • Why now: The roadmap's provider-neutrality hardening theme names Provider Identity & Target Scope Neutrality as an anti-drift foundation, and the user supplied the numbered Spec 381 draft as the next manual candidate after Spec 380.
  • Why not local: A local compare patch would keep display-name identity and manual decisions as run-local interpretation. Binding decisions must survive across runs, be queryable by managed environment, and be auditable because they affect future governance truth.
  • Approval class: Core Enterprise.
  • Red flags triggered: New truth model, new persisted entity, new enum/status family, foundation language, and follow-up sequence. Defense: the spec is narrowed to current managed-environment scope, removes duplicate state, reuses existing baseline/capability seams, and prohibits matching/UI/evidence expansion.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
  • Decision: approve as a narrowed Core Enterprise foundation, with matching, UI, and evidence/review integration split into follow-up specs.

Candidate Selection Gate

  • Selected candidate: Spec 381 - Provider Resource Identity and Binding Foundation v1.
  • Source: Direct user-provided candidate attachment, with roadmap relationship to docs/product/roadmap.md R1.x Foundation Hardening - Governance Platform Anti-Drift, especially Provider Identity & Target Scope Neutrality.
  • Why selected: The active auto-prep queue is empty, but the user supplied a complete, numbered manual candidate that follows the completed Spec 380 sequence and unlocks the proposed Specs 382-385.
  • Roadmap relationship: Supports provider boundary hardening, governed-subject vocabulary enforcement, and baseline identity safety before additional matching, evidence, or review readiness semantics are added.
  • Close alternatives deferred:
    • governance-artifact-lifecycle-retention-runtime: broader artifact lifecycle P2 candidate, unrelated to baseline subject identity.
    • provider-readiness-onboarding-productization: optional onboarding/readiness UX, not the underlying compare identity foundation.
    • cross-domain-indicator-runtime-follow-through: UI/runtime indicator adoption, not provider resource identity.
    • manual-system-panel-browser-fixture-or-audit-procedure: validation procedure, not a domain foundation.
    • first-governed-ai-runtime-consumer: P3 runtime consumer and explicitly later.
  • Completed-spec guardrail result:
    • specs/163-baseline-subject-resolution/ has completed task markers and is historical implementation context. It must not be rewritten or converted back into preparation state.
    • specs/380-management-report-pdf-staging-runtime-validation/ is completed release-validation context for the dependency sequence. It is not modified by Spec 381.
    • No specs/381-* directory or 381-* local/remote branch existed before this preparation run.
  • Smallest viable implementation slice: Managed-environment-scoped provider resource identity and binding persistence, with no-op compare/evidence integration proof.
  • Gate result: PASS. The candidate is user-provided, unprepared, not completed, roadmap-aligned, and narrowed to a bounded implementation slice.

Problem Statement

TenantPilot currently has structured baseline subject and resolution semantics, but the durable identity for a governed subject can still fall back to display-name-derived keys or overloaded policy-centric identifiers. Display names are labels, not identity. They are mutable, non-unique, provider-specific, and frequently reused by defaults, restored objects, copied policies, test resources, and built-in targets.

The missing product foundation is a durable way to say which provider resource, built-in target, virtual target, unsupported subject, exclusion, or accepted limitation a managed-environment baseline subject maps to. Without this, future matching and evidence specs would keep patching around display-name ambiguity instead of using auditable provider resource truth.

Business / Product Value

  • Reduces false ambiguity and false confidence in baseline compare results.
  • Lets future operators make binding, exclusion, unsupported-coverage, and accepted-limitation decisions once and have them persist safely.
  • Creates auditable groundwork for later resolution UI and evidence/readiness behavior.
  • Keeps platform-core identity terms provider-neutral while allowing provider-specific knowledge behind later adapters.
  • Protects customer trust by separating "not found", "not supported", "accepted limitation", and "known built-in or virtual target" before these states reach management-ready outputs.

Primary Users / Operators

  • MSP operator or workspace manager responsible for baseline governance accuracy.
  • Tenant operator reviewing compare results and deciding whether a mismatch is actionable.
  • Release owner validating that baseline identity semantics do not regress into provider-specific or display-name-only shortcuts.
  • Future support/platform operator diagnosing why a subject was resolved, excluded, or treated as a limitation.

Spec Scope Fields (mandatory)

  • Scope: tenant-owned managed-environment identity foundation within workspace boundary.
  • Primary Routes: No new or changed routes in v1. Existing baseline compare, evidence, review, and OperationRun surfaces are regression targets only.
  • Data Ownership: New provider_resource_bindings rows are tenant-owned operational truth and MUST include workspace_id and managed_environment_id as non-null scope columns. The table MUST enforce the repo-standard composite workspace/environment invariant against managed_environments(id, workspace_id), and the model MUST use DerivesWorkspaceIdFromTenant or an equivalent invariant so workspace_id cannot drift from the bound managed environment. Provider identity support classes are derived in memory. Existing baseline snapshots, inventory items, policy versions, operation runs, evidence snapshots, stored reports, and review packs remain authoritative for their current domains.
  • RBAC: Existing workspace membership plus managed-environment entitlement is required. V1 reuses workspace_baselines.view for read semantics and workspace_baselines.manage for create/supersede/revoke decisions unless the implementation updates this spec before introducing dedicated capabilities.

For canonical-view specs:

  • Default filter behavior when tenant-context is active: Not applicable. Spec 381 adds no canonical-view route.
  • Explicit entitlement checks preventing cross-tenant leakage: Binding reads and mutations must resolve the target managed environment through workspace and managed-environment entitlement. Non-members receive deny-as-not-found. Members missing capability receive forbidden after membership is established.

UI Surface Impact (mandatory - UI-COV-001)

Does this spec add, remove, rename, or materially change any reachable UI surface?

  • No UI surface impact
  • Existing page changed
  • New page/route added
  • Navigation changed
  • Filament panel/provider surface changed
  • New modal/drawer/wizard/action added
  • New table/form/state added
  • Customer-facing surface changed
  • Dangerous action changed
  • Status/evidence/review presentation changed
  • Workspace/environment context presentation changed

UI/Productization Coverage

N/A - no reachable UI surface impact. Spec 381 creates backend identity and binding foundations only. Baseline compare, evidence, review, and OperationRun surfaces remain unchanged and are regression targets. The future resolution UI belongs to Spec 384.

Cross-Cutting / Shared Pattern Reuse

  • Cross-cutting feature?: yes, it touches provider/platform seams, baseline subject identity, RBAC, audit, and future evidence/review truth.
  • Interaction class(es): no UI interaction class in v1. Backend shared families include provider boundary vocabulary, baseline subject keys, managed-environment isolation, audit events, and capability enforcement.
  • Systems touched: BaselineSubjectKey, baseline subject/resolution support classes, provider connection/resource identity metadata, AuditLog, capability/policy enforcement, PostgreSQL migration/index patterns.
  • Existing pattern(s) to extend: existing baseline subject and resolution support, existing Capabilities registry, existing policy/Gate semantics, existing AuditLog model/builder patterns, existing partial unique index migration patterns.
  • Shared contract / presenter / builder / renderer to reuse: none for UI. Reuse BaselineSubjectKey, SubjectClass, ResolutionOutcome, ProviderConnection, InventoryItem, PolicyVersion, BaselineSnapshot, OperationRun, and AuditLog as current repo truth.
  • Why the existing shared path is sufficient or insufficient: Existing subject classes and resolution outcomes classify compare behavior, but they do not persist durable provider resource binding decisions. Existing BaselineSubjectKey is sufficient as the place to evolve canonical subject key creation without a parallel class in v1.
  • Allowed deviation and why: one new binding persistence/service path is allowed because manual identity decisions must outlive a run and be audited independently.
  • Consistency impact: New identity terms must not create a second subject taxonomy. Existing compare/evidence/review semantics must remain unchanged until follow-up specs deliberately consume bindings.
  • Review focus: no display-name-only identity as primary truth, no Microsoft built-in literals in core, no workspace/managed-environment leakage, no duplicate active binding, and no hidden compare behavior change.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: no.
  • Shared OperationRun UX contract/layer reused: N/A.
  • Delegated start/completion UX behaviors: N/A.
  • Local surface-owned behavior that remains: N/A.
  • Queued DB-notification policy: N/A.
  • Terminal notification path: N/A.
  • Exception required?: none.

Bindings may reference a source OperationRun for traceability, but creating, updating, superseding, or revoking a binding is expected to be a short DB-only, security-relevant action that writes AuditLog and does not create a new OperationRun.

Provider Boundary / Platform Core Check

  • Shared provider/platform boundary touched?: yes.
  • Boundary classification: mixed. ResourceIdentity, descriptors, bindings, and canonical subject keys are platform-core. Provider-specific built-in names, Graph endpoints, and Microsoft matching rules remain provider-owned and out of scope.
  • Seams affected: governed subject keys, provider resource identity descriptors, binding persistence, baseline compare future input seams, audit metadata, capability enforcement.
  • Neutral platform terms preserved or introduced: provider, provider connection, managed environment, governed subject, subject class, subject type key, canonical subject key, provider resource identity, binding, resolution mode.
  • Provider-specific semantics retained and why: provider_key and provider resource type/id/discriminator fields are retained as provider-owned descriptors, not platform-wide nouns. Microsoft examples may appear only in tests or docs as provider-specific examples, not as core logic.
  • Why this does not deepen provider coupling accidentally: Core classes must not branch on literal Microsoft display names such as All users, All devices, or Default. A fake-provider contract test must prove identity and binding can work without Microsoft values.
  • Follow-up path: Spec 382 may consume descriptors and bindings in the matching pipeline. Spec 384 may add operator UI. Spec 385 may integrate evidence/review readiness.

UI / Surface Guardrail Impact

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Provider resource identity and binding foundation no N/A baseline identity, audit, RBAC backend domain truth only no No route, page, navigation, action, table, modal, or presentation change in v1

Decision-First Surface Role

N/A - no operator-facing surface change.

Audience-Aware Disclosure

N/A - no customer/operator-facing detail or status surface change. Future disclosure belongs to resolution UI and evidence/review integration follow-up specs.

UI/UX Surface Classification

N/A - no operator-facing list, detail, queue, audit, config, or report surface is added or materially changed.

Operator Surface Contract

N/A - no new operator-facing page or material page refactor.

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: yes. Active provider_resource_bindings rows become durable managed-environment-scoped identity decision truth for future baseline subject resolution.
  • New persisted entity/table/artifact?: yes. provider_resource_bindings.
  • New abstraction?: yes, narrowly: ResourceIdentity, ProviderResourceDescriptor, and a binding service. BaselineSubjectKey is extended rather than replaced.
  • New enum/state/reason family?: yes. Binding status and resolution mode are introduced because they change active lookup, audit consequences, revocation/supersession behavior, and later matching/readiness semantics.
  • New cross-domain UI framework/taxonomy?: no.
  • Current operator problem: Operators need future compare/review truth to distinguish provider resource identity, built-ins, virtual targets, unsupported coverage, exclusions, and accepted limitations without renaming provider objects or relying on one run's diagnostics.
  • Existing structure is insufficient because: Existing subject/resolution classes classify runtime gaps, but they do not persist auditable binding decisions or durable provider resource identity across compare runs.
  • Narrowest correct implementation: Managed-environment-scoped bindings only, existing capability reuse, no UI, no matching rewrite, no automatic canonicalizer, no workspace/baseline-profile scopes, and no duplicate active-state column.
  • Ownership cost: Migration/index maintenance, one model/policy/service, identity/descriptor unit tests, PostgreSQL partial unique coverage, and reviewer discipline to keep follow-up matching/UI/evidence work separate.
  • Alternative intentionally rejected: Run-local JSON context notes or display-name normalization only. Those are not durable, not uniquely constrained, not safely queryable, and not independently auditable.
  • Release truth: current-release foundation needed before the immediately proposed matching, compare semantics, UI, and evidence/review specs can be implemented safely.

Compatibility posture

This feature assumes a pre-production environment. Existing records remain readable, but no legacy alias, dual-write path, historical OperationRun rewrite, or backfill is required. Existing display-name-derived subject keys may remain as legacy/fallback inputs while new canonical subject keys are introduced for new binding records.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Unit for identity/value-object behavior, Feature for service/RBAC/audit/isolation, PostgreSQL for partial unique indexes and constraints, targeted regression for baseline compare/evidence/review no-op behavior.
  • Validation lane(s): fast-feedback, confidence, and PostgreSQL. Browser is not required because no UI changes.
  • Why this classification and these lanes are sufficient: The change is backend identity and persistence truth. Unit tests prove deterministic identity; feature tests prove business behavior; PostgreSQL proves partial unique active binding safety that SQLite cannot prove.
  • New or expanded test families: a focused ProviderResources or equivalent feature/unit family for binding foundation; no heavy-governance or browser family.
  • Fixture / helper cost impact: new factory for ProviderResourceBinding; fake-provider fixtures must stay local to these tests and must not widen default workspace/provider setup.
  • Heavy-family visibility / justification: none.
  • Special surface test profile: N/A - no Filament or operator surface.
  • Standard-native relief or required special coverage: no UI coverage required.
  • Reviewer handoff: verify no display-name-only primary identity, no Microsoft literal core branches, no duplicate active truth, no managed-environment leakage, and no compare/evidence/review behavior change.
  • Budget / baseline / trend impact: minimal; PostgreSQL lane adds one focused migration/index test. Escalate if implementation broadens compare/evidence suites or creates heavy fixtures.
  • Escalation needed: document-in-feature if a contained provider-boundary exception remains; follow-up-spec if workspace-level binding scope, resolution UI, automatic canonicalization, or evidence readiness behavior becomes necessary.
  • Active feature PR close-out entry: Identity Binding Foundation / Provider Boundary.
  • Planned validation commands:
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/Resources/ResourceIdentityTest.php tests/Unit/Support/Resources/ProviderResourceDescriptorTest.php tests/Unit/Support/Baselines/BaselineSubjectKeyCanonicalIdentityTest.php
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderResources/ProviderResourceBindingServiceTest.php
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml tests/Feature/ProviderResources/ProviderResourceBindingPostgresTest.php
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Baselines/BaselineCompareGapClassificationTest.php tests/Feature/Evidence/BaselineDriftPostureSourceTest.php tests/Feature/ReviewPack/Spec349ReviewPackResolutionGuidanceTest.php
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
    • git diff --check

User Scenarios & Testing (mandatory)

User Story 1 - Represent provider identity without display names (Priority: P1)

As a baseline governance operator, I need TenantPilot to represent governed subjects by stable provider identity or canonical platform identity instead of display names, so copied, restored, built-in, virtual, and duplicate resources do not collapse into the same subject.

Why this priority: This is the core trust gap. Later matching and resolution UI cannot be safe while identity is still display-name-first.

Independent Test: Unit tests create tenant-owned, built-in, virtual, unsupported, and unknown ResourceIdentity values and canonical subject keys, then prove display labels are optional and equality/key generation uses stable identity fields.

Acceptance Scenarios:

  1. Given two provider resources with the same display label but different provider resource IDs, When canonical subject keys are generated, Then the keys differ without requiring a renamed display label.
  2. Given a provider built-in or virtual assignment target with no provider object ID, When the identity is represented, Then the identity uses provider/canonical discriminator fields rather than a display-name fallback.
  3. Given a fake provider with non-Microsoft resource types, When descriptors are serialized and compared, Then the core identity model remains valid without Microsoft Intune literals.

User Story 2 - Persist auditable binding decisions (Priority: P1)

As an authorized workspace baseline manager, I need manual binding, exclusion, accepted limitation, unsupported coverage, and revocation decisions to persist with audit evidence, so future compare runs can reuse trusted decisions instead of re-litigating ambiguity.

Why this priority: Durable and auditable decisions are the difference between a one-run diagnostic note and enterprise governance truth.

Independent Test: Feature and PostgreSQL tests create, supersede, and revoke managed-environment-scoped bindings; assert active uniqueness, note requirements, authorization, workspace/managed-environment isolation, and audit events.

Acceptance Scenarios:

  1. Given an authorized manager creates a manual binding for a managed environment, When the service stores it, Then the row includes workspace, managed environment, provider key, canonical subject key, resolution mode, actor, note, and audit metadata.
  2. Given an active binding already exists for the same managed-environment/provider/canonical subject key, When a new binding supersedes it, Then exactly one active binding remains and the old row is marked superseded.
  3. Given a user from another workspace or without baseline management capability, When they attempt to create or revoke a binding, Then cross-workspace access is denied as not found and missing capability is forbidden after entitlement is established.

User Story 3 - Preserve existing compare and evidence behavior (Priority: P2)

As a release owner, I need this foundation to land without changing baseline compare, evidence readiness, review readiness, or customer-facing output, so the platform gains identity safety without hidden behavior changes.

Why this priority: Follow-up specs will deliberately consume bindings. Spec 381 must not silently change current operational truth.

Independent Test: Existing targeted compare/evidence/review tests still pass, and new no-op regression coverage proves the binding table is not automatically consumed by current compare or readiness paths.

Acceptance Scenarios:

  1. Given existing baseline compare fixtures, When Spec 381 foundation code exists, Then compare result semantics remain unchanged unless a follow-up spec explicitly changes them.
  2. Given evidence and review readiness tests, When bindings exist in the database, Then readiness output remains unchanged in v1.
  3. Given the implementation adds passive helper seams, When they are unused by the current pipeline, Then they do not perform Graph calls, queue jobs, or alter OperationRun lifecycle.

Edge Cases

  • Two tenant-owned resources share the same display label but have different provider IDs.
  • A provider built-in or virtual target has no provider resource ID.
  • A provider connection is deleted or disabled after a binding is created.
  • A binding references source evidence from an old OperationRun, inventory item, policy version, or baseline snapshot.
  • A binding attempts to reference a provider connection, OperationRun, inventory item, policy version, or baseline snapshot outside the binding workspace, managed environment, or provider scope.
  • A manual decision lacks an operator note.
  • A revoked or superseded binding exists for the same canonical subject as a new active binding.
  • A fake provider descriptor uses a provider key, resource type, and discriminator that are not Microsoft-shaped.
  • Existing compare inputs continue to include legacy display-name-derived subject keys.

Requirements (mandatory)

Constitution alignment (required): This feature adds no Graph calls, no queued work, no OperationRun lifecycle change, no UI surface, and no customer-facing output change. It introduces new persistence and semantic machinery, so the proportionality review is mandatory and included above. Mutating binding decisions are DB-only but security-relevant, so they require policy/Gate authorization and AuditLog entries.

Constitution alignment (PROV-001): Provider-specific knowledge remains outside platform core. Core identity classes may store provider-owned fields, but must not branch on Microsoft display names or Graph endpoint assumptions.

Constitution alignment (RBAC-UX): Binding reads and mutations must enforce workspace and managed-environment entitlement. Non-member access is deny-as-not-found; entitled member missing capability is forbidden. UI visibility is not security, even though no UI is included in v1.

Constitution alignment (PERSIST-001 / STATE-001): Bindings are persisted because they are independent, auditable identity decisions that survive a run and change future resolution behavior. Binding statuses and resolution modes are allowed only because they determine active lookup, audit meaning, supersession/revocation behavior, and future operator next actions.

Functional Requirements

  • FR-381-001: TenantPilot MUST represent provider resource identity without requiring display name as primary identity.
  • FR-381-002: TenantPilot MUST support identity shapes for tenant-owned provider resources, provider built-ins, provider defaults, virtual resources, unsupported resources, and unknown resources.
  • FR-381-003: TenantPilot MUST evolve the existing baseline subject key foundation so canonical keys can encode provider key, subject class, subject type, resource type, and stable identity or canonical discriminator.
  • FR-381-004: TenantPilot MUST provide a provider resource descriptor shape that wraps identity, display label, subject metadata, source references, fingerprint where available, and last-seen metadata.
  • FR-381-005: TenantPilot MUST persist managed-environment-scoped provider resource bindings in provider_resource_bindings.
  • FR-381-006: Each provider resource binding MUST be scoped by workspace_id, managed_environment_id, provider_key, and canonical_subject_key.
  • FR-381-006A: Each persisted binding MUST enforce the workspace/managed-environment pair with a composite foreign key to managed_environments(id, workspace_id) and a model-level workspace derivation guard.
  • FR-381-007: TenantPilot MUST prevent more than one active binding for the same managed-environment/provider/canonical subject key.
  • FR-381-008: Binding status MUST distinguish active, superseded, and revoked rows.
  • FR-381-009: Resolution mode MUST distinguish exact provider identity, canonical built-in, canonical virtual target, manual binding, excluded non-governed object, accepted limitation, unsupported coverage, and missing expected resource. Provider defaults are represented as canonical built-ins in v1 unless this spec is updated before implementation.
  • FR-381-010: Manual binding, exclusion, accepted limitation, unsupported coverage, missing expected, supersession, and revocation decisions MUST require an operator note or reason.
  • FR-381-011: Binding decisions and revocations MUST emit audit records with actor, workspace, managed environment, provider key, canonical subject key, old binding ID where applicable, new binding ID where applicable, resolution mode, and safe source references. Operator-provided note text MUST be redacted, summarized, length-limited, or referenced safely before it is written to audit metadata; raw notes MUST NOT be copied into audit metadata unchecked.
  • FR-381-012: Binding service methods MUST enforce workspace and managed-environment scope before reading, creating, superseding, or revoking records.
  • FR-381-012A: Binding service methods MUST validate any provider_connection_id, source_operation_run_id, source_inventory_item_id, source_policy_version_id, and source_baseline_snapshot_id against the binding workspace and managed environment before persistence. A referenced provider connection MUST belong to the same workspace and managed environment and match provider_key when present.
  • FR-381-013: V1 MUST reuse existing baseline capabilities unless the spec is updated before dedicated provider-resource-binding capabilities are introduced.
  • FR-381-014: Core identity and binding logic MUST NOT hardcode Microsoft Intune display names, Graph endpoint names, or provider-default object labels.
  • FR-381-015: Fake-provider contract tests MUST prove the identity and binding foundation is not Microsoft-only, including service-level persistence and mutation behavior, not only in-memory identity/descriptor serialization.
  • FR-381-016: V1 MUST NOT rewrite baseline compare matching, evidence completeness, review readiness, review-pack publication, or customer-facing output.
  • FR-381-017: Existing baseline snapshots, baseline snapshot items, inventory items, policy versions, operation runs, evidence snapshots, stored reports, and review packs MUST remain readable without backfill.

Non-Functional Requirements

  • NFR-381-001 - Workspace isolation: No binding may leak across workspace boundaries; database constraints, model invariants, service resolution, and policy tests must all reinforce the same workspace boundary.
  • NFR-381-002 - Managed-environment isolation: No binding may affect another managed environment; source references and provider connections must be rejected if they do not belong to the binding's managed environment.
  • NFR-381-003 - Auditability: Every governance-impacting manual binding decision is traceable and redacted.
  • NFR-381-004 - Provider neutrality: Platform-core code stores provider identity fields but does not treat Microsoft as platform truth.
  • NFR-381-005 - Backward compatibility: Existing development data remains readable; no historical OperationRun or snapshot rewrite is required.
  • NFR-381-006 - Minimal runtime risk: No current compare, evidence, review, or report outcome changes in v1.
  • NFR-381-007 - PostgreSQL integrity: Active binding uniqueness, workspace/environment composite integrity, enum/check-constraint validity where practical, and service-level validation are covered in the PostgreSQL lane.

UI Action Matrix (mandatory when Filament is changed)

N/A - no Filament Resource, RelationManager, Page, action, table, form, modal, drawer, wizard, navigation entry, or panel/provider surface is added or changed.

Key Entities (include if feature involves data)

  • ResourceIdentity: Provider-agnostic in-memory identity for a tenant-owned, built-in, default, virtual, unsupported, or unknown provider resource.
  • ProviderResourceDescriptor: Normalized in-memory descriptor that wraps ResourceIdentity and carries display label, subject class/type, source references, fingerprint, and last-seen metadata for future matching.
  • Canonical Subject Key: Stable governed-subject key created through the existing baseline key foundation, using provider/resource identity or canonical discriminator rather than display-name-only identity.
  • ProviderResourceBinding: Managed-environment-scoped persisted decision that maps a canonical subject key to a provider identity, built-in/virtual target, manual binding, exclusion, accepted limitation, unsupported coverage, or missing expected marker.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-381-001: Unit tests prove at least six identity forms: tenant-owned, built-in, default, virtual, unsupported, and unknown.
  • SC-381-002: Unit tests prove two subjects with the same display label but different stable provider identity produce distinct canonical keys.
  • SC-381-003: PostgreSQL tests prove only one active binding can exist for a managed-environment/provider/canonical subject key.
  • SC-381-004: Feature tests prove unauthorized cross-workspace access is deny-as-not-found and missing capability is forbidden after entitlement is established.
  • SC-381-005: Feature tests prove manual decisions require notes and emit audit records.
  • SC-381-006: Fake-provider tests prove the core foundation and binding service work without Microsoft Intune literals.
  • SC-381-007: Targeted existing compare, evidence, and review tests pass without behavior changes.

Out of Scope

  • Baseline matching pipeline rewrite.
  • Automatic canonicalization of Microsoft built-ins such as All users, All devices, or default role scope tags.
  • Baseline Subject Resolution UI.
  • Evidence Snapshot readiness changes.
  • Environment Review readiness changes.
  • Review Pack publication/output changes.
  • Customer-facing output changes.
  • Historical OperationRun or snapshot backfill.
  • Workspace-wide, baseline-profile-specific, or subject-only binding scopes.
  • Generic provider adapter framework or workflow engine.
  • Graph calls or provider runtime calls.
  • New Filament resource or global search surface.

Risks

  • Over-generalization: The foundation could drift into a provider framework. Mitigation: no provider adapters, automatic canonicalizers, or matching pipeline changes in v1.
  • Duplicate taxonomy: New classes could duplicate SubjectClass and existing baseline semantics. Mitigation: reuse/extend existing subject key and subject class seams.
  • Scope leakage: Bindings could apply across workspaces or managed environments. Mitigation: non-null scope columns, policy checks, service checks, partial unique index, and isolation tests.
  • False green later: Accepted limitation could be interpreted as verified success. Mitigation: resolution mode is explicit and follow-up specs must map it as limitation, not no-drift.
  • Provider-specific leakage: Core logic could accidentally hardcode Microsoft defaults. Mitigation: fake-provider tests and provider-boundary review.

Assumptions

  • Spec 380 has been completed/committed separately and is not modified by this package.
  • Managed-environment scope is sufficient for the first valuable binding foundation.
  • Existing workspace_baselines.view and workspace_baselines.manage capabilities are acceptable for v1.
  • Provider connection ID is nullable for built-in, virtual, unsupported, missing expected, and fake-provider cases, but any supplied provider connection ID must be scoped to the same workspace and managed environment and must match provider_key.
  • Source references are traceability hints only; they never authorize cross-scope access and must be rejected when they point outside the binding workspace or managed environment.
  • Revocation marks the existing binding revoked and non-active through status; it does not create a new revocation row unless implementation discovers an audit/legal need and updates the spec first.
  • Automatic provider built-in bindings are not stored by v1; they are future matching/canonicalization behavior.

Open Questions

None blocking for implementation. The source draft questions are resolved by the narrowed assumptions above. Broader scope choices are deferred to follow-up specs.

Follow-up Spec Candidates

  • Spec 382 - Baseline Matching Pipeline & Canonicalization v1: consume ResourceIdentity, descriptors, canonical subject keys, and bindings before display-name fallback.
  • Spec 383 - Baseline Compare Result Semantics & Gap Classification v1: split overloaded compare result states using binding-aware semantics.
  • Spec 384 - Baseline Subject Resolution UI & Operator Decisions v1: add operator UI for bind, exclude, accept limitation, mark unsupported, and revoke.
  • Spec 385 - Evidence & Review Readiness Integration v1: map resolved, blocked, limited, and unsupported binding semantics into evidence and review readiness.
  • Workspace or baseline-profile binding scope: only if a concrete workspace-level or baseline-profile-level operator workflow proves environment scope insufficient.

Acceptance Criteria

  • AC-381-001: Provider-agnostic resource identity exists and does not require display name as primary identity.
  • AC-381-002: Canonical subject key creation can encode stable provider/resource identity or canonical discriminator through the existing baseline key foundation.
  • AC-381-003: Provider resource descriptor shape exists and is serializable for future matching use.
  • AC-381-004: provider_resource_bindings exists with workspace and managed-environment scope, composite workspace/environment integrity, active uniqueness, and scoped source references.
  • AC-381-005: Binding status and resolution mode are implemented and test-covered.
  • AC-381-006: Manual decision note requirements, authorization, isolation, supersession, revocation, audit behavior, and audit-note redaction/safe-reference behavior are test-covered.
  • AC-381-007: Fake-provider coverage proves provider neutrality through identity, descriptor, and binding-service persistence behavior.
  • AC-381-008: Existing compare, evidence, review, and review-pack behavior is unchanged in v1.