# 20260625_flow_visibility_all_profiles

Generalizes the **WA-001 flow-visibility workaround** (see `docs/workarounds.md`)
from the original 11-profile allow-list to **every profile-owned PermissionSet**,
so any profile can resolve pack-owned flows instead of hitting
`Flow '<name>' not found or not active`.

## Symptom

Users on the **DM**, **Sales Ops**, and **System Administrator (SF imported)**
profiles get an error when clicking **Create Quote** on an Opportunity:

> Error
> Flow 'Std_CreateQuoteFromOpportunity' not found or not active

The same failure applies to *every* pack flow trigger (Log a Call, etc.), not
just Create Quote - it is an object-level visibility gap, not a per-flow defect.

## Root cause (upstream NexusCRM#1553 / pack #2119, ledger WA-001)

The L0 RLS layer treats pack-owned `Flow` / `FlowDefinition` rows as ordinary
records. A profile that has `PermissionsRead = 1` but **not**
`PermissionsViewAllRecords = 1` on those two objects cannot see the pack flow
rows, so the standard-action dispatcher resolves the flow to nothing and returns
"not found or not active". A profile is only exempt if it carries the
`ViewAllData` god-bit (the native `System Administrator`).

`pingcap-inc/nexuscrm-pingcap-pack#2119` shipped the original mitigation
(`20260529_flow_visibility_profile_workaround`) but hardcoded **11** profile
names. That left every other migrated profile broken, and the gap has had to be
re-discovered repeatedly (Sales Ops + System Administrator (SF imported), then
DM).

## Evidence (live, read-only, prod, 2026-06-25)

Measured `ObjectPermissions` for `Flow` + `FlowDefinition` across all 50
profile-owned permsets (`IsOwnedByProfile = 1`):

| State | Count | Profiles |
|-------|-------|----------|
| `Read=1, ViewAll=1` (OK) | 12 | the 11 WA-001 names + native `System Administrator` |
| `Read=1, ViewAll=0` (**broken**) | **38** | DM, Sales Ops, System Administrator (SF imported), Legal, Management, Contract Manager, Demand Gen, CEG - Growth, GGC, Education, Marketing India, NA&EMEA SDR Lead, Outsourcing SDR, Solution Manager, PoC Profile, Read Only, Read Only-IT, IT User, Management API-Enabled, Partner Community User, Chatter*, Guest License, and the integration users |
| missing row | 0 | - every profile already has both rows |

Because every broken profile already has the `ObjectPermissions` row with
`Read=1`, this is a pure **UPDATE** (flip `ViewAllRecords -> 1`); no INSERT is
needed.

## What `001` changes

Set-based, env-agnostic, idempotent UPDATE: flips `PermissionsViewAllRecords = 1`
on `Flow` + `FlowDefinition` for **every** profile-owned permset that currently
has `Read = 1` and `ViewAll <> 1`. Matched by `ps.IsOwnedByProfile = 1` - no
hardcoded profile ids or names - so re-running is a no-op and any future migrated
profile is picked up automatically. Expected `updated_rows = 76` on first prod
apply (38 profiles x 2 objects); postcheck `row_count` must be `0`.

## Scope decision

Granting `ViewAllRecords` on `Flow` / `FlowDefinition` exposes only the flow
*registry* (which automations exist), never business records, and only to
profiles that were **already provisioned with flow Read**. The deliberate choice
here is to cover all 38 rather than re-curate an allow-list, because the
allow-list approach has now leaked the same bug three times. This supersedes the
*scope* of `20260529_flow_visibility_profile_workaround` (which remains applied;
this bundle is a strict superset and leaves its rows untouched).

## Target environments - staging AND prod

The 11-profile gap exists on both staging and prod, so both need this. Order of
operations (per the standing rule - do **not** trial against prod):

1. Read-only confirm current `ViewAll=0` count on the target env (the `001`
   precheck does this).
2. Apply to **staging**, then verify: run `099` (headline count must be `0`) and,
   as a previously-broken persona (e.g. Sales Ops), confirm **Create Quote** on an
   Opportunity no longer errors.
3. Then apply to **prod** through the gated deploy and re-run `099`.

## Verification

- `099` headline `profile_owned_flow_rows_missing_viewall` = **0**.
- `099` spot-check: DM, Sales Ops, System Administrator (SF imported) each show
  `PermissionsViewAllRecords = 1` on both `Flow` and `FlowDefinition`.
- Functional: Create Quote from an Opportunity as a formerly-broken profile
  succeeds (a real Quote with cloned line items is created).

## Revert criterion / durable fix

This is a **workaround**, tracked as WA-001. The durable fix is upstream
**NexusCRM#1553** - the RLS layer should not scope pack-owned `Flow` /
`FlowDefinition` rows as regular records (they should be visible to all who can
execute them). When #1553 lands in the deployed backend, re-test a broken
profile *without* this grant; if Create Quote still resolves, this bundle (and
WA-001) can be reverted.
