# C6 authority switch for NP Group — proposal for the owner's ruling

Prepared 2026-09-10 from the repository, the live Main database (read-only) and the FDR source
tree. Nothing here changes production, the sync history or any guard. It puts one decision to the
owner with the facts needed to take it, and names the work each answer implies.

## 1. Why this decision is now on the critical path

Release `20260909-175028-829c4bb` put native Argus persistence and Stage 19 matching into
production, and today's candidate `20260910-012403-4086e43` carries the credential page fix. None
of it can write a single native row for NP Group: every Argus engine refuses an owner that has
`sync_run` rows, and NP Group has 52. That rule is the sync-era authority ruling
([plan §"The sync-era authority ruling, made explicit in code"](apollo-discovery-and-plan-260826.md),
enforced in eighteen sites listed in §4 below). It is deliberate and it is correct while the FDR is
still the issuing authority. It is also the single fact that makes production, for the only real
licence, a read-only mirror.

Every recent record repeats that lifting it is "the owner's call to schedule, not a gap", and that
the 52 rows must not be deleted as a shortcut. This paper is the schedule request.

## 2. Facts on 2026-09-10

Verified today unless a source is cited.

| Fact | Value | How verified |
|---|---|---|
| `sync_run` rows on Main (NP Group) | 52: 33 `succeeded`, 11 `failed`, 8 `running` | read-only `psql` as the migrator |
| First / last sync run | 2026-08-28 00:35 UTC / last **succeeded** 2026-09-03 00:18 UTC | same |
| Orphaned `running` rows | 8, the last started 2026-09-01 17:11 UTC; they never finished and count for the guard like any other row | same |
| Register rows synced vs native | `fdchdr` 1,346 synced / 0 native; `bnkmov` 2,281 synced / 0 native | same |
| FDR source tree (`invoice-skill-build\Editor\Data`) | 307 files, newest write 2026-09-09 09:08 UTC (`wrkflw.json`); repository head 2026-09-09 "Advance registry to Stage 19 Round 6" | file system and `git log` |
| **Main is behind the FDR** | at least six days of FDR edits after the last successful sync | the two rows above |
| Argus migrations | 35 applied on Main and on Preview, including all eleven dated 2026-09-09 | `__EFMigrationsHistory_Sibyla` on both databases |
| Platform migrations | 29 on both; `/health/schema` on the production API lists the same 29 | API and both databases |
| Main/Preview parity gate | `PreviewParityTests` 10/10 pass | `dotnet test` today |
| Other licences | none; the sync targets one owner id and only NP Group is seeded | `Sibyla.Sync\SyncSupport.cs`, `db\seed\tenant1.sql` |
| Scheduled task driving the FDR pipeline on this host | none found | `Get-ScheduledTask` |

Two conclusions follow. The FDR is still being edited, so cutover cannot be "flip the switch": it
has to be the freeze-and-final-sync the runbook describes. And the schema prerequisites the
persistence-slice record listed as open (Preview-only migrations, three failing parity tests) are
now met and should be read as closed.

## 3. What C6 changes

From the [cutover runbook](discovery/11-continuous-sync-design.md) §7 and the mapping note
[§1.2](discovery/06-source-to-target-mapping.md):

1. Sibyla becomes the issuing authority: `code_counter` floors verified equal to the ledger
   maximum per table code, then `CodeIssuer` mints with `issued_by = 'apollo'`.
2. The sync-owned column guards are lifted; synced rows become Sibyla-owned.
3. Every `SyncRuns.AnyAsync` refusal stops firing for NP Group: document capture and entry,
   fiscal and bank statement intake persistence, master data, associations, catalogues and period
   closures, bank movement resolution, matching (automatic, manual and grouped), the settlement
   ledger, IBAN learning and gap detection.
4. The sync is switched to verify-only for the C7 watch window and then decommissioned (C8).

Rollback before C6 is free: unfreeze the FDR, Sibyla lost nothing. After C6 it is a documented
break-glass export of native deltas (`sync_run_id IS NULL`) back to the FDR operator.

## 4. Where the guard lives

All in `src\Sibyla.Modules.Argus.Infrastructure`: `Capture\DocumentCaptureService.cs` (two sites),
`Classification\DocumentEntryService.cs`, `Capture\FiscalIntakeEntryService.cs`,
`Capture\FiscalIntakeResolver.cs` (two), `Capture\BankStatementIntakeService.cs`,
`MasterData\MasterDataService.cs` (four), `MasterData\AssociationService.cs` (four),
`MasterData\CatalogueService.cs` (two), `Reconciliation\BankMovementResolutionService.cs`,
`Reconciliation\DocumentMatchingService.cs`, `Reconciliation\ManualMatchService.cs`,
`Reconciliation\SettlementEventService.cs` (three), `Review\ReviewDecisionEngine.cs`,
`Review\ReviewDecisionEngine.Groups.cs`, `Learning\LearningStore.cs`, `Audit\GapDetector.cs`.
The condition is the same everywhere: any `sync_run` row visible under the owner's row-level
security, regardless of status. There is no flag; the design says C6 "adds the explicit switch
record when it lifts it", and no such record or table exists yet.

## 5. Prerequisites, with today's status

| Runbook prerequisite | Status 2026-09-10 |
|---|---|
| Phase 3 hardening done | Open per the [status map](project-status-map-260904.md); the restore drill is the item that matters here |
| Previous milestone runs signed off | No sign-off record for the 33 succeeded runs |
| Rehearsal cutover on a database restore, freeze window timed | **Never performed** |
| C1–C5 (freeze, final FDR run, hash the tree, final sync, owner sign-off) | Not executed; required because the FDR moved after 2026-09-03 |
| `code_counter` floors equal ledger max | Maintained by every sync run for ledgered families; `ITMMST` is not ledgered and "must be seeded above the mirrored dictionary at cutover" (plan) — not done |
| Sync `--verify-only` mode | **Not implemented** in `Sibyla.Sync` |
| Explicit switch record | **Not implemented** |
| Break-glass delta export procedure (P3-14) | Not written |
| Main/Preview schema parity | Met today (see §2) |
| Native persistence acceptance | Reused-corpus regression passed and deployed; the owner's amendment says it does not authorize cutover by itself |
| Legacy application retirement | Done 2026-09-09; the FDR pipeline is a different thing and was not part of it |

## 6. Options

**A. Full cutover per the runbook (recommended).** Build the four missing pieces, rehearse on a
restore, then run C1–C8 with the FDR operator. This is the only option every existing ruling
already permits.

**B. Owner-ruled sync-era exception.** Lift the guard for one path only (for example fiscal intake
persistence) while the FDR keeps authority for the rest. The spec allows the owner to rule this.
It is not recommended: any code Sibyla mints beside a live FDR collides at the next sync run, which
is the exact failure the guard exists to prevent, so an exception is only safe if the sync never
runs again, and then it is a cutover without the freeze discipline.

**C. Hold.** Keep NP Group read-only; native writes only for licences with no sync history. This is
the status quo and it makes the persistence and matching work unusable for the only real licence.

**D. Delete or edit the 52 rows.** Refused by every record since 2026-09-09 and by the design:
provenance foreign keys point at `sync_run`, break-glass rollback keys off it, and deletion would
flip all eighteen engines to native with no recorded authority switch. Not an option.

## 7. Plan for option A

Stages, each closed by evidence before the next opens. Estimates are working sittings, not dates.

| Stage | Work | Exit evidence |
|---|---|---|
| 0 Ruling | The owner answers the questions in §8 | This document amended with the answers |
| 1 Build | (a) `sync_authority` switch record: table + migration under forced RLS, one row per owner with `switched_at`, `genesis_sync_run_id`, actor; every guard consults it instead of `SyncRuns.Any()` — the data-derived rule stays the default when no row exists, so nothing changes for any owner until the row is written. (b) `--verify-only` in `Sibyla.Sync`: full pipeline, report only, no writes, non-zero exit on drift. (c) `ITMMST` counter seeding above the mirrored dictionary, done inside the switch. (d) Break-glass delta export: a documented query set over `sync_run_id IS NULL` and the audit trail. | Tests RED before GREEN; the sync-era refusal tests keep passing with no switch row; parity gate green; two-reviewer round as for every slice |
| 2 Rehearsal | Restore Main into a scratch database, run C3–C6 against it end to end, time the freeze window, run the write-path smoke test (first minted code per table above the ledger maximum) | Timed transcript; scratch database dropped afterwards |
| 3 Freeze and final sync | C1–C5 with the FDR operator: announce, final FDR run, hash the `Editor\Data` tree, final `Sibyla.Sync` run on Main (and Preview), owner reviews the reconciliation report and signs the genesis run | Freeze manifest with two identical hashes 15 minutes apart; signed `sync_run` id |
| 4 Switch | Write the switch record for NP Group in one transaction with the counter verification; smoke test on production | First native document entered and audited; C6 evidence file |
| 5 Watch | Verify-only daily for the agreed window (design DN-13 says five zero-drift runs) | N consecutive zero-drift reports |
| 6 Decommission | C8 checklist: FDR scripts inventoried and disabled, workbook read-only and archived, final `Editor\Data` snapshot zipped and hashed | Checklist signed |

Stage 1 is the only engineering. Stages 3 to 6 are the owner's and the FDR operator's calendar.

## 8. Questions for the owner

| Id | Question | Recommendation |
|---|---|---|
| Q-C6-1 | Option A, B or C? | A |
| Q-C6-2 | Is the FDR still receiving edits, and who operates it? The tree changed on 2026-09-09. Cutover needs a freeze date agreed with that person. | Name the operator and a freeze week |
| Q-C6-3 | Before C5, may the 8 orphaned `running` rows and the 11 `failed` rows have their **status** set to `failed` / left as they are, so the genesis run is unambiguous? No row is deleted either way. | Leave every row untouched; the switch record names the genesis run explicitly, which is enough |
| Q-C6-4 | Is the rehearsal on a restore mandatory? The runbook says yes; it doubles as the restore drill Phase 3 still owes. | Mandatory |
| Q-C6-5 | Does the switch cover Preview's copy of NP Group too? `prepare-preview.ps1` syncs the same owner id into Preview. | Yes, in the same sitting, so tests and Preview stay level with Main |
| Q-C6-6 | Does the 2026-09-05 re-amendment of D10 ("import all the documents in the handover, including bank") change the final sync's scope? The sync already carries documents and bank in every run. | No change: the final sync is a full run as today |

## 9. What this proposal does not do

It does not lift, weaken or reinterpret any guard. It does not touch the 52 rows. It does not claim
that the reused-corpus regression is independent acceptance. It does not schedule anything: the
dates belong to the owner and the FDR operator.

Related: [C-17 decision](c17-register-gap-decision-260910.md) (the pre-assigned upload register
check is live at persistence for every native owner, and reaches NP Group only after C6);
[legacy database disposition](legacy-database-disposition-260910.md) (independent of C6).
