## Purpose

Follow-ups from the Story #1466 staging persona test run (R16 report,
2026-06-03). All findings were re-verified read-only against staging before
this bundle was authored.

The headline conclusion: **none of the 7 reported clusters is an upstream
platform bug.** Local (pack-only) runs the Credits approval end-to-end. The
staging failures all trace to hand-patched staging/prod state diverging from the
pack, or to pack content that has not re-reconciled onto staging yet.

## Target environments — staging AND prod

`20260531/007` (the patch this corrects) was applied to **both staging and prod**,
so prod's Finance/Sales Ops permsets carry the same `ViewAll=0` inconsistency. If
Credits personas are in use in prod (Phase 1 is live there), prod needs `001` too.

`001` is written env-agnostically (idempotent `UPDATE` on deterministic
`ParentId` + `SobjectType`), so it is safe to run against either env where the
`permset_credits_finance_ops_manual_20260531` / `permset_credits_sales_ops_manual_20260531`
rows exist. Order of operations: **(1)** read-only confirm the current ViewAll
values on the target env, **(2)** apply to staging + verify with a persona query,
**(3)** then apply to prod through the gated prod deploy. Per the standing rule,
do not test-or-trial against prod — confirm read-only first, deploy once.

## What this bundle DOES change (verified-safe, hand-patch-owned)

`001_credits_finance_salesops_viewall.sql` — flips `PermissionsViewAllRecords`
(Finance Ops + Sales Ops) and `PermissionsModifyAllRecords` (Sales Ops) to 1,
correcting an internal inconsistency in `20260531/007`. 007 set them to 0 while
its own permset Descriptions and the design doc both call for ViewAll. This is
the only genuinely hand-patch-owned fix, so it is the only SQL here.

Post-deploy verification: as a Finance Ops / Sales Ops persona, query Credits
not owned by the persona and confirm COUNT > 0.

## What this bundle deliberately does NOT hand-SQL

These are NOT staging-only state; the pack already carries the correct content.
Hand-SQL'ing them would re-introduce the very pack-vs-patch drift that caused the
findings. The fix is to **re-reconcile / re-deploy the pack to staging**, not to
patch around it.

- **`Credits__VR_Opp_Matches_Account` missing on staging (cluster
  `PACK-1466-missing-vr`).** The VR is in the pack
  (`validation/standard_validation_rules.json`, merged in #2292) and in the final
  merged pack. Staging has only 2 of the 3 Credits VRs — a partial-reconcile gap
  (same class as the field-reconcile issue tracked separately). Fix: re-reconcile
  the pack validation rules onto staging.

- **`Credits.Name` blank on every record, including brand-new ones (cluster
  `PACK-1466-credits-name-blank`).** The staging active flow version
  `Credits_Prefill_Snapshot_Fields` (`flowver_std_..._v1`) stamps
  `Account_Name__c`/`Opportunity_Name__c` but is MISSING the `$Record.Name`
  assignment that the pack source flow has (`Credits_Name_Value` -> `$Record.Name`).
  Same flow-version identity, stale content — a pack-content-drift / source-identity
  reconcile gap. Fix: force the flow to re-apply from the pack (re-reconcile;
  hash-neutral / SourceRevision bump as used elsewhere for this class).

## `approve-broken` — local reproduction done; ProcessAction hypothesis REFUTED

A first hypothesis (in an earlier revision of this README) blamed the 007
`FieldUpdate` ProcessActions conflicting with the pack lifecycle flow. **Local
reproduction refuted that.**

Repro (2026-06-03): replayed `20260531/007` onto a local DB — local then carries
the identical hand-patched approval `ProcessDefinition` + 3 `ProcessNode`s + 4
`ProcessAction`s + the step-criteria `Metadata` blob. Created a qualifying
Credits, Submit, Approve:

- **Approve SUCCEEDED** (`success=true`, status -> Approved, lifecycle -> Active).
  With the ProcessActions present. So the ProcessActions do NOT cause the staging
  failure — hypothesis dead. (This is exactly why reproducing first matters: a
  blind "drop ProcessActions" staging patch would have been wrong.)
- 007 carries the **full** approval definition including the step-criteria
  `Metadata` JSON (not "missing config").

So the staging `success=false / "An unexpected error occurred"` is NOT reproduced
by a faithful local replay of the hand patch.

**Every Credits approval definition was then verified byte-identical between staging
(read-only) and local:**
  - procdef `Metadata` step-criteria — identical (Finance: `Initial_Credits__c > 1000`
    AND `Requires_Finance_Approval__c equals "true"`; BG: `> 3000`). No drift.
  - the 4 `ProcessAction`s (`FieldUpdate` on `Approval_Status__c`) — identical.
  - the `Credits_Lifecycle_On_Approval_Decision` flow (RecordBeforeSave, decision ->
    assign Lifecycle) — identical to pack source. No drift.

And local, with that identical definition, **succeeds at both single-step approval
and multi-step advance** (amount 5000 -> Step 1 cleanly advances to the BG step).

Conclusion: `approve-broken` is **not** a content/config/pack difference and **not**
an upstream-platform bug in general (the same code path + same definitions succeed
locally). It is a **data-dependent 500 inside `approval_service.go processAction`**,
and the client-facing `"An unexpected error occurred"` is the generic wrapper
(`recovery.go` / `apierr.go`) that **hides the real internal error**. The mechanism
hypotheses I gave earlier (ProcessAction conflict, Metadata drift, flow drift) are
all **ruled out** by the verification above.

Definitive next step — needs something the read-only API does not expose:
  1. **the unwrapped server error / stack** from the staging backend around
     `approval_service.go` Approve (the real message behind the generic 500), and/or
  2. confirm the **staging backend build ref** is not stale vs local upstream `main`
     (if staging runs an older runtime with an approval bug already fixed in `main`,
     identical definitions would throw on staging but pass locally — an ops check).

Only with the unwrapped error should a fix be authored. Do NOT ship a speculative
approval change to staging.

### Side finding from the repro — parent Finance gate silently never fires (REAL, separate)

The Step 2 (Finance) criteria in the 007 `Metadata` is
`Requires_Finance_Approval__c equals "true"`. Locally, a Credits with
`Initial_Credits__c = 2500` (> 1000) and the flag set **skipped Finance entirely**
and went straight to Approved. Cause: the flag is a `tinyint(1)` and the engine
string-compares the stored value `1` against `"true"` -> not equal -> AND-gate
false -> Finance bypassed. This is the **same class as #2305** (boolean vs
`equals "true"` in approval stepCriteria), which fixed it for the Topup metadata
with the comma ANY-match `"true,1"` — **but the parent PoC Credits metadata never
got that fix**. Net effect: the Finance approval step is silently skipped for every
parent Credits, a gating hole.

Recommended fix (mirrors #2305): change the Finance criteria value `"true"` ->
`"true,1"` in `procdef_credits_poc_approval_manual_20260531`.Metadata.

**DEFERRED — not needed now.** Per the 2026-06-03 launch decision (design §7.0,
Option B), the Finance step is **dormant at launch**: the flag is set by nobody and
hidden from all layouts, so the gate does not run and this silent-skip has no live
effect. The `"true,1"` fix belongs to the day the per-region budget gate is
re-enabled (A-blueprint in §7.0) — apply it then and verify live on a
metadata-reloading backend. (Today the silent-skip would actually be a convenient
no-op; but we are not relying on a bug — the gate is explicitly off by hiding the
flag.) Best folded into migrating the approval def into the pack.

## Architectural root cause (the real fix)

The Credits **approval definition and permission sets live in hand-written SQL
patches**, not in the pack — even though `watchdog/seeds/catalog/credits-core.yaml`
documents them as shipping "via the deployed pack." That divergence is the common
root of the approve-broken, finops-edit, and salesops-no-viewall clusters: local
(pack-only) cannot see or test the hand-patched logic that actually runs on
staging/prod. Long-term fix: migrate the Credits approval ProcessDefinition /
ProcessNodes / ProcessActions and the Credits permission matrix into the pack so a
single source is built, locally tested, and reconciled everywhere.

## "Who arms the Finance flag" — RESOLVED by the dormant-Finance decision (§7.0)

`PACK-1466-finops-edit` reported "Finance Ops can never arm the Finance step" (007
gives Finance Ops object Edit=0 but FLS Edit=1 on the flag — a contradiction). This
is now **moot**: per the 2026-06-03 launch decision (design §7.0, Option B), the
Finance gate is **dormant** — the flag is hidden from all layouts and set by nobody
at launch. So no one needs edit on it, and the vestigial 007 FLS-Edit grant is
harmless (the field does not render anywhere). When the per-region budget gate is
re-enabled (A-blueprint), the flag is stamped from a `Region_All__c` toggle at
submit time, not armed per record — so the "who arms it" question does not return.
No permission SQL is needed for this.
