TenantAtlas/spec-candidates/380-provider-resource-identity-binding-foundation.md
ahmido dbff2a0a90 feat(report): implement management report pdf runtime (#450)
Added jobs, controllers, and PDF generation logic for management report runtime as defined in Spec 379. Includes artifact migrations, payload builders, and testing coverage.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #450
2026-06-15 11:36:29 +00:00

11 KiB

Spec Candidate 380 - Provider Resource Identity & Binding Foundation v1

Candidate Status

Candidate for implementation.

This candidate introduces the provider-agnostic identity and binding foundation required to resolve baseline subject ambiguity, built-in/default canonicalization, and future provider/resource-class expansion.

Spec Candidate Check

  • Problem: Baseline compare and capture can still treat display-name-derived subject_key values as if they were stable identity, which creates ambiguous or false missing states for built-ins, defaults, virtual targets, foundation resources, and tenant-owned duplicate names.
  • Today's failure: Operators can see ambiguous_match, policy_record_missing, or foundation_not_policy_backed without a durable way to distinguish real duplicate tenant resources from provider defaults, inventory-only coverage, unsupported classes, or accepted limitations.
  • User-visible improvement: Operators get auditable, workspace/environment/provider-scoped binding truth that later compare, evidence, review, and restore workflows can trust without pretending display names are identity.
  • Smallest enterprise-capable version: Add the binding table, core value objects, status/mode taxonomy, isolation rules, and audit contract only; do not rebuild matching, UI, evidence, restore, or review behavior in this slice.
  • Explicit non-goals: No full baseline compare matching rewrite, no resolution UI, no evidence/review readiness changes, no generic workflow engine, no restore redesign, and no production multi-provider implementation beyond fake-provider contract tests.
  • Permanent complexity imported: One persisted binding table, resource identity value object, canonical subject key evolution, descriptor object, resolution mode/status enums, subject/resource class taxonomy, audit requirements, model tests, and workspace/environment isolation tests.
  • Why now: Specs 381-384 depend on stable identity; without this foundation, later matching and customer-readiness work would keep encoding display-name ambiguity and false blocker states.
  • Why not local: A local compare-only patch cannot preserve manual decisions, exclusions, accepted limitations, or provider-default classification across future compares, evidence snapshots, and review packs.
  • Approval class: Core Enterprise.
  • Red flags triggered: New axes, new persisted truth, new meta-infrastructure, foundation terminology, and multiple follow-up specs in one domain. The defense is that identity ambiguity currently affects compare trust, evidence gaps, review readiness, and auditability; persistence is required because operator decisions must outlive a single run.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 1 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 10/12
  • Decision: approve as the first candidate, with strict scope control and no matching/UI expansion.

Proportionality Review

  1. Current operator problem: Operators cannot tell whether compare blockers are real duplicate resources, expected provider defaults, unsupported coverage, or missing local evidence.
  2. Why existing structure is insufficient: policy_type + subject_key and current resolution outcomes do not provide durable provider identity or auditable operator decisions.
  3. Narrowest correct implementation: Persist only bindings and identity primitives; all matching, result semantics, UI, and readiness work stays in later candidates.
  4. Ownership cost: Baseline/domain owners must maintain binding statuses, resolution modes, resource descriptors, and audit semantics.
  5. Rejected alternative: Snapshot-JSON-only or baseline-only annotations were rejected because they would not survive across compare runs or support revocation/audit.
  6. Current-release truth or future prep: Current-release trust foundation required by existing compare ambiguity and review-readiness gaps; not speculative multi-provider runtime work.

Problem

TenantPilot baseline compare currently relies too heavily on policy_type + subject_key, where subject_key can be derived from normalized display names. This is not enterprise-safe because names are not stable identity.

The current model cannot reliably distinguish:

  • provider-owned built-ins,
  • virtual assignment targets,
  • tenant-owned resources,
  • foundation objects,
  • policy objects,
  • unsupported resource classes,
  • excluded/non-governed resources,
  • duplicate display names,
  • accepted limitations.

This causes false or overloaded compare states such as:

  • ambiguous_match,
  • policy_record_missing,
  • foundation_not_policy_backed.

Goal

Create a durable, provider-agnostic identity and binding foundation that future compare, evidence, review, restore, and governance workflows can use.

This spec does not yet fully rebuild baseline matching or UI. It creates the data model and core primitives.

Scope

In Scope

  • Introduce ResourceIdentity value object.
  • Introduce or evolve CanonicalSubjectKey.
  • Introduce ProviderResourceDescriptor.
  • Add persistent provider_resource_bindings table.
  • Add resolution mode/status enums.
  • Add subject/resource class taxonomy for baseline resolution.
  • Enforce workspace/environment/provider isolation.
  • Add audit support for manual bindings, exclusions, accepted limitations, and revocations.
  • Add provider-agnostic contracts that future provider adapters can implement.
  • Add unit tests for value objects and binding model behavior.

Out of Scope

  • Full baseline compare matching rewrite.
  • Built-in canonicalization implementation.
  • Resolution UI.
  • Evidence/review readiness changes.
  • Generic workflow engine.
  • Full historical OperationRun backfill.
  • Restore redesign.
  • Multi-provider production implementation beyond fake-provider contract tests.

Design Principles

  • Display name is not identity.
  • Provider object ID or canonical provider key wins over display name.
  • Core logic must remain provider-agnostic.
  • Provider-specific knowledge belongs behind adapters/registries.
  • Bindings are persisted state, not workflow tasks.
  • Manual decisions must be auditable.
  • No fake green state.
  • No customer blocker for expected provider defaults once canonicalized.

Data Model

Add table:

provider_resource_bindings

Suggested fields:

id
workspace_id
environment_id nullable
provider_key
provider_connection_id nullable
binding_scope
subject_domain
subject_class
subject_type
subject_key
canonical_subject_key
provider_resource_type nullable
provider_resource_id nullable
provider_resource_external_id nullable
provider_resource_discriminator nullable
provider_resource_fingerprint nullable
binding_status
resolution_mode
resolution_reason
operator_note nullable
source_operation_run_id nullable
source_baseline_snapshot_id nullable
source_baseline_compare_run_id nullable
source_inventory_item_id nullable
source_policy_version_id nullable
decided_by_user_id nullable
decided_at nullable
is_active
valid_from nullable
valid_until nullable
created_at
updated_at

Binding Status

Required values:

active
inactive
superseded
revoked

Resolution Modes

Required v1 modes:

exact_provider_identity
canonical_builtin
canonical_virtual_target
manual_binding
excluded_non_governed
accepted_limitation
unsupported_coverage
missing_expected

Subject Classes

Minimum v1 classes:

policy
foundation
assignment_target
virtual_assignment_target
provider_builtin
provider_default
unsupported
unknown

Where possible, reuse or extend the existing governance subject taxonomy instead of creating duplicate enums.

Isolation Rules

Bindings must be scoped by:

workspace_id
environment_id where applicable
provider_key
provider_connection_id where applicable

No binding may be used across workspaces.

Environment-specific binding is the default.

Workspace-wide binding is only allowed for explicitly workspace-level subjects.

New Core Objects

ResourceIdentity

Represents stable provider resource identity.

Must support:

  • provider key,
  • resource type,
  • provider resource ID,
  • external ID,
  • discriminator,
  • fingerprint/hash,
  • built-in/default/virtual flags,
  • tenant-owned flag.

Must not require display name as identity.

CanonicalSubjectKey

Represents TenantPilot's stable internal key for a governed subject.

Examples:

provider:{provider_key}:policy:{provider_resource_type}:{provider_resource_id}
provider:{provider_key}:builtin:{canonical_discriminator}
provider:{provider_key}:virtual-target:{canonical_discriminator}
provider:{provider_key}:foundation:{resource_type}:{provider_resource_id}

Provider-specific canonical values are supplied by adapters.

ProviderResourceDescriptor

Represents a candidate provider resource for matching/resolution.

Should contain:

  • resource identity,
  • display label,
  • subject class,
  • provider resource type,
  • support level,
  • source inventory item,
  • source policy version,
  • source operation run,
  • fingerprint/hash where available.

Audit Requirements

Every manual or operator-driven binding decision must record:

  • actor,
  • timestamp,
  • workspace,
  • environment,
  • provider,
  • subject,
  • previous decision,
  • new decision,
  • reason/note,
  • source operation run/compare where available.

Revocation must also be audited.

Automatic high-confidence canonical built-in bindings may be stored without operator note, but should remain traceable.

Acceptance Criteria

  • provider_resource_bindings exists with workspace/environment/provider isolation.
  • Only one active binding exists per scoped canonical subject unless versioning explicitly allows otherwise.
  • ResourceIdentity can represent tenant-owned, built-in, virtual, and unsupported resources.
  • CanonicalSubjectKey does not depend on display name alone.
  • Manual binding, exclusion, accepted limitation, unsupported coverage, and revocation modes are representable.
  • Audit records are emitted for manual changes.
  • No baseline compare behavior is made worse.
  • Existing baseline compare records remain readable.

Required Tests

  • Unit test: ResourceIdentity does not require display name.
  • Unit test: CanonicalSubjectKey includes provider/resource class/type.
  • Unit test: built-in and tenant-owned identities produce distinct keys.
  • Unit test: active binding uniqueness is enforced per workspace/environment/provider/canonical key.
  • Feature test: binding cannot cross workspace boundary.
  • Feature test: revoked binding is no longer active.
  • Feature test: operator note is required for manual binding/exclusion/accepted limitation.
  • Contract test: fake provider can create provider resource descriptors.

Validation Commands

cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/Baselines

Add new dedicated tests for provider resource bindings and resource identity.

Risks

  • Over-generalizing into workflow engine.
  • Creating a second taxonomy parallel to existing governance taxonomy.
  • Allowing bindings to leak across workspaces/environments.
  • Treating display names as stable keys again through the back door.

Recommendation

Implement this first.

This is the foundation required before matching, result semantics, UI, and review readiness can be fixed safely.