# Agent prompt — v6 · finish S1

**Repo:** `GOTT.Sibyla` · **Runtime baseline:** `1b4600d` (merge of `s1/tax-identifier-materialization`, MR `!122`, source `58ecd44`; this is the latest runtime change — the **primary tax identifier materialized from seed evidence** — and it is the verified runtime merge this records update is prepared from. It is an **immutable runtime merge and baseline**, not a claim about the current Git tip of `main`, which docs-only merges advance without changing runtime.)
**Plan:** `docs/V6.md` · **Structure:** `docs/master-data-and-ui-plan.md` rev. 15 (plan **approved 2026-08-11**; revision current 2026-08-20)
**State:** `docs/STATE.md` · **Backlog:** `docs/project-todo-v6.md` rev. 42 · **Method:** `AGENTS.md`

Read `docs/STATE.md` and `docs/master-data-and-ui-plan.md` §0 and §3 first. Do not re-derive
what they say. Nothing below reopens M-D1…M-D7, the five source-semantics decisions in
`p1-0-schema-mapping.md` §3, or **P2-2, which is closed** — ITMCLS, MNGACC and COCACC stay
separate and `ReferenceValue` is never created.

**This prompt supersedes rev 26** (rev 27, 2026-08-20). **Runtime baseline is now `1b4600d`**
(`!122`, the tax-identifier materialization; `!121` fixed the demonstration's mojibake before
it). **Open data decision O-6** (STATE `## Open`): two duplicate-fiscal groups in the source
hold the materialization back by design — resolve before any official `database update`. Among the `g`/`h` remainders
only **g3** (on O-1) and the S2-deferred DOCEFL editor stay open. **The CTT demonstration is
prepared and waits only for the human session**: the demo database reached Latest through the
full S1.5 sequence with the real source (reconciliation 115/115), the seeder replay on Latest
is idempotent, and the real CTT row (`EC000007`, three mapped items) exists; record the date,
who was shown, and the witness in `STATE.md` when it happens — S1 closes then. See STATE for
the fiscal-identifier policy and the post-collapse ingestion gap recorded for `S2-6`/`S2-7`. The CI-minutes quota ran out on
2026-08-20 (`ci_quota_exceeded` on `!110`'s post-merge pipeline **2775612809**) and paused the
V6-O1 gate; compute minutes were added the same day and that pipeline was retried **green**, so
the gate is open again. **Every buildable `S1-9` piece is delivered** — `!112` closed `e` and
`!113` closed `f`; what remains in S1 is the demonstrated "CTT" exit and the Miguel-gated
`g`/`h` remainders. S1 seeding, all of S1.5 (MR `!59`),
`S1-3a` (`!62`), `S1-9a` (`!63`), `S1-9b` (`!64`), **all six `S1-9c` descriptor screens** —
the code lists (`!65`, `!66`, `!69`) and the 2026-08-20 remainder **EXCRAT** (`!100`, with the
missing-rates panel), **ITMALS** (`!101`, first `GlobalOrActiveCompany` grid) and **ENTALS**
(`!102`, surfacing `HumanOwned`) — the whole of `S1-6a` (`!70`–`!72`), the **read-only** Entity
360 Identity shell
(`!74`), the **governed Identity/ENTMST write-service slice** (`!79`), the **governed Entity 360
Tax identifiers slice** (`!82`), the **governed Entity 360 Roles slice** (`!84`), the
**read-only Entity 360 Aliases slice** (`!86`), the **governed Entity 360 Aliases/ENTALS write
slice** (`!89`), the **governed Entity 360 Banking slice** (`!91`), the **governed Entity 360
Items slice** (`!93`) and the three **read surfaces** — **Documents** (`!96`), **Balances**
(`!97`) and **Audit** (`!98`) — are merged; **S2-15 phase 1** — the Invoice Skill reconciliation
matrix — landed docs-only (`!94`, `docs/invoice-skill-reconciliation-matrix.md`); the
**read-only DOCEFL flag-rules catalogue** (`!104`), the **governed DOCTYP presentation
write** (`!105`, `S1-9g` slice 1 — LabelPt/LabelEn/SortOrder only), the **`S1-9i` Companies
entity-half repoint** (`!107`), the three **`S1-9e` slices** (`!109`/`!110`/`!112`) and the
**`S1-9f` SNC tree** (`!113`) are merged.
**Tasks 0, 1 and 2 are done, all eleven Task 3 slices have landed — every Entity 360 tab is
built — and every buildable Task 4 piece is done: `c`, `e`, `f`, `i`, the `h` first cut and
the `g` presentation slice. What remains is not construction I start alone: the demonstrated
"CTT" exit (Task 3), `g2` (the IsActive offer toggle — assessed per slice under the stop list,
see `docs/s1-gated-editors-proposal.md`), `g3` (blocked on **O-1**, Luís) and the DOCEFL editor
(**formally deferred to S2**, when documents exist for its pattern tester; **O-4** stays
Miguel's).** S1.5 is complete —
nothing in it is to be repeated or "verified again" beyond reading its records.

---

## Where things stand

Merged to `origin/main` since MR `!59` (2026-08-15), in order. Pipeline ids are the authenticated
MR head pipelines; every one listed was read from GitLab and every one succeeded.

| Merge | MR | Pipeline | What it landed |
|---|---|---|---|
| `d959b8b` | `!62` | 2763137497 | **S1-3a** — item-master consolidation. Migration `20260815142000_S13aItemMasterConsolidation`: ITMMST gains `NormalizedItemDesc`/`IsActive`, `IntegrationProductPlKeyMapping` retired, `IntegrationProductBinding` repointed to `ITMMST.ItemCode`; Cegid/Moloni writers and endpoints updated; 1,072-line disposable migration suite |
| `dbf1a50` | `!63` | 2763220529 | **S1-9a** — module navigation shell: numbered pipeline nav, module switcher shell, and the four §4 route moves as 301s in `LegacyPageRedirects` (`/master/entities` · `/intake/upload` · `/review/queue` · `/admin/document-types`) |
| `c5d783b` | `!64` | 2764012228 | **S1-9b** — generic `<ReferenceGrid TEntity,TKey>`: descriptor contracts (columns, search, natural key, policies, validation), sort/filter/paging, optimistic concurrency on `Version`, deactivate-not-delete, `ReferenceGridState`, ~2,400 lines of tests |
| `def45d8` | `!65` | 2765893231 | **S1-9c (1/3)** — ITMCLS read-only descriptor screen at `/{c}/master/item-classes`, `sibyla.financial-operations` |
| `703e674` | `!66` | 2766649380 | **S1-9c (2/3)** — MNGACC read-only descriptor screen at `/{c}/master/accounts/mng` (+ metadata alignment `d8c09dd`) |
| `7ad42e6` | `!67` | 2766834732 | Docs only — S1 state and flow organigram refresh (source `2d8f224`) |
| `5f3389d` | `!68` | 2766897829 | Docs only — the `!62`–`!66` merge pipeline ids recorded (source `1a327a2`), closing Task 0 |
| `edf61fb` | `!69` | 2767014671 | **S1-9c (3/3)** — COCACC read-only descriptor screen at `/{c}/master/accounts/cost-centres` (source `c0f7be2`) |
| `b25d178` | `!70` | 2767296596 | **S1-6a step 1** — `20260817120000_S1DocumentTypePresentationData` copies `LabelPt`/`LabelEn`/`SortOrder`/`IsActive` from `DocumentTypeSetting` onto DOCTYP (source `62d1bed`) |
| `e96cb06` | `!71` | 2767775709 | **S1-6a step 2** — document types routed through DOCTYP: `DocumentTypeRoutingService` replaces enum reads in intake, extraction, review, integration and the Moloni writers (source `8392c0d`) |
| `1f47449` | `!72` | 2768548294 | **S1-6a step 3** — `DocumentTypeSetting` dropped (`20260818120000_S1DocumentTypeSettingsDrop`), `FinancialDocumentType` retired, `DocumentTypeSettings.razor` rewritten onto a read-only DOCTYP catalogue with a PT/EN verbal routing preview (source `0062a35`) |
| `7a1e8eb` | `!73` | 2768788874 | Docs only — S1 reconciled after the DOCTYP cutover (source `6d4cf8f`). **No runtime behaviour shipped in it** |
| `cdb26c5` | `!74` | 2769319314 | **S1-9d slice 1** — Entity 360 shell + **read-only** Identity tab over merged ENTMST at `/{c}/master/entities` (source `e7f46c9`). Canonical ENTMST list/detail, PostgreSQL search and paging, `EntityCode`/`CodeName` from `ExternalIdentity`, name, fiscal number, country tri-state, currency, Role, Status, Origin, RelatedParty + Kind, external identities, honest placeholders for the unbuilt tabs, service-side authorization, a test proving the read path writes no audit rows. **No migration, no snapshot, no new write path**; the pre-existing supplier Update/Verify/Merge stayed supplier-scoped |
| `8d924db` | `!79` | 2770706234 | **S1-9d slice 2** — governed Identity/ENTMST write-service pattern: service-side `ClaimsPrincipal` authorization (`Administrator` required for `InternalCompany`), the exact governed writable field set with permanent codes and every field outside that set staying preserved and read-only, localized PT/EN validation and error copy, a before/after `AuditEvent` appended inside the same transaction as the mutation, optimistic concurrency on PostgreSQL `xmin` (no speculative `Version` column, no migration), transaction ownership/savepoints with deny-by-default handling of unsafe caller-owned `ChangeTracker` state, and PostgreSQL transaction-level serialization for identity/role authorization races (source `03180d1d`) |
| `3fb806b` | `!82` | 2771182592 | **S1-9d slice 3** — governed Entity 360 **Tax identifiers**: an accessible PT/EN Tax identifiers tab, governed 1:N `EntityTaxIdentifier` mutations plus the atomic `ENTMST.FiscalNo` primary projection, service-side `ClaimsPrincipal` authorization, permanent fields not writable, a before/after audit write in the same transaction, `xmin` optimistic concurrency, caller-transaction/savepoint and dirty-tracker deny-by-default, duplicate/primary/race handling, a current/submitted reload-and-reapply conflict UI, and supplier/Identity compatibility preserved. Additive migration `20260819030442_S19dEntityTaxIdentifierInvariants` — no destructive repair or backfill (source `2e9732e`) |
| `2c7eab4` | `!84` | 2771963044 | **S1-9d slice 4** — governed Entity 360 **Roles**: an accessible PT/EN Roles tab, Supplier/Customer add / deactivate / explicit reactivate preserving the permanent assignment and its verification evidence, `InternalCompany` read-only, `ENTMST.Role` untouched, verification read-only, one `EntityRoleAssignment` mutation seam used by Entity360, `BusinessEntityService` and Cegid, automation still refusing inactive roles, service-side Admin/Finance/Accounting authorization with `Administrator` required for active `InternalCompany` entities, parent `xmin`, advisory locking, same-transaction audit, savepoints, dirty-tracker deny-by-default, a current/submitted reload-and-reapply conflict UI, and merge into an inactive destination role failing closed before repointing. Additive migration `20260819082319_S19dEntityRoleAssignmentInvariants` — no repair or backfill (source `b9b332b`) |
| `c1cec04` | `!86` | 2772364485 | **S1-9d slice 5** — **read-only** Entity 360 **Aliases**: an accessible PT/EN Aliases tab over ENTALS at the unchanged route, following the Identity precedent of a read slice before a write slice; rows served only for canonical (non-merged) ENTMST entities; PostgreSQL-backed paging in a deterministic order (normalised alias, then scope, then `ALCode`); scope shown explicitly — an unscoped alias renders as "all companies" in PT/EN and is never a blank field; service-side Administrator/Finance/Accounting read authorization. **No write path.** Migration `20260819111951_S19dEntityAliasesReadModel` has an empty `Up`/`Down` — EF model-mapping alignment only, no schema change (source `d2064e8`) |
| `35ca2e7` | `!89` | 2773586157 | **S1-9d slice 6** — **governed** Entity 360 **Aliases/ENTALS write**: update-only mutation of aliases that already exist, no creation and no deletion; `Alias` and the **explicit** scope are the writable fields, while `ALCode`, `EntityId`, the generated `NormalizedAlias`, `CodeName` and `Flag` stay read-only; service-side authorization for Administrator / Finance / Accounting with an active company required; `xmin` optimistic concurrency; a before/after `AuditEvent` inside the same transaction as the mutation; a current/submitted conflict UI rather than a silent overwrite; **one ENTALS update seam**, which marks a successful human edit durably `HumanOwned`; and a seeder lock order that preserves human `Alias` and scope while still synchronizing source evidence. Additive migration `20260819144205_S19dEntityAliasWriteInvariants` — a count-only preflight, `CK_ENTALS_Alias_NonBlank` and a `HumanOwned` boolean defaulting to false, with no repair, no backfill and no code issuance (source `a6b70fc`) |

Object names for the recent merged sequence — `!67`–`!77` plus `!79`, `!82`, `!84`, `!86` and `!89` — recorded exactly: `!67` source
`2d8f2244d761891d3b8472f893b27c9699a98453` → merge `7ad42e6839cbf9f6b708dddfa5992795e8b0079b` ·
`!68` source `1a327a24512b848b6e8e9ecf7c322297f16a4c62` → merge
`5f3389d24221a1a2a50e3875d5d7f28e72704153` · `!69` source
`c0f7be2d6ed59ca7e1a3560ac03303012d2416e9` → merge `edf61fb180508314adf09265f419b727bacb2c1e` ·
`!70` source `62d1bedbc17963bbb8d92a92fa554a792b99db1e` → merge
`b25d178bc6ea7da769f9fc2fbdc5674fc0e2489a` · `!71` source
`8392c0da4377d31737bfc246d956d910dfe866f8` → merge `e96cb06ffbb0a29da57e4b2a60f8cb3d572eb40f` ·
`!72` source `0062a35b1f64dba3fbfe97f080b97224a103a486` → merge
`1f4744998f6db97affdbeac7ff5374be5d6f1e09` · `!73` source
`6d4cf8fb27e8728be6dd52ed4c4dcd0fd6139f47` → merge
`7a1e8eb2c3bb2f7f264d9071785432da0736143f` · `!74` source
`e7f46c9ce596f1f025b7046ec0e084dcdac3974d` → merge
`cdb26c5b7abd48b8fc7db9c5c28178a244fe0125` · `!75` source
`48bf62ca66457bf9cca3c9dc5fc49e7f0fba6e93` → merge `4aff695bfb15d1a92069798394293d7dd82d7a65`;
`!75` is docs-only (it recorded the `!74` shell) and its pipeline ids have since been read from
GitLab: MR pipeline **2769830454** and post-merge `main` pipeline **2769833799**, both success.
Two docs-only merges followed it, and
neither shipped runtime behaviour: `!76` (*docs: refresh S1 state and flow v16*) source
`d449f87551dd00c0091d75a95551430ed43e5c2e` → merge `0312db6a62ebc6d79b94d5f23ea433e6da0107bb`,
merged 2026-08-18T16:50:56.496Z on green pipeline 2769962049; and `!77` (*docs: record verified S0
intake principals*) source `fbef709a831dec85e1b06809ce25de8e4e993ed5` → merge
`917f81e719b3b2df3c3922c0bcc6be9108175467`, merged 2026-08-18T17:52:33.902Z on green pipeline
2770083626. `!77` recorded the verified channel-intake client
and principals; it did **not** itself perform the GD-1 E2E. `!77` was the `main` tip until `!79`
(below) landed. `!73` was merged by
GitLab user `gottsolutions.net` at 2026-08-18T10:44:44.377Z on green pipeline 2768788874. `!74`
([MR 74](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/74), *feat(s1):
add Entity 360 identity read shell*) was merged by GitLab user `gottsolutions.net` at
2026-08-18T14:15:36.254Z on green pipeline 2769319314. Local gates reported in the `!74` merge
request description: Debug and Release builds 0 warnings / 0 errors · Release suite 1534/1534 ·
`FdrDatabase` 244/244 · `PartyCollapseContract` 38/38 · `P11aDatabase` 61/61 · pending-model check
clean. **`!79`**
([MR 79](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/79), *S1-9d
slice 2 — governed Identity/ENTMST write service*) source
`03180d1dc64f14231c44bed406ee423c35889003` → merge `8d924db618357570b8d7d64b0e0c7ce3ed84333d` was
the latest runtime change until `!82`, merged 2026-08-18T23:05:41.472Z on green head pipeline
**2770706234**.
The first pipeline on that MR failed in the `PartyCollapseContract` source/baseline contract; it
was fixed forward without weakening that contract, and the final MR pipeline succeeded. Local
final evidence: solution build 0 warnings / 0 errors, focused tests 102/102, the
disposable-PostgreSQL Entity 360 tests 8/8, full suite 1567/1567, no pending model changes — all
observed 2026-08-18, none an acceptance criterion. Two docs-only merge requests followed `!79` and
changed no runtime behaviour: `!80` (*docs: reconcile S1-9d governed identity writes*) and `!81`
(*docs: distinguish S1 runtime baseline from Git tip*). **`!82`**
([MR 82](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/82), *S1-9d
slice 3 — governed Entity 360 tax identifiers*) source
`2e9732eb6ec43d745e8d199446e67a4068a41a1c` → merge `3fb806be571ea4a9c0a1c7e748a01d122b6d39bd` was
the latest runtime change until `!84`, **merged**
2026-08-19T04:40:56.137Z. It touched **21 files — 12 production/runtime paths under `src/` and 9
test paths under `tests/`**. A docs-only merge recording that delivery followed it — merge
`0b031c5`, no runtime behaviour. **`!84`**
([MR 84](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/84), the `S1-9d`
slice 4 governed Entity 360 Roles merge request) source
`b9b332b6674848c1a247ba0368610e3bbe30fbbe` → merge `2c7eab4d8a42ab5b5b5ad5c026096556852fb315` was
the latest runtime change until `!86` — **merged** 2026-08-19T10:17:17.49Z. It touched
**24 files — 13 production/runtime paths under `src/` and 11 test paths under `tests/`**. One
docs-only merge followed it and changed no runtime behaviour: `!85`, the **`S1-9d` Roles delivery
records**, source `97bbb7c53ce73c3246dc4778f5deb62aec7e8b5a` → merge
`ff8773e141da4cbd489236a5120bc3909c8305d1`. `!85` is **not** the flow-v17 refresh; that is `!87`,
below. **`!86`**
([MR 86](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/86), the `S1-9d`
slice 5 read-only Entity 360 Aliases merge request) source
`d2064e82aeb42579d4c6e3fc10bd5e1b43ef0dec` → merge
`c1cec047a706f31b4e4bfc614b3604d1c3ebd567` was the latest runtime change until `!89` —
**merged** 2026-08-19T12:26:35Z. Two docs-only merge requests landed **after** `!86` and
changed no runtime behaviour: **`!87`** (*docs: refresh S1 state and flow v17*) source
`52c05ae1ce03a6b78c43d0ab45c7dead560a794e` → merge
`68327e8647baf63a796db6fa6dd9a0c8d61bb631`, and **`!88`** (*docs: record S1-9d Aliases delivery*)
source `41c3c0b767de925857fdf06e066f58ad8b09fb91` → merge
`44de3a42af6b7bce543bf466ec8bd9c2849a6c20`. **`!89`**
([MR 89](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/89), the `S1-9d`
slice 6 governed Entity 360 Aliases/ENTALS write merge request) source
`a6b70fc2987bf274b7304d44032c2ff55a9b0c5c` → merge
`35ca2e7016a629292c2a084fe22a4692d74438ba` is the latest runtime change and the verified runtime
merge this records update is prepared from — an **immutable runtime merge and baseline**, not a
claim about the current Git tip of `main`, which docs-only merges advance without changing
runtime — **merged** 2026-08-19T17:42:38.385Z. It touched **26 files — 14 production/runtime
paths under `src/` and 12 test paths under `tests/`**. The order is `!84` → `!85` → `!86` →
`!87` → `!88` → `!89`: the flow-v17 refresh came **after** the read-only Aliases slice, not
before it, and neither docs-only merge moved the runtime baseline, which advanced from `c1cec04`
to `35ca2e7` only when `!89` landed. Route
unchanged for every slice above: `/{c}/master/entities`.

**What is a green pipeline, and what is only a local observation — for `!82`.** The gate is
GitLab, not the host. MR head pipeline **2771182592** succeeded on exactly source
`2e9732eb6ec43d745e8d199446e67a4068a41a1c`, and the post-merge `main` pipeline **2771203526**
succeeded on exactly merge `3fb806be571ea4a9c0a1c7e748a01d122b6d39bd`, its jobs `build-test`
**15973204170**, `p11a-database-tests` **15973204171** and `fdr-database-tests` **15973204172** all
success. Separately, and **not** the gate, the local final evidence measured on that exact source
candidate: Release non-incremental build 0 warnings / 0 errors · default suite 1592/1592 ·
`FdrDatabase` 278/278 · `PartyCollapseContract` 38/38 · `P11aDatabase` 61/61 · EF reported no
pending model changes · a fresh adversarial review returned ACCEPT. Those are observations on a
date, never acceptance criteria, and they are not what "tests green" means.

**What is a green pipeline, and what is only a local observation — for `!84`.** The gate is
GitLab, not the host. MR head pipeline **2771963044** succeeded on exactly source
`b9b332b6674848c1a247ba0368610e3bbe30fbbe`, its jobs `build-test` **15978432659**,
`p11a-database-tests` **15978432660** and `fdr-database-tests` **15978432661** all success; and the
post-merge `main` pipeline **2772015854** succeeded on exactly merge
`2c7eab4d8a42ab5b5b5ad5c026096556852fb315`, its jobs `build-test` **15978791686**,
`p11a-database-tests` **15978791687** and `fdr-database-tests` **15978791688** all success.
Separately, and **not** the gate, the local final evidence measured on that exact source candidate:
Release non-incremental build 0 warnings / 0 errors · default suite 1607/1607 · `FdrDatabase`
293/293 · `PartyCollapseContract` 38/38 · `P11aDatabase` 61/61 · EF reported no pending model
changes · a final fresh Claude review returned ACCEPT. Those are observations on a date, never
acceptance criteria, and they are not what "tests green" means.

**What is a green pipeline — for `!86`.** The gate is GitLab, not the host. MR head pipeline
**2772364485** succeeded on exactly source `d2064e82aeb42579d4c6e3fc10bd5e1b43ef0dec`, and the
post-merge `main` pipeline **2772402931** succeeded on exactly merge
`c1cec047a706f31b4e4bfc614b3604d1c3ebd567`. Job ids for this pair are not recorded here; read them
from GitLab if they are needed, do not invent them. Any local figures for this slice are
observations on a date, never acceptance criteria.

**What is a green pipeline, and what is only a local observation — for `!89`.** The gate is
GitLab, not the host. MR head pipeline **2773586157** succeeded on exactly source
`a6b70fc2987bf274b7304d44032c2ff55a9b0c5c`, and the post-merge `main` pipeline **2773640192**
succeeded on exactly merge `35ca2e7016a629292c2a084fe22a4692d74438ba`, its jobs `build-test`
**15990486347**, `p11a-database-tests` **15990486348** and `fdr-database-tests` **15990486349** all
success. Separately, and **not** the gate, the local evidence measured on that exact source
candidate: Release build 0 warnings / 0 errors · default suite **1660/1660** · `FdrDatabase`
**305/305** · a final fresh review returned ACCEPT. Those are observations on a date, never
acceptance criteria, and they are not what "tests green" means.

**The `!82` migration, and why it is not stop-list work.**
`20260819030442_S19dEntityTaxIdentifierInvariants` is **additive**: it adds four CHECK constraints
and two unique indexes to `EntityTaxIdentifiers` — one primary per entity, and fiscal-identity
uniqueness. It performs **no destructive repair and no backfill**; its preflights are deterministic
and **count-only**, raising with a violation count and never a row value, so a database that would
violate an invariant fails closed instead of being silently mutated. `Down` drops exactly what `Up`
added, and `Up`/`Down`/`Up` plus the pending-model gate were proven before merge.

**The `!84` migration, and why it is not stop-list work.**
`20260819082319_S19dEntityRoleAssignmentInvariants` is **additive**: **six count-only preflights**
and **five CHECK constraints**. It performs **no repair and no backfill**, alters **no index**,
writes **nothing to `ENTMST.Role`** and makes **no seeder write**, so a database that would violate
an invariant fails closed instead of being silently mutated. `Up`/`Down`/`Up` and the pending-model
gate were proven before merge.

**The `!86` migration, and why it is not stop-list work.**
`20260819111951_S19dEntityAliasesReadModel` has an **empty `Up` and an empty `Down`**: it is EF
model-mapping alignment only, with **no schema change**, no data change and no backfill.

**The `!89` migration, and why it is not stop-list work.**
`20260819144205_S19dEntityAliasWriteInvariants` is **additive**: one deterministic **count-only**
preflight, the `CK_ENTALS_Alias_NonBlank` check constraint, and a `HumanOwned` boolean column
defaulting to false. It performs **no repair, no backfill and no permanent code issuance** — no
`ALCode` is ever issued by this slice — so a database that would violate the invariant fails
closed instead of being silently mutated. `Down` drops exactly what `Up` added.

- **S0 is closed — 8/8.** `S0-4` and `S0-5` closed **2026-08-18**: the GD-1 channel-intake E2E
  rerun ran through `/api/channel-intake/v1` with the verified dedicated client and the nine steps
  are marked in `docs/STATE.md` — steps 1, 3, 6 and 9 **work** (9 for fiscal GD-1), 2 and 4
  **broken** on unresolved company / counterparty / direction, 5 and 7 **missing**, and 8 **not
  reached** because outbound integrations were deliberately disabled. Nothing in S0 is open and
  nothing in it is to be rerun; read `docs/STATE.md` for the detail rather than re-deriving it.
- **Open in S1:** the `S1-9d` exit
  demonstration and the gated `g`/`h` remainders — **every buildable `S1-9` piece is
  delivered**: the `S1-9c` remainder closed
  2026-08-20 (`!100`/`!101`/`!102`), the DOCEFL read catalogue landed (`!104`), the DOCTYP
  presentation write landed (`!105`), the `S1-9i` Companies repoint landed (`!107`), the three
  `S1-9e` slices landed — the ITMMST item master (`!109`, MR pipeline **2775459223**,
  post-merge **2775503263** success), the entity-item matrix with the classification queue
  (`!110`, MR head pipeline **2775569220** success; post-merge **2775612809** retried green
  after the quota top-up) and the entity-banking catalogue (`!112`, MR pipeline **2775662815**,
  post-merge **2775718587** success) — and the `S1-9f` SNC tree landed (`!113`, MR pipeline
  **2775760116**, post-merge **2775800133** success); per the corrected stop-list framing in
  `docs/s1-gated-editors-proposal.md`: **g2** (the IsActive offer toggle) proceeds through the
  normal flow with its assessment in the MR, **g3** (routing columns) waits on **O-1** (Luís),
  and the **DOCEFL editor is formally deferred to S2** (O-4 stays Miguel's). `S1-9d` Entity 360 is still the exit criterion; all eleven slices
  are done — Identity shell (`!74`), governed Identity/ENTMST writes (`!79`), governed **Tax
  identifiers** (`!82`), governed **Roles** (`!84`), read-only **Aliases** (`!86`) and its
  governed write (`!89`), governed **Banking** (`!91`), governed **Items** (`!93`), and the read
  surfaces **Documents** (`!96`), **Balances** (`!97`) and **Audit** (`!98`) — so every tab is
  built and what remains is the demonstration.
  **`S1-9d` is not done and S1 is not closed.**
- **`S1-9g` is partly landed, and the distinction matters.** `!72` had to rewrite
  `DocumentTypeSettings.razor` so it did not point at a dropped table — the DOCTYP *read-only*
  catalogue and its routing preview were the `S1-9g` first cut — and `!105` added the **governed
  presentation write** (LabelPt/LabelEn/SortOrder only). What remains in `S1-9g` (Task 4) is
  **g2, the `IsActive` offer toggle** (normal flow, assessed in its MR per
  `docs/s1-gated-editors-proposal.md`) and **g3, the routing columns** (on the O-1 decision).
- The four new **reference** surfaces (ITMCLS, MNGACC, COCACC and the DOCTYP catalogue) are
  **read-only**: `ReferencePolicies.Write` is wired in the contracts but no screen exercises that
  write path yet. Separately, **five Entity 360 tabs** now have a **governed write path**. `!79`
  introduced the Identity/ENTMST write service — service-side `ClaimsPrincipal`
  authorization (`Administrator` required for `InternalCompany`), the exact governed writable
  field set shaped against the live code, permanent codes and every field outside that set staying
  preserved and read-only, PT/EN validation and error copy, a before/after `AuditEvent` inside the
  same transaction as the mutation, and optimistic concurrency on PostgreSQL `xmin` — no
  speculative `Version` column, no migration. `!82` then reused that pattern for **Tax
  identifiers**: governed 1:N `EntityTaxIdentifier` mutations together with the atomic
  `ENTMST.FiscalNo` primary projection, the same service-side authorization, permanent fields not
  writable, the same-transaction before/after audit write, `xmin` concurrency, caller
  transaction/savepoint and dirty-tracker deny-by-default, duplicate/primary/race handling, and a
  current/submitted reload-and-reapply conflict UI. `!84` then reused it again for **Roles**:
  Supplier/Customer add, deactivate and **explicit** reactivate that preserve the permanent
  assignment and its verification evidence, `InternalCompany` read-only, `ENTMST.Role` untouched,
  verification read-only, **one `EntityRoleAssignment` mutation seam** used by Entity360,
  `BusinessEntityService` and Cegid, automation still refusing inactive roles, service-side
  Admin/Finance/Accounting authorization with `Administrator` required for active
  `InternalCompany` entities, parent `xmin`, advisory locking, same-transaction audit, savepoints,
  dirty-tracker deny-by-default, the same current/submitted reload-and-reapply conflict handling,
  and merge into an inactive destination role failing closed **before** repointing. The
  pre-existing supplier Update / Verify /
  Merge writes remain on this page and stay supplier-scoped, unaffected by any of these slices, and
  supplier/Identity compatibility was preserved. The fourth tab, **Aliases**, shipped
  **read-only** with `!86` — following the Identity precedent of a read slice before a write
  slice — and `!89` then gave it the governed write: **update-only** mutation of aliases that
  already exist, `Alias` and the **explicit** scope writable while `ALCode`, `EntityId`, the
  generated `NormalizedAlias`, `CodeName` and `Flag` stay read-only, service-side authorization
  with an active company required, `xmin` concurrency, a same-transaction before/after audit
  write, the same current/submitted conflict handling, **one ENTALS update seam** that marks a
  successful human edit durably `HumanOwned`, and a seeder that preserves human `Alias` and scope
  while still synchronizing source evidence. The fifth tab, **Banking**, gained the same governed
  path with `!91`: **update-only** edits of the ENTBNKMethod/ENTBNKAccount child values, one value
  per save through the single `EntityBankingMutation` seam, with the parent ENTBNK
  `PayMethod`/`PayAccount` projection strings **regenerated from the children in the same
  transaction — never edited directly** — explicit scope where unscoped means "all companies" and
  structurally carries no pay accounts, parent `xmin` concurrency, durable `HumanOwned`, and
  seeder preservation with difference-gated projection regeneration. The sixth tab, **Items**,
  gained the same governed path with `!93`: **update-only** edits of the per-row SNCACC/CostCentre
  account mapping — the exact write the S3-4 learning path will later make — cleared only through
  explicit toggles, with the `SNCDSC` description **regenerated from the mapped SNCACC row, never
  edited directly** (and kept live for human-owned rows by a difference-gated seeder pass), unknown
  codes failing closed before any write, `xmin` concurrency, a same-transaction audit keyed by the
  permanent `EICode`, durable `HumanOwned`, and seeder preservation of the human mapping while
  source-owned columns still sync. The M-D4
  rule stands: writes go through one application service per table — the same service the S3-4
  learning path will call. The three remaining tabs shipped as **read surfaces**: **Documents**
  (`!96`, recent DOCLOG matched via the entity's `fdr.code_name` identities, rendered honestly
  while DOCLOG is writerless), **Balances** (`!97`, source-owned operational values labelled as
  not master data per the matrix's R-40 boundary) and **Audit** (`!98`, a type-scoped view over
  the entity's governed-write events with its attribution properties recorded in code).

---

## Task 0 — **done** (`!68`)

The `!62`–`!66` merge pipeline ids were read from GitLab and recorded in `docs/STATE.md`'s "Where
the code stands" paragraph. All five were green, so there was nothing to report as a finding, and
no per-merge archaeology was run below the verified green tip. `!67`–`!74` are recorded the same
way in the table above; `!73`'s pipeline id **2768788874** was read live from GitLab on 2026-08-18
and is recorded with the others. Every listed pipeline was green. Since Task 0 closed, `!75`,
`!76`, `!77`, `!79`, `!82`, `!84`, `!86` and `!89` have also been read from GitLab and are recorded, with their
pipeline ids, in the same table and in `docs/STATE.md` — this does not reopen Task 0, which stays closed on
the `!62`–`!66` verification it was scoped to. The rule stands for whatever merges next: read the
id, do not invent it.

## Task 1 — **done** (`!69`): `S1-9c` COCACC

Shipped read-only on the ITMCLS/MNGACC pattern — descriptor + `CostCentreReferenceService` +
`/{c}/master/accounts/cost-centres` + focused tests. COCACC still holds **one placeholder row**
and **O-2 is still open**: the screen is inert until the business names an owner. The three code
lists were not consolidated; P2-2 stays closed.

## Task 2 — **done** (`!70`, `!71`, `!72`): `S1-6a`, document types are data

One MR per step, as required:

1. **`!70` — presentation data migrated.** `20260817120000_S1DocumentTypePresentationData` copies
   `LabelPt`, `LabelEn`, `SortOrder` and `IsActive` from `DocumentTypeSetting` onto the matching
   DOCTYP rows. The columns stay target-owned and the seeder still does not write them.
2. **`!71` — the `FinancialDocumentType` enum reads removed.** `DocumentTypeRoutingService` now
   serves `Treatment`, `DocClass` and `ProcessingRoute` from DOCTYP to `ChannelIntakeService`,
   `ExtractDocumentJobHandler` directly, `StoredDocumentRegistrationService`, the review services,
   the integration eligibility path used by `IntegrateDocumentJobHandler`, the Moloni writers and
   the Razor pages — the handler names are not interchangeable. This is the prerequisite
   `S2-3` names, and `S2-3` is now the cataloging-time application of it rather than the removal.
3. **`!72` — `DocumentTypeSetting` dropped.** `20260818120000_S1DocumentTypeSettingsDrop` removes
   the table; `FinancialDocumentType` is retired; `DocumentTypeSettings.razor` was rewritten onto
   the read-only DOCTYP catalogue with a **PT/EN routing preview in words** beside each row, so
   the admin screen never pointed at a dropped table.

**What the drop did to data, from `S1DocumentTypeSettingsDropSql`.** `Up` refuses to run unless
`DocumentTypeSettings` holds **exactly the eight known legacy rows** — no unknown type, no missing
type, `count(*) = 8` — and unless the **nine** `(DocumentType, OriginClass)` DOCTYP tuples those
eight map onto carry `LabelPt`, `LabelEn`, `SortOrder` and `IsActive` in **NULL-safe exact field
equality to the source** (`IS DISTINCT FROM` per column), non-blank and in range. Only
then are the presentation trigger, its function and the table dropped. Three columns were **not**
carried across and were **deliberately not preserved** — `Version`, `UpdatedAt` and `UpdatedBy`
were operational row metadata of the July table, and DOCTYP holds no equivalent. `Down` is
therefore a reconstruction, not a restoration: nine tuples fold back to eight deterministically
because the two Invoice origin tuples must carry identical presentation and so collapse by
`LegacyType`/`DocumentType` to the single legacy Invoice row — the recovery guard rejects an
inconsistent fan-out — and it rebuilds the eight rows from DOCTYP and fills
those three with **explicitly synthetic** values (`Version = 1`, `UpdatedAt =
1970-01-01T00:00:00Z`, `UpdatedBy = 's1-doctyp-cutover-recovery'`), which is why the file's own
comment says recovery "never claims to restore the July row metadata".

Step 3 was the destructive migration on the stop list. **What this repository can attest is the
measured GitLab action:** the merge request was merged to `main` as
`1f4744998f6db97affdbeac7ff5374be5d6f1e09` by GitLab user `gottsolutions.net` at
2026-08-18T09:46:15.85Z on green pipeline 2768548294. There is **no verbatim approval text in the
repository**; do not quote or reconstruct one. The migration is merged — **do not reopen it, redo
it, or repeat any part of it.**

> **`FinancialDocumentType` / `DocumentTypeSetting` are gone from application code.** They survive
> only inside historical migration payloads, which are never edited. A document that still says
> either is live is stale — report it, do not act on it.

## Task 3 — `S1-9d`: Entity 360 — **the S1 exit criterion · all eleven slices landed, exit pending**

Rebuild `Suppliers.razor` (already at `/{c}/master/entities`) into the tabbed Entity 360 of the
plan §3.3, over merged ENTMST: **Identity** (`EntityCode`/`CodeName` read-only, resolved from
`ExternalIdentity`; name, NIF, country tri-state, currency, Role, Status, Origin, RelatedParty +
Kind) · **Tax identifiers** · **Roles** (`EntityRoleAssignments`, `InternalCompany` badge) ·
**Aliases** (scope explicit — unscoped means "all companies", shown, never blank) · **Banking**
(edit children, regenerate parent strings — never the reverse) · **Items** (ENTITM with the
accounts each posts to) · **Documents** (recent DOCLOG — empty until S2, render honestly) ·
**Balances** (read-only;
the approved plan §3.3 lists it, so it stays in scope) · **Audit**. Keep the merge panel writing
`MergedIntoId`. Permanent codes are never editable.

The pre-existing supplier Update / Verify / Merge writes are **retained** on this page and stay
supplier-scoped. `!79` established the governed M-D4 write-service pattern for Identity/ENTMST,
audit-write coverage and optimistic concurrency included, `!82` reused it for Tax identifiers and
`!84` reused it again for Roles. `!86` then shipped the **Aliases** tab **read-only** — no write
path — following the Identity precedent of a read slice before a write slice, `!89` gave that
tab its governed, update-only write, `!91` reused the pattern once more for **Banking**, and `!93`
again for **Items**. The
next slice, **Documents**, is a read surface over DOCLOG, rendered honestly while DOCLOG is
writerless.

**Do not open this as one merge request.** Nine tabs plus the first write-service pattern is far
past the ~20-minute review threshold, and one-item-per-MR is the rule that made `!62`–`!77` plus
`!79`, `!82`, `!84`, `!86` and `!89` work.

**Slice 1 — done (`!74`).** The tabbed shell and a **read-only** Identity tab on merged ENTMST at
`/{c}/master/entities`: canonical ENTMST list/detail, PostgreSQL-backed search and paging,
`EntityCode` / `CodeName` resolved from `ExternalIdentity`, name, fiscal number, country
tri-state, currency, Role, Status, Origin, RelatedParty + Kind, external identities, honest
placeholders for the tabs not yet built, service-side authorization and a test proving the read
path writes no audit rows.
No migration, no snapshot, no new write path; the pre-existing supplier Update / Verify / Merge
stayed supplier-scoped. It proved the resolution path and left the write-service pattern to be
reviewed on its own.

**Slice 2 — done (`!79`): the governed Identity/ENTMST write-service pattern.** It reuses the
existing paths rather than duplicating them, keeps the permanent codes read-only, enforces
authorization **service-side** — including an `Administrator` requirement for `InternalCompany` —
validates with PT and EN messages, appends an `AuditEvent` **inside the same transaction** as the
write (before and after), and implements and tests **optimistic concurrency against PostgreSQL**
on `xmin` (no speculative `Version` column, no migration). Transaction ownership and savepoints
deny by default on unsafe caller-owned `ChangeTracker` state, and identity/role authorization races
serialize at the PostgreSQL transaction level. The exact governed writable field set was shaped
against the live code at the time, and every field outside it stays preserved and read-only.
Merged as source `03180d1d` → merge `8d924db6`, MR
[!79](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/79), green head
pipeline **2770706234**. The first pipeline on this MR failed in the `PartyCollapseContract`
source/baseline contract and was fixed forward without weakening that contract.

**Slice 3 — done (`!82`): governed Entity 360 Tax identifiers.** It reused the M-D4 write-service
pattern `!79` established rather than inventing a new one. What shipped: an **accessible PT/EN Tax
identifiers tab**; governed **1:N `EntityTaxIdentifier` mutations** together with the **atomic
`ENTMST.FiscalNo` primary projection**, so the child rows and the primary projection move as one;
service-side `ClaimsPrincipal` authorization; permanent fields **not writable**; a before/after
audit write **inside the same transaction** as the mutation; `xmin` optimistic concurrency; caller
transaction / savepoint handling and dirty-tracker **deny-by-default**; duplicate, primary and race
handling; a **current/submitted reload-and-reapply conflict UI** rather than a silent overwrite;
and supplier/Identity compatibility preserved. Its migration
`20260819030442_S19dEntityTaxIdentifierInvariants` is **additive** — no destructive repair or
backfill, deterministic count-only preflights, `Up`/`Down`/`Up` and the pending-model gate proven.
Merged as source `2e9732e` → merge `3fb806b`, MR
[!82](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/82), MR head
pipeline **2771182592** success on that exact source SHA and post-merge `main` pipeline
**2771203526** success on that exact merge SHA. Route unchanged: `/{c}/master/entities`.

**Slice 4 — done (`!84`): governed Entity 360 Roles.** It reused the M-D4 write-service pattern
rather than inventing a new one. What shipped: an **accessible PT/EN Roles tab**; Supplier and
Customer **add, deactivate and explicit reactivate**, preserving the permanent assignment and its
verification evidence rather than re-creating either; **`InternalCompany` read-only**;
**`ENTMST.Role` untouched**; verification **read-only**; **one `EntityRoleAssignment` mutation
seam** used by Entity360, `BusinessEntityService` and Cegid alike, so there is no second write
path; automation still **refuses inactive roles**; service-side Admin / Finance / Accounting
authorization with **`Administrator` required for active `InternalCompany` entities**; parent
`xmin` optimistic concurrency, advisory locking, a same-transaction audit write, savepoints and
dirty-tracker **deny-by-default**; a **current/submitted conflict reload-and-reapply**; and
**merge into an inactive destination role fails closed before repointing**. Its migration
`20260819082319_S19dEntityRoleAssignmentInvariants` is **additive** — six count-only preflights and
five CHECKs, with no repair, no backfill, no index alteration, no `ENTMST.Role` write and no seeder
write; `Up`/`Down`/`Up` and the pending-model gate proven. Merged as source `b9b332b` → merge
`2c7eab4`, MR
[!84](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/84), MR head
pipeline **2771963044** success on that exact source SHA and post-merge `main` pipeline
**2772015854** success on that exact merge SHA. Route unchanged: `/{c}/master/entities`.

**Slice 5 — done (`!86`): the read-only Entity 360 Aliases tab.** It followed the Identity
precedent of a read slice before a write slice. What shipped: an **accessible PT/EN Aliases tab**
over ENTALS at the unchanged route; rows served **only for canonical (non-merged) ENTMST
entities**; PostgreSQL-backed paging in a **deterministic order** (normalised alias, then scope,
then `ALCode`); **scope shown explicitly** — an unscoped alias renders as "all companies" in PT
and EN and is never a blank field; and service-side Administrator / Finance / Accounting **read**
authorization. **No write path.** Its migration `20260819111951_S19dEntityAliasesReadModel` has an
**empty `Up` and an empty `Down`** — EF model-mapping alignment only, no schema change, no data
change, no backfill. Merged as source `d2064e8` → merge `c1cec04`, MR
[!86](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/86), MR head
pipeline **2772364485** success on that exact source SHA and post-merge `main` pipeline
**2772402931** success on that exact merge SHA. Route unchanged: `/{c}/master/entities`.

**Slice 6 — done (`!89`): the governed Aliases/ENTALS write.** It reused the M-D4 write-service
pattern `!79` established, `!82` and `!84` reused, and `!86` read from — it did **not** invent a
new one. What shipped:

- **Update-only.** Aliases that already exist are updated; the slice creates no alias and deletes
  none.
- **`Alias` and the explicit scope are the writable fields.** An alias is either scoped to a
  company or unscoped, and **unscoped means all companies** — rendered in words in PT and EN, on
  read and on write, never a blank field and never inferred from an empty control.
- **`ALCode`, `EntityId`, the generated `NormalizedAlias`, `CodeName` and `Flag` are read-only.**
  `ALCode` is a permanent code; it is never editable and **never issued here**.
- **Service-side authorization**, enforced in the application service against the
  `ClaimsPrincipal` rather than in the UI, on the same Admin / Finance / Accounting basis the read
  slice used, and requiring an **active company** — a hidden control is not an authorization
  decision.
- **Accessible PT/EN editing and error copy, including CHECK failures.** Validation and database
  constraint failures surface as localized messages rather than raw constraint names or exceptions.
- **A before/after `AuditEvent` appended inside the same transaction as the mutation** — not a
  second transaction and not best-effort.
- **Optimistic concurrency on PostgreSQL `xmin`** — no speculative `Version` column.
- **A current/submitted reload-and-reapply conflict UI** on concurrency loss, rather than a silent
  overwrite.
- **One ENTALS update seam**, used by every caller, per M-D4 — and a successful human edit is
  marked durably **`HumanOwned`** through it.
- **The seeder preserves human `Alias` and scope** while still synchronizing source evidence.

Its migration `20260819144205_S19dEntityAliasWriteInvariants` is **additive** — a count-only
preflight, `CK_ENTALS_Alias_NonBlank`, and a `HumanOwned` boolean defaulting to false, with no
repair, no backfill and no code issuance. Merged as source `a6b70fc` → merge `35ca2e7`, MR
[!89](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/89), MR head
pipeline **2773586157** success on that exact source SHA and post-merge `main` pipeline
**2773640192** success on that exact merge SHA, its jobs `build-test` **15990486347**,
`p11a-database-tests` **15990486348** and `fdr-database-tests` **15990486349** all success. Route
unchanged: `/{c}/master/entities`.

**Slice 7 — done (`!91`): the governed Banking tab.** It reused the M-D4 write-service pattern
rather than inventing a new one. What shipped: an **accessible PT/EN Banking tab** over ENTBNK per
`(EntityId, ScopeKey)` with the ENTBNKMethod/ENTBNKAccount children ordered by ordinal; **explicit
scope** — an unscoped row renders as "all companies" in PT/EN, never blank, and structurally
carries no pay accounts (`CK_ENTBNK_Unscoped_NoPayAccount`); a governed **update-only** write of
one child pay value per save through the single `EntityBankingMutation` seam — the values
participate in alternate keys, so the human update is parameterized SQL — with the parent
`PayMethod`/`PayAccount` strings **regenerated from the children in the same transaction, never
edited directly**, and child values validated non-blank and comma-free because the comma is the
projection separator; service-side Admin/Finance/Accounting authorization with an active company
required; parent `xmin` optimistic concurrency; a same-transaction before/after audit write; a
current/submitted reload-and-reapply conflict UI; dirty-tracker deny-by-default and savepoints;
the shared governed advisory lock; durable `HumanOwned` on successful human edits; and seeder
preservation of human child values with **difference-gated** regeneration of human-scope parent
projections, so steady-state replays rewrite nothing. Its migration
`20260819211044_S19dEntityBankingWriteInvariants` is **additive** — count-only preflights,
`HumanOwned` on both child tables, non-blank/no-comma CHECKs, and ENTBNK's pre-existing projection
columns newly mapped but never created, dropped or altered. Merged as source `22392c3` → merge
`4842500`, MR
[!91](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/91), MR head
pipeline **2774384047** success on that exact source SHA and post-merge `main` pipeline
**2774401009** success on that exact merge SHA. The fresh adversarial pass found one blocker
(an unconditional projection rewrite in the seeder) — fixed forward inside the MR — and its
findings are recorded as MR comments. Route unchanged: `/{c}/master/entities`.

**Slice 8 — done (`!93`): the governed Items tab.** It reused the M-D4 write-service pattern
rather than inventing a new one. What shipped: an **accessible, paged PT/EN Items tab** over
ENTITM ordered deterministically (`ItemCode`, then `EICode`) — `EICode`, item identity and
class/subclass **read-only** — with a governed **update-only** write of the account mapping the
S3-4 learning path will later target: `SNCACC` and `CostCentre` per row, cleared only through
**explicit toggles** (an empty control never means "no mapping"); `SNCDSC` **regenerated from the
mapped SNCACC row's description in the same transaction, never edited directly**, and kept live
for human-owned rows by a difference-gated seeder pass; unknown accounts and cost centres
**failing closed before any write**; service-side Admin/Finance/Accounting authorization; `xmin`
optimistic concurrency; a same-transaction before/after audit keyed by the permanent `EICode`; a
current/submitted reload-and-reapply conflict UI; dirty-tracker deny-by-default, savepoints and
the shared governed advisory lock; **one `EntityItemMappingMutation` seam** for the human edit and
the seeder's source sync, with durable `HumanOwned` and seeder preservation of the human mapping
while source-owned columns still sync. Its migration `20260819235415_S19dEntityItemMappingInvariants`
is **additive** — it adds only `HumanOwned`; ENTITM's descriptive columns, SNCACC's `Conta` and
the `xmin` system column are newly mapped but never created, dropped or altered. Merged as source
`7c094bd` → merge `01b6b90`, MR
[!93](https://gitlab.com/gottsolutions.dev/sibyla/GOTT.Sibyla/-/merge_requests/93), MR head
pipeline **2774534974** success on that exact source SHA and post-merge `main` pipeline
**2774555750** success on that exact merge SHA. The fresh adversarial pass returned ACCEPT with
two should-fixes — the stale-`SNCDSC` projection gap and seam-guard blind spots — fixed forward
inside the MR; findings are recorded as MR comments. Route unchanged: `/{c}/master/entities`.

**Slices 9–11 — done (`!96`, `!97`, `!98`): the three read surfaces, completing the nine tabs.**
Each was a small read-only MR — no write path, service-side Admin/Finance/Accounting read
authorization, null for non-canonical entities, sentinel-proven audit-untouched reads, and a
fresh adversarial pass whose findings were fixed forward inside the MR and recorded as MR
comments. **Documents** (`!96`, source `5822188` → merge `ffc8d04`, merged
2026-08-20T02:04:51.064Z; MR pipeline **2774628822** — one `build-test` retry **15997571185**
after a recorded pre-existing timing flake in the Hermes Windows-helper toolset test — and
post-merge **2774664385** success) pages recent DOCLOG via the entity's `fdr.code_name`
identities and names the missing DOCLOG writer in its empty state; its migration
`20260820011243` has an empty `Up`/`Down`. **Balances** (`!97`, source `4d1b81d` → merge
`dfb7e96`, merged 2026-08-20T02:43:59.463Z; MR pipeline **2774701711**, post-merge **2774717382**
success) renders the source-owned operational balances labelled explicitly as not master data,
faithful to the stored `numeric(19,4)` scale in the page culture; no migration. **Audit**
(`!98`, source `e6f4e19` → merge `ed9cf25`, merged 2026-08-20T03:22:11.391Z; MR pipeline
**2774744416**, post-merge **2774775333** success) is a paged, type-scoped view of the entity's
governed-write events — entity guid, `ALCode`s, `EICode`s, the `{guid}|` banking composite —
with two deliberate attribution properties recorded in code: merge history stays in the audit
store un-rendered, and code-keyed rows follow the code's current owner; no migration. Route
unchanged throughout: `/{c}/master/entities`. No speculative design beyond that.

**Exit, demonstrated to a person:** search "CTT" → the entity, its aliases, its bank accounts,
its usual items and the accounts those items post to. Re-running the seeder changes nothing.
**This has not happened**: slices 1–11 (`!74`, `!79`, `!82`, `!84`, `!86`, `!89`, `!91`, `!93`, `!96`, `!97`, `!98`) did not satisfy
the exit criterion and
supplied no proof of a real CTT row and no human demonstration — there is **no date and no
witness** to record, and none is to be invented. The criterion is not met by a screen that would
render such a row: it requires a **real CTT row in ENTMST, actually shown to a real person**, and
both the **date** and the **witness** recorded. Do not call the demonstration
"CTT" unless a real matching ENTMST row exists **and** is actually shown to a person. When it
demonstrably works, S1 closes; record it — with the date and who saw it — in `STATE.md` and the
backlog. Until then S1 is open, `S1-9d` is not done, and neither may be described otherwise.

## Task 4 — remaining `S1-9` pieces, in this order

`c` remainder — **done 2026-08-20**: EXCRAT with the missing-rates panel (`!100`, source
`80b3f0b` → merge `5dc156c`, MR pipeline **2774901553**, post-merge **2774923067** success),
ITMALS as the first `GlobalOrActiveCompany` grid (`!101`, source `9f85337` → merge `8a28cad`,
MR pipeline **2774961350**, post-merge **2774986416** success) and ENTALS surfacing `HumanOwned`
(`!102`, source `8f0734d` → merge `f451bbf`, MR pipeline **2775012507**, post-merge
**2775047768** success), all read-only
first cuts, each with a fresh adversarial pass fixed forward and recorded as MR comments; no
migration and no write path in any of the three. Two admin-surface merges followed 2026-08-20:
the **`h` first cut** — the read-only DOCEFL flag-rules catalogue (`!104`, source `b93c4a6` →
merge `75485e0`, MR pipeline **2775106669**, post-merge **2775135541** success; no write path,
no migration, no O-4 dependency) — and the **`g` presentation slice** — the governed DOCTYP
presentation write (`!105`, source `a60113f` → merge `607c2ab`, MR pipeline **2775197342**, post-merge
**2775227965** success; LabelPt/LabelEn/SortOrder only, Administrator-only, `xmin` concurrency via the empty
model-alignment migration `20260820065333`, same-transaction audit, fail-closed offered-type,
sort-order-range and label-length rules; **IsActive and the routing columns stay read-only in
this slice** — their writes are g2 (normal flow) and g3 (on O-1)) · `e` — **done 2026-08-20** in three
slices: the ITMMST item master (`!109`), the entity-item matrix with the "unclassified lines
seen in the last 30 days" classification queue (`!110`), and the entity-banking catalogue
(`!112`, source `dd28dff` → merge `2a65676`, MR pipeline **2775662815**, post-merge
**2775718587** success) · `f` — **done 2026-08-20** (`!113`, source `cf444ed` → merge
`904b434`, MR pipeline **2775760116**, post-merge **2775800133** success): the read-only SNCACC
tree at
`/{c}/master/accounts/snc` with lazy expansion, path-revealing search and **direct**
ITMMST/ENTITM posting counts per account; adding a leaf issues a permanent SNCode and stays
behind the stop list · `g` **the DOCTYP
editing surface** — the read-only catalogue and its routing preview landed with Task 2 step 3 and
the **presentation write landed with `!105`** (LabelPt/LabelEn/SortOrder only), so what is left
here is **g2, the `IsActive` offer toggle** — normal V6-O1 flow, the slice's MR stating the
assessment (it configures this application's own intake offering, no live tenant) — and **g3,
the routing columns**, waiting on O-1
(`Payables`/`Receivable`) fixed at source or preserved verbatim, still Luís's call · `h` the
DOCEFL **editor** — the read-only flag-rules catalogue landed with `!104`; the editor is
**formally deferred to S2** (its pattern tester has no documents until S2), goes
**with the pattern tester and impact count — do not ship it without them**, and O-4 stays
Miguel's · `i` — **done 2026-08-20** (`!107`, source `f511e08` → merge `01f9095`, MR pipeline
**2775314610**, post-merge **2775367662** success): the entity half of `Companies.razor` writes through the governed
identity path, the permanent code is no longer submitted, the stored identifier type is carried
read-only, conflicts render reload-and-reapply and the fresh `xmin` is adopted only post-commit;
its connection half is working S4 code and was not touched.

Task 4 can interleave with Task 3; Task 3 is the gate S1 closes on. After S1 closes, the next
prompt opens **S2** (two records, one bridge — `DocumentCatalogingService` writes
DOCLOG/FDCHDR/FDCDTL; S2-13 golden set built early — the S0-4 GD-1 E2E and state closure it needed
landed 2026-08-18, so that prerequisite is met).

---

## Standing rules

- **V6-O1.** Pipeline green → merge. Adversarial pass comments, never gates. Fix forward. A
  review past ~20 minutes means the change is too large.
- **Stop list** — destructive migrations · ERP write path · permanent code issuance · live-tenant
  config. **The one item this prompt carried — the `DocumentTypeSetting` drop, Task 2 step 3 — is
  merged and closed.** No currently planned Task 3 UI slice is itself on the stop list, and none of
  `!82`, `!84` and `!89` was: each migration is additive, with no destructive repair and no
  backfill — `!84`'s also alters no index, writes nothing to `ENTMST.Role` and makes no seeder
  write, and `!89`'s issues no permanent code, `ALCode` included. Task 4
  slices are assessed individually when shaped; runtime editors are **not automatically**
  live-tenant configuration (`docs/s1-gated-editors-proposal.md`, corrected 2026-08-20) — the
  stop list bites when a slice would point configuration at a live tenant, and such a slice
  stops and asks Miguel.
  Normal data writes still require authorization, audit, validation and optimistic concurrency;
  they are not made reversible by a `git revert`. If a slice introduces a destructive migration,
  ERP write path, permanent code issuance or live-tenant configuration, it stops and asks —
  **the approver is Miguel, and his explicit approval is required before the merge.** For `!72`
  the repository holds **no verbatim approval record** — only the GitLab merge action recorded
  above; do not quote or reconstruct one.
- **One merge request per item.** Small MRs; the `!62`–`!77` plus `!79`, `!82`, `!84`, `!86` and
  `!89` run of single-item MRs is the pattern to keep — and the reason Task 3 is sliced rather than shipped
  whole.
- **What CI runs:** `build-test` (default filter, Windows) · `p11a-database-tests`
  (`PartyCollapseContract` then `P11aDatabase`, disposable PostgreSQL 17) · `fdr-database-tests`
  (`FdrDatabase`) · `docs-check` (link checker, docs-only changes). **`FdrSource` is host-only by
  design and never appears in a pipeline.** If you add a test category, add its job in the same MR.
- **Counts are observations on a date, never acceptance criteria.** Report measured results only;
  no projected figures, no invented pipeline ids.
- `docs/STATE.md` is updated **in place** and never grows past one page.
- A blocker is an observed fact that makes an instruction impossible — report it and carry on
  with everything it does not block.

---

## Report back

Tasks 0–2 delivery evidence is recorded above and is not re-reported. The missing verbatim
approval record for the `!72` stop-list merge remains an explicit provenance gap; do not
reconstruct it. What is still owed:

1. **Entity 360, MR by MR** (Task 3): **all eleven slices are landed and reported** — `!74`,
   `!79`, `!82`, `!84`, `!86`, `!89`, `!91`, `!93`, `!96`, `!97`, `!98`. Nothing in this item
   remains.
2. **The Entity 360 demonstration** (Task 3 exit): what "CTT" showed — from a real ENTMST row,
   shown to a real person — on a date, and who saw it.
   Until that line can be written from something that happened, S1 stays open.
3. Each Task 4 piece as it lands: MR, pipeline, route.
4. Any row count or doc statement that disagreed with the backlog, with the date observed.
5. Anything contradicting the master-data plan §3 — as a **finding to report, not a change to
   make**.
