# `Profile` Setup-Object Permission Repair Checklist

This document records the second repair/validation pass for the `Profile` migration gap.

## Scope

This pass focuses on the setup-object permission chain:

`system-permission SSoT -> setup-object ObjectPermissions / FieldPermissions -> describe / User form rendering`

The concrete user-visible symptom is the `Create User` / `Edit User` experience staying incomplete even after the system-permission SSoT backfill restored `ManageUsers`.

## Mechanism

> Migrated profile-owned `PermissionSet` rows can regain `ManageUsers` in `_System_PermissionSetPermission`, but still lack `ObjectPermissions` / `FieldPermissions` rows for setup objects such as `User`, so metadata-driven forms remain under-rendered.

This repair does **not** overwrite existing OP/FP rows.

Instead, it:

- discovers setup objects from `_System_Object`
- reads each object's `RequiredWritePermission`
- checks the already-restored system-permission SSoT grants
- insert-only backfills missing `ObjectPermissions` / `FieldPermissions` rows for profile-owned permission sets

## Why this is safe

- metadata-driven: target objects come from `_System_Object`, not hardcoded tenant facts
- insert-only: existing OP/FP rows are preserved
- order-aware: it runs after `BackfillPermissionSetPermissionSSoT`
- bounded: it only targets setup objects with metadata-declared write gates

## Validation Sample

- `Profile`: `System Administrator (Salesforce)`
- `PermissionSetId`: `0PS5g000001HHVSGA4`
- Comparison reference: native bootstrap `System Administrator`

## Broken-State Evidence

Before running the new repair on `ci-test`:

| Profile | `ManageUsers` | `UserObjectRows` | `UserWritableRows` | `UserFieldRows` | `UserEditableFieldRows` |
| --- | --- | --- | --- | --- | --- |
| `AI Agent Profile` | `0` | `0` | `0` | `0` | `0` |
| `System Administrator` | `1` | `1` | `1` | `0` | `0` |
| `System Administrator (Salesforce)` | `1` | `0` | `0` | `0` | `0` |

Interpretation:

- `System Administrator (Salesforce)` already had `ManageUsers`
- but its profile-owned `PermissionSet` still had no `User` object row
- so the setup-object write gate was restored at the system-permission layer, but not at the object/field-permission layer

## Repair Action

Code change:

- `backend/internal/controlplane/packs/setup_object_permissions_backfill.go`
- wired into `backend/internal/controlplane/operations.go`

Runtime validation:

- `go test ./internal/controlplane/packs/...`
- `go test ./internal/controlplane/...`
- `go run ./cmd/setup repair` against `ci-test`

Observed repair log on `ci-test`:

- `BackfillSetupObjectPermissions`
- `objects_considered=28`
- `object_rows_inserted=1092`
- `field_rows_inserted=71915`

## After-State Evidence

After running the repaired `setup repair` on `ci-test`:

| Profile | `ManageUsers` | `UserObjectRows` | `UserWritableRows` | `UserFieldRows` | `UserEditableFieldRows` |
| --- | --- | --- | --- | --- | --- |
| `AI Agent Profile` | `0` | `1` | `0` | `208` | `17` |
| `System Administrator` | `1` | `1` | `1` | `192` | `192` |
| `System Administrator (Salesforce)` | `1` | `1` | `1` | `208` | `208` |

Interpretation:

- `System Administrator (Salesforce)` is no longer missing the `User` object row
- the profile now has writable `User` object access aligned with its restored `ManageUsers` grant
- `User` field rows were also backfilled, so metadata-driven form rendering now has the expected inputs to project a complete admin form
- non-admin profiles still stay non-writable (`AI Agent Profile` has `UserWritableRows=0`)

## Conclusion

This repair closes the second `Profile` gap for setup-object forms:

- pass 1 fixed `PermissionSet boolean -> _System_PermissionSetPermission`
- pass 2 fixes `restored system grants -> missing setup-object OP/FP rows`

Together, they move the setup/user-management path much closer to the native bootstrap admin behavior without overwriting existing permission customizations.

## Out of Scope

Still not covered by this pass:

- full-schema business-object OP/FP gap from the broader `#1806` umbrella
- browser screenshots / form-level visual evidence for this pass
- prevention work in profile-creation/bootstrap seed paths
