# `Profile` Repair-Path Business Permission Convergence

This document records the fifth `Profile` validation track: wiring the business-object permission convergence logic into standalone `setup repair`.

## Scope

This pass answers a remaining execution-path question after `validation-04`:

> If product or operator workflows run `setup repair` without a full `setup apply`, will the profile business-object permission drift still converge?

Before this change, the answer was effectively **no**.

## Why Another Pass Was Needed

After `validation-04`, the business-object partial-seeded reconciliation lived inside:

- `InitializePermissions`

That means the fix was reached through:

- `setup apply`
- `setup apply-packs`

But standalone `setup repair` only executed:

- discovery
- historical backfills
- compatibility fixes

It did **not** invoke the profile permission convergence logic added in `validation-04`.

For environments where `setup repair` is the operational recovery step, this left a gap:

- the codebase knew how to converge business-object profile permissions
- but the recovery entrypoint did not actually run that convergence step

## Repair Strategy

Add a dedicated `RunRepair` step that:

1. creates a headless control-plane runner
2. refreshes metadata cache
3. invokes `InitializePermissions`

Why this is appropriate:

- it reuses the same convergence logic as the normal control-plane path
- it avoids duplicating another business-object permission repair implementation
- it keeps `setup repair` aligned with the now-canonical convergence rule

## Code Change

Primary file:

- `backend/internal/controlplane/operations.go`

New repair step:

- `ReconcileProfileBusinessPermissions`

Execution order:

- after the existing setup-object backfill step
- before later compatibility backfills continue

## Local Verification Completed

The following commands were run after the repair-path change:

```bash
go test ./internal/controlplane/...
go test ./internal/features/permissions/...
go test ./internal/infrastructure/persistence/...
```

Observed result:

- all targeted packages passed

This validates:

- the new `RunRepair` step compiles in the real control-plane package
- the headless runner integration is valid
- the shared permission convergence logic still builds and passes its targeted tests

## What This Validation Does Not Yet Claim

This pass does **not** yet claim that `setup repair` has already been executed in `ci-test` or `staging` with this branch.

At this stage, the verified facts are:

- standalone repair now includes an explicit profile business-permission convergence step
- the repaired control-plane path builds and tests cleanly

Environment execution remains a later validation round.

## Environment Validation Checklist

When validating this branch in `ci-test` or `staging`, confirm the repair-path behavior explicitly:

### 1. Capture pre-repair evidence

Record:

- sampled business-object missing `ObjectPermissions`
- sampled business-object missing `FieldPermissions`
- profile(s) used for validation

### 2. Run standalone repair

Execute:

```bash
go run ./cmd/setup repair
```

### 3. Confirm repair log contains the new convergence step

Expected tracked step:

- `ReconcileProfileBusinessPermissions`

### 4. Capture post-repair evidence

Confirm that the sampled business-object permission gaps are gone after repair, without requiring a full `setup apply`.

### 5. Confirm idempotence

Run `setup repair` a second time and confirm:

- no regressions
- stable counts
- no repeated drift

## Expected Operator Impact

After this pass:

- environments using standalone `setup repair` can heal the profile business-object drift
- recovery no longer depends on running the full control-plane apply sequence
- the convergence rule is shared between the normal pack path and the standalone repair path

## Out of Scope

Still not covered by this pass:

- final staging screenshots
- machine-checkable audit / verify guardrails
- non-profile permission defects that only resemble this symptom class
