Files
llm/docs/runbooks/1c-designer-sql-decoding.md
T

21 KiB
Raw Blame History

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. That historical fixture was later removed from the live saved state. The observations below remain decoder evidence, but they must not be interpreted as proof that the current upo_test still contains the object.

The reproducible fixture requirements are declared in config/1c_metadata_kind_fixtures.json. Validate the declaration offline:

python scripts/check_1c_metadata_kind_fixtures.py

Probe the current adapter and test base:

python scripts/check_1c_metadata_kind_fixtures.py --live

Use --require-ready only as a strict regression gate after the fixtures have been loaded with 1C Designer. The checker never creates metadata and never writes platform SQL. CalculationRegister and Sequence belong in the saved test2 extension. Legacy Interface requires a dedicated compatible test base, supplied explicitly as --target-base interface_legacy_base=<base_id>; it must not be simulated in a modern configuration by editing Config, ConfigCAS, or DBNames.

At the 2026-07-26 verification point, the upo_test server required platform 8.5.1.1236. The exact Designer build is now installed at C:\Program Files\1cv8\8.5.1.1236\bin\1cv8.exe; the previous client-version blocker is closed.

Export the current saved test2 sources through operating-system integrated authentication only:

.\scripts\export_1c_extension_sources.ps1 `
  -OutputDirectory C:\Temp\upo-test-test2-source

The export helper verifies the exact executable version, refuses a non-empty output directory, always passes /WA+, and has no user or credential parameters. It only reads and exports the extension; it does not load, save, or apply a configuration.

The current workstation account is not mapped to an infobase user on wsr\upo_test, so the server export stops with Пользователь ИБ не идентифицирован. A disposable local file infobase needs a client license and stops with Не найдена лицензия. Therefore provisioning is still blocked by execution environment, not by adapter code or platform version. Continue on a licensed workstation under an already authorized operating-system identity; do not add a user name or password to scripts, manifests, or reports, and do not bypass the block with direct SQL.

An external structural reference is pinned to asosnoviy/go1cover@c7e3ea3d90396d341cb98285c29973bcc0a82eca, path testresourse/cf/designer/src. It contains examples of CalculationRegister, Sequence, and legacy Interface. The upstream repository is GPL-3.0; its files are reference input only and are not vendored into this project. The pinned source and per-kind paths are declared in the fixture manifest.

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 <extension-guid>__<object-guid>; 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 <extension-guid>__<object-guid> 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.241.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 <extension-guid>__<child-guid> key. A saved command exposes its BSL payload as <extension-guid>__<command-guid>.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 <extension-guid>__<form-guid>.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 <extension-guid>__<object-guid>; 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.