# Controlled Designer-to-SQL Decoding Use the disposable `upo_test` base to learn SQL encodings that cannot be established from static samples. The mutation is performed by 1C Designer or a 1C Enterprise client. The adapter remains a read-only SQL observer. The active rule is `plugins/1c/connector/policies/designer-sql-decoding-policy.yaml`. ## Credential rule Keep the 1C user password outside the repository. Supply it for one process through an environment variable or an operating-system credential store. Do not add it to `.env`, YAML, JSON, test fixtures, reports, or command examples. ## Metadata experiment 1. Select an object by a public 1C name. 2. Confirm there are no unrelated pending Designer changes. 3. Capture the target from live SQL, including active and saved-state origin. 4. In Designer change exactly one property and save it without applying the configuration when saved-state evidence is sufficient. 5. Capture `ConfigSave` or `ConfigCASSave` again and compute the structural and byte-level diff. 6. Repeat with a second value; one pair is only a hypothesis. 7. Promote a decoder only after the name, type, path, and ownership are stable. 8. Revert through Designer and verify rollback in SQL. Applying the configuration is a separate explicit phase because it can change `Config`, `ConfigCAS`, and the physical application-data schema. ## Application-data experiment 1. Resolve the object through `data.schema` using its public name. 2. Capture `data.count` and a narrowly filtered `data.list`. 3. Create or edit one test record through 1C Enterprise, never through SQL. 4. Capture the same logical filter after the 1C transaction commits. 5. Correlate logical values with SQL columns, including composite branches. 6. Revert or delete through 1C Enterprise and verify rollback read-only. ## Noise controls - Record configuration-check errors that existed before the experiment. - Do not run two experiments against the same object concurrently. - Separate base configuration and extension ownership. - Treat timestamps, version bytes, caches, and background service data as volatile unless explicitly targeted. - Discard a run when more than one semantic property changed. Each accepted experiment produces a manifest with the public selector, intended change, before/after SQL hashes, changed paths or columns, semantic rule, second verification case, rollback evidence, and regression tests. XML may be attached as offline naming evidence but is not read by the adapter. ## Confirmed baseline The first live `upo_test` CAS comparison is recorded in `reports/1c-sql/upo_test/designer-sql-baseline-20260714.json`. It proves a BSL module-text change at tree path `$.2`. The accompanying `pos` and `end` changes are stream-directory offsets recalculated from the text length; they are not independent metadata properties and must be filtered as derived evidence. ## Saved extension metadata descriptors The `test2` experiment on 2026-07-15 added a minimal calculation register and its required chart of calculation types through Designer, then saved the extension without applying it. The objects remain intentionally `saved_only` for adapter regression checks. Observed read-only SQL signatures in `ConfigCASSave`: - `CalculationRegister`: brace root marker `1`, root length `10`, metadata block marker `21`; - `ChartOfCalculationTypes`: brace root marker `1`, root length `8`, metadata block marker `35`; - saved extension descriptor names use `__`; child/module parts add a numeric suffix. The runtime adapter derives these signatures only from SQL payloads. The XML export is offline evidence used to confirm the public object kind, name, GUID, and the register-to-chart relationship; it is not a runtime data source. When `state=working`, `extension.objects.find` must overlay these descriptors from `ConfigCASSave` and report `saved_only` or `saved_override`. With `state=active`, the same unapplied objects must not be returned. Route-cache rebuilds must reclassify active descriptors so an earlier guessed kind cannot survive as a false match. Public saved-state card selectors expose `extension_guid`, object `guid`, and `table=ConfigCASSave`; they do not expose the physical descriptor name. The adapter reconstructs `__` internally before the read-only SQL lookup. For `ChartOfCalculationTypes`, the verified kind-specific map currently covers 17 properties: the five scalar code/name settings at paths `1.24`–`1.30`, six default/auxiliary form references, five localized presentations, and `ActionPeriodUse` at `1.57`. The paths were cross-checked on the live `Начисления` and `Удержания` descriptors against their offline XML exports. For the saved-only `CalculationRegister`, the verified header map covers 13 properties: periodicity, action/base-period flags, list-form references, chart reference, standard-command/help flags, lock and full-text modes, and three localized list presentations. `metadata.object.properties` accepts the public `extension_guid` + object `guid` selector and reconstructs the `ConfigCASSave` descriptor name internally. Runtime property responses remain SQL-only. The saved register descriptor also confirms all seven variable child-part collections: `Attribute` at root path `3`, `Recalculation` at `4`, `Template` at `5`, `Resource` at `6`, `Form` at `7`, `Command` at `8`, and `Dimension` at `9`. The three field roles were distinguished by a controlled Designer sample containing one `Реквизит1`, `Ресурс1`, and `Измерение1`. Designer saved the extension without applying it; the adapter identified the records read-only from the resulting live `ConfigCASSave` payload. Saved-only register fields are available through `metadata.object.attributes` with `table=ConfigCASSave`, `extension_guid`, and the public object `guid`. The response returns names and decoded types while reconstructing the physical saved descriptor key internally. `metadata.object.related` accepts the same selector for recalculations, templates, forms, and commands; saved child keys are also prefixed internally and remain hidden unless storage diagnostics are explicitly requested. A second controlled Designer sample added one item to every related collection: `Перерасчет1`, `Макет`, `ФормаСписка`, and `Команда1`. The root descriptor then reported a declared count of one at paths `4`, `5`, `7`, and `8`. Recalculation, template, and form descriptors use the internal `__` key. A saved command exposes its BSL payload as `__.2`; the additional command-class GUID inside the owner record is type evidence, not a second related command. Public related results therefore keep only the record identity GUID and probe the `.2` module route internally when the direct saved command descriptor is absent. The specialized `metadata.object.forms`, `metadata.object.form.details`, `metadata.object.commands`, and `metadata.object.modules` methods accept the same saved-state selector. Form enumeration and detail decoding use the internally reconstructed `__.0` payload. Object commands are returned from the owner descriptor and their saved `.2` payload is verified without exposing the physical key in normal responses. Each saved object command also returns a ready public `modules.read` selector, so callers select the command by name and never need to calculate its GUID or SQL route. The `.2` payload is a raw-deflate multi-stream container; `modules.read` automatically selects its single BSL-marked stream when whole-payload text decoding is not applicable. Object-scoped `modules.search` and its `code.search` wrapper include these saved command modules alongside the owner's regular modules. A caller can therefore search by the public register selector plus BSL text and receive a ready `modules.read`/`code.read` selector for the matching command module. `metadata.definition.find` with `areas=["modules"]` follows the same saved selector, enumerates command-module routines, and returns the exact procedure or function definition with a routine-scoped read selector. `metadata.object.parts` and `metadata.object.decode` also reconstruct the saved descriptor prefix before reading. The former enumerates the root and suffix payloads under `__`; the latter decodes the root descriptor from that key while keeping physical storage coordinates hidden by default. The combined `metadata.object.full` profile promotes saved object-command selectors into its `modules` collection as `command_module` handles. This keeps the profile lightweight (no BSL text is loaded there) while ensuring the reported module count includes code carriers owned by commands. Targeted `metadata.code_index.build` runs on saved command `.2` containers now retain only streams that are positively identified as BSL. Command owner metadata cached from `metadata.object.commands` is inherited by the concrete `#stream:N` index row, and obsolete non-BSL rows plus their vector chunks are pruned when the source file is rebuilt. The extension GUID is recovered from the saved module route and retained in the indexed owner metadata. For saved extensions, `metadata.object.get` resolves an object name through the saved extension manifest/state route before reading its descriptor. The public `/rpc` dispatcher preserves this name selector when `extension_guid` and `table=ConfigCASSave` are supplied; callers may use the object name directly and do not have to resolve its GUID first. An explicit `guid` still takes precedence when both selectors are present. `metadata.code_index.build` can therefore be scoped by `kind` plus `name` and `extension_guid`; it discovers owner and command module files internally and does not require callers to pass a physical prefix or command GUID. The same object-scoped build enumerates saved forms, decodes their embedded modules separately from container streams, and indexes a form only when a valid non-empty BSL module is present. Empty generated forms are not emitted as code carriers. Build counts distinguish `forms_scanned`, `form_modules_discovered`, `empty_form_modules`, and `form_module_errors`, so coverage and decoding failures are observable separately. `CalculationRegister` is included in the public register code-carrier matrix. Its record-set/register/command module handles use the same name-first SQL-only read and saved-state write contract as the other register kinds. Offline `Form.xml` analysis uses the same public vocabulary as the SQL form decoder for form commands, events, attributes and value-table columns, check box fields, and search/view-status/search-control additions. The XML profile also exposes semantic properties of the root `Form` node, including command bar location and visibility. XML remains comparison evidence only and is never consulted by runtime adapter calls. The SQL/XML comparison report records property-route evidence as `XML kind/property -> SQL marker/parameter/source`. Across the 11 controlled test-extension forms, 764 elements and 3,361 properties compare without mismatches or XML-only properties; 23 routes have at least two matching examples and a single SQL route. `UsualGroup.Visible` remains intentionally variant-aware because marker `22` uses parameter `26` or `28` in two observed structures. A controlled Designer probe on `t_FORM_ContainerTableBehaviorVariants` changed only `ГруппаФорма.Visible=false -> true`: parameter `26` changed `0 -> 1`, while parameter `10` and nested `Группа1` remained unchanged. In the nested shape, parameter `26` is a GUID and parameter `28` is the boolean visibility slot. Saved-state writes therefore select parameter `26` only when it is boolean; otherwise they select boolean parameter `28`. The extension was restored with `/RollbackCfg -Extension test`, and its `ConfigCASSave` prefix was verified empty after the probe. Root form properties are compared separately from element properties. A controlled `ShowCommandBar=false -> true` Designer probe changed exactly two form atoms: parameter `17` from `0` to `2` and parameter `56` from `0` to `1`. The SQL profile exposes this as `ОтображатьКоманднуюПанель` with `write_shape=paired_scalar`; it is readable but must not be routed through a single-scalar writer. `АвтоКоманднаяПанель` is resolved from the decoded form item with `id=-1`. Before the next controlled probe, 33 root properties matched and 44 remained. A controlled `WindowOpeningMode=DontBlock -> LockOwner` Designer probe changed exactly form parameter `2` from `0` to `1` and companion parameter `54` from `0` to `1`. The SQL profile exposes the confirmed values as `РежимОткрытияОкна=DontBlock|LockOwner` with `write_shape=paired_scalar`. Other platform enum values remain undecoded until separately observed. The probe was loaded only into the saved extension configuration, then rolled back; the `test` extension prefix in `ConfigCASSave` was verified empty afterwards. Across the 11 fixtures, 44 root properties now match; the remaining 33 are three scalar properties repeated on each form: `AutoSaveDataInSettings`, root `Group`, and `CommandBarLocation`. A controlled `AutoSaveDataInSettings=Use -> DontUse` Designer probe changed only form parameter `7` from `1` to `0`. The SQL profile exposes this as `АвтоСохранениеДанныхВНастройках=Use|DontUse` with `write_shape=scalar_enum`. The extension was rolled back and the `test` prefix in `ConfigCASSave` was verified empty. Across the 11 fixtures, 55 root properties now match; the remaining 22 are root `Group` and `CommandBarLocation`, each repeated on all forms. A controlled root `Group=Vertical -> Horizontal` Designer probe changed four form parameters together: `11`, `40`, `47`, and `57`, all from `0` to `1`. The SQL profile exposes `Группировка=Vertical|Horizontal` with `write_shape=composite_scalar`; partial single-atom writes are not safe. The extension was rolled back and the `test` prefix was verified empty. Across the 11 fixtures, 66 root properties now match; only `CommandBarLocation` remains. `CommandBarLocation` shares the same parameter pair as `ShowCommandBar`. With the panel enabled, `Top` produced `[17,56]=[2,1]` and `Bottom` produced `[3,1]`; the hidden state is `[0,0]` and is exposed as `None`. XML `None` with `ShowCommandBar=true` normalizes to the same SQL state as `Top`, so SQL exposes the effective position. The profile returns `ПоложениеКоманднойПанели=None|Top|Bottom` with `write_shape=paired_scalar_shared`; both properties must be encoded together. After each probe the extension was rolled back and its saved prefix was empty. All 77 root properties across the 11 controlled forms now match SQL to XML. The platform's third window-opening mode was verified separately because it is not present in the UPO XML inventory. The accepted XML literal is `LockWholeInterface`; a controlled Designer probe changed form parameters `[2,54]` from `[0,0]` to `[2,2]`. `РежимОткрытияОкна` now decodes the complete confirmed enum: `DontBlock=[0,0]`, `LockOwner=[1,1]`, and `LockWholeInterface=[2,2]`. The failed tentative `LockUI` literal was rejected by XDTO before any SQL saved state was created. The successful probe was rolled back and the extension saved prefix was verified empty. The complete root `Group` enum observed in UPO was verified with two additional Designer probes. `AlwaysHorizontal` maps to `[11,40,47,57]=[1,1,3,3]`, while `HorizontalIfPossible` maps to `[1,2,2,2]`. Together with `Vertical=[0,0,0,0]` and `Horizontal=[1,1,1,1]`, the decoder now covers every root form grouping value present in the XML inventory. Each probe was rolled back and the saved prefix was verified empty. Active base-configuration forms also use compact root layouts. Across multiple SQL-only samples, form payload versions 49 and 50 store `WindowOpeningMode` directly in parameter `2`; values `0` and `1` were confirmed by `DontBlock` list forms and `LockOwner` item forms. In these layouts, parameter `11=0` consistently identifies root `Group=Vertical` even when the newer companion positions are absent. The decoder applies these fallbacks only to versions 49/50 and observed values; runtime remains SQL-only. The active base catalog form `ЗадачиАссистентаУправления.ФормаСписка` confirmed the compact marker-55 dynamic-list layout. Parameter `54` is the property-bag entry count; its typed key/value pairs decode keys `5`, `6`, `8`, `9`, `11`, `12`, `14`, and `16` as `AutoRefresh`, `AutoRefreshPeriod`, `ChoiceFoldersAndItems`, `RestoreCurrentRow`, `ShowRoot`, `AllowRootChoice`, `UpdateOnDataChange`, and `AllowGettingCurrentRowURL`. The following tail records contain the user-settings-group item id, `InitialTreeView`, and the standard `DefaultPicture` field reference. The same live payload confirms `CommandBarLocation=None` at parameter `6` and `DefaultItem=true` at parameter `16`. Compact marker-22 command bars expose `Autofill` at parameter `28`. Marker-35 label fields with nested subtype marker `11` store `AutoMaxWidth/MaxWidth` in nested positions `15/16` of parameter `39`. The SQL/XML comparison normalizes these public XML names to the decoder's Russian semantic vocabulary and treats marker-55 `Динамический список` as the SQL implementation of XML `Table`. XML is used only to validate the learned routes; runtime decoding reads the SQL payload alone. The base item form of the same catalog confirmed more compact-layout routes. Root parameter `20` is a typed enum with type GUID `59ef2b80-c86b-11d5-a3c1-0050bae0a776`; value `0` decodes `UseForFoldersAndItems=Items`. Root event bindings may reside in a direct form block such as `1.23`; they are discovered by the GUID/handler pair shape rather than a fixed position. GUID `bf0ac0e1-bcbb-4dfe-8fc4-0b1923b461a6` identifies `BeforeWriteAtServer`. Compact pages options `{3,1,...}` decode `PagesRepresentation=TabsOnTop`. Object-backed data paths resolve public standard fields `-2/-3/-4/-5` as `Code/Description/Parent/Ref`; custom object and tabular-section fields are resolved from the element name and owning table. XML `AdditionalColumns` definitions are correlated with the physical SQL form element by their full data path. Across both active forms of `Catalog.ЗадачиАссистентаУправления`, the comparison now covers 144 XML elements, including the logical additional column, with no missing elements, property mismatches, or XML-only properties.