Initial project import
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# SQL protocol knowledge base for 1C configuration storage
|
||||
|
||||
This directory is the durable, evidence-first record for the 1C SQL adapter.
|
||||
It complements [the general format specification](../1c-sql-format-spec.md).
|
||||
Do not put all observations into one chronological note: add a fact to the
|
||||
document for its layer, object type, codec, operation, or experiment.
|
||||
|
||||
## Non-negotiable runtime rule
|
||||
|
||||
The adapter works **only through SQL**. It may decode and encode only what was
|
||||
observed in the target database and proven by round-trip checks. It must never
|
||||
invent a metadata object, physical path, BSL fragment, form element, join,
|
||||
codec, or cryptographic value. Unknown or ambiguous work returns an explicit
|
||||
unsupported/protocol-incomplete result.
|
||||
|
||||
The Configurator remains a human-operated consumer of the saved-state overlay.
|
||||
The adapter does not start it, automate it, or claim to change its in-memory
|
||||
state.
|
||||
|
||||
## Map
|
||||
|
||||
- [Rules and evidence discipline](rules/evidence-and-safety.md)
|
||||
- [Agent contract: do not invent](rules/agent-contract.md)
|
||||
- [Configuration SQL layers](layers/configuration-storage.md)
|
||||
- [Extension saved-state overlay](extensions/saved-state-overlay.md)
|
||||
- [Common form and BSL module handling](objects/common-form-module.md)
|
||||
- [Object component graph and child selectors](objects/component-graph.md)
|
||||
- [Report object-module carrier](objects/report-object-module.md)
|
||||
- [Payload envelope codec](codecs/payload-envelope.md)
|
||||
- [`__configinfo` map and service atom](codecs/configinfo.md)
|
||||
- [Configurator refresh behaviour](operations/configurator-cache.md)
|
||||
- [Reproducible `upo_test/test2` experiment](experiments/upo-test-test2.md)
|
||||
- [Known dead ends and prohibited shortcuts](research/known-dead-ends.md)
|
||||
- [Template for the next experiment](templates/experiment-record.md)
|
||||
- [Current adapter component map](implementation/adapter-components.md)
|
||||
|
||||
## Maintenance rule
|
||||
|
||||
After every material protocol investigation, record all three outcomes:
|
||||
|
||||
1. proven direction and the exact evidence;
|
||||
2. failed direction and why it failed;
|
||||
3. remaining unknowns and the next safe experiment.
|
||||
|
||||
Keep raw payloads and credentials out of git. Reference private learning
|
||||
artifacts by opaque ID or SHA-1 only.
|
||||
@@ -0,0 +1,35 @@
|
||||
# `__configinfo`: file map and service atom
|
||||
|
||||
## Proven map
|
||||
|
||||
The decoded `E__configinfo` text contains logical file-name pairs:
|
||||
|
||||
```text
|
||||
"<object-guid>.0",<base64 of 20-byte SHA-1>
|
||||
```
|
||||
|
||||
The Base64 value is the SHA-1 of the complete raw `BinaryData` stream for that
|
||||
logical file. Updating a module without replacing this map value produces the
|
||||
Configurator error “Ошибка хеш-версии файла конфигурации”.
|
||||
|
||||
The map rewrite is deterministic and losslessly round-trip proven for the
|
||||
studied extension form module.
|
||||
|
||||
## Service atom: current status
|
||||
|
||||
The root block also contains three observed binary atoms: two 48-byte values
|
||||
and a 32-byte value. The 32-byte value changed across manual saves, including
|
||||
when the module bytes returned exactly to a previous SHA-1. A random mutation
|
||||
of its variable part triggered a platform licensing/crypto error.
|
||||
|
||||
Therefore:
|
||||
|
||||
- preserve all service atoms byte-for-byte during the proven incremental
|
||||
protocol;
|
||||
- do not synthesise, randomise, zero, or “recalculate” them;
|
||||
- do not claim their reverse codec is known;
|
||||
- record new observations in an experiment file before changing this rule.
|
||||
|
||||
The `test2` map-update experiment activated successfully while preserving the
|
||||
existing service atom. This is activation evidence for preservation, not for
|
||||
generation.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Payload envelope codec
|
||||
|
||||
## Observed codec pipeline
|
||||
|
||||
For the studied configuration payloads:
|
||||
|
||||
```text
|
||||
SQL BinaryData
|
||||
→ raw-deflate (or detected alternative envelope)
|
||||
→ UTF-8 text, sometimes BOM
|
||||
→ brace-based 1C serialized value tree / container text
|
||||
```
|
||||
|
||||
The decoder must retain envelope type, original encoding, BOM, line endings,
|
||||
and all unmodified text. An encoder is valid only if an unchanged
|
||||
decode→encode cycle returns byte-identical payload bytes.
|
||||
|
||||
## Lossless transform discipline
|
||||
|
||||
1. Decode source bytes.
|
||||
2. Identify the exact BSL or value-tree slice with a proven extractor.
|
||||
3. Replace only that slice.
|
||||
4. Encode with the original codec metadata.
|
||||
5. Calculate SHA-1 from the final raw stored bytes, never from decoded text.
|
||||
|
||||
Do not canonicalize braces, whitespace, strings, BOM, compression level, or
|
||||
base64 blocks without an independently proven canonical writer.
|
||||
@@ -0,0 +1,72 @@
|
||||
# `upo_test` / `test2` saved-state experiment
|
||||
|
||||
## Scope
|
||||
|
||||
- Test base: `upo_test`
|
||||
- Extension: `test2`
|
||||
- Extension GUID: `fb26cf42-7609-11f1-828f-005056b0d483`
|
||||
- Common form: `t_Форма`
|
||||
- Form GUID: `77494708-43ea-4956-ac3c-199cfb035ad2`
|
||||
- Independently manually edited form: `tt_Форма3`
|
||||
- Form GUID: `99590008-addf-49fa-9ada-24962756d0cf`
|
||||
|
||||
These are experiment identifiers, not a universal hardcoded route.
|
||||
|
||||
## Follow-up cross-extension confirmation (2026-08-13)
|
||||
|
||||
The same logical-file protocol was exercised on a different extension and
|
||||
object class:
|
||||
|
||||
- Extension: `фс_Отчеты`
|
||||
- Extension GUID: `9b11f844-3d08-11f1-8287-005056b0d483`
|
||||
- Object: `Report._ПоступлениеТовара`
|
||||
- Object GUID: `c428f629-785a-4141-b038-f2192bb4580d`
|
||||
- Guarded change: `//Пример - 3` → `//Тест - 3`
|
||||
|
||||
The active root was a hash-keyed `ConfigCAS` record, but decoding it exposed
|
||||
the logical `O` / `O.0` map and the SHA-1 of each active payload. The adapter
|
||||
created exactly `E__configinfo`, `E__O`, `E__O.0`, executed a public
|
||||
`code.write` replacement and reread it. A controlled `apply_and_rollback`
|
||||
passed before `apply_and_verify`. A human then confirmed `//Тест - 3` in the
|
||||
Configurator extension editor.
|
||||
|
||||
This proves the canonical object-module overlay route for this observed
|
||||
extension-root family. The implementation must retain the suffix of the exact
|
||||
resolved BSL stream: a separately diagnosed production route for
|
||||
`Report.УОП_ПечатьЦенниковАссортимента` resolves its manager module as `.2`,
|
||||
not `.0`. This does not authorize a guessed suffix: the selected `O.S` entry
|
||||
and its SHA-1 must be present in the decoded root map. Forms or an unknown
|
||||
root that cannot be decoded into that exact logical map remain unproven.
|
||||
|
||||
## Outcomes
|
||||
|
||||
1. Writing a `.0` module alone made a comment visible after a reload but
|
||||
failed activation with a hash-version error.
|
||||
2. Pairing the module write with the matching `__configinfo` map update made
|
||||
the comment activate into `ConfigCAS`; Configurator cleared
|
||||
`ConfigCASSave` after successful application.
|
||||
3. Building a complete three-file initial overlay while Configurator was
|
||||
closed, then opening and applying it, succeeded for `change-10`.
|
||||
4. A manual save in `tt_Форма3` produced a three-row pending overlay for that
|
||||
form plus `__configinfo`. Incrementally adding `t_Форма` descriptor/module
|
||||
while preserving the existing rows and map entries kept both edits.
|
||||
5. A pending `__configinfo` map can point at a newer active module than an
|
||||
earlier inspection of `ConfigCAS`; selecting the source through the pending
|
||||
map avoids duplicate BSL comments.
|
||||
|
||||
## Failed paths retained as evidence
|
||||
|
||||
- Raw module-only write: invalid collection hash.
|
||||
- Random service-atom bytes: licensing/crypto error.
|
||||
- Treating the active module as authoritative while a pending map exists:
|
||||
duplicate comment insertion.
|
||||
- Assuming UI text means SQL save: the editor buffer can differ from
|
||||
`ConfigCASSave`; verify SQL immediately after saving.
|
||||
|
||||
## Verification after every apply
|
||||
|
||||
1. `ConfigCASSave` for the extension becomes empty.
|
||||
2. Extension root key in `_ExtensionsInfo`/`ConfigCAS` changes to the new
|
||||
`__configinfo` SHA-1.
|
||||
3. Active `ConfigCAS` contains the requested BSL text.
|
||||
4. The active map points to the SHA-1 of the active module bytes.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Extension saved-state overlay (`ConfigCASSave`)
|
||||
|
||||
> **Deployment and integration-test target:** `adapter-1c-mcp` runs on
|
||||
> `docker.cin.su`. Use that host for deployment and live adapter checks;
|
||||
> `test-docker` is staging only and requires an explicit request.
|
||||
|
||||
## Canonical object-module overlay: activation evidence
|
||||
|
||||
For extension GUID `E` and object GUID `O`, the overlay uses:
|
||||
|
||||
```text
|
||||
E__configinfo
|
||||
E__O
|
||||
E__O.S
|
||||
```
|
||||
|
||||
This route is now human-confirmed in two independently selected extension
|
||||
object-module cases on `upo_test`:
|
||||
|
||||
| Extension | Object | Public test | Human confirmation |
|
||||
|---|---|---|---|
|
||||
| `test2` | Common form/module fixture | prior `change-10` experiment | Configurator applied overlay into `ConfigCAS` |
|
||||
| `фс_Отчеты` | `Report._ПоступлениеТовара` object module | `//Пример - 3` → `//Тест - 3` | Configurator displayed `//Тест - 3` in the extension editor |
|
||||
|
||||
The descriptor and module are separate objects. A pending extension may contain
|
||||
only rows changed manually by the user; the root `__configinfo` map can still
|
||||
refer to unchanged active parts. An adapter must preserve those rows and all
|
||||
their map entries.
|
||||
|
||||
For the separately observed hash-keyed overlay, the equivalent boundary is the
|
||||
live extension `root_cas_key`: an automatic first-write copy must include that
|
||||
root manifest together with the selected object parts. A leaf module key alone
|
||||
is not a complete working-copy selection boundary.
|
||||
|
||||
## Hash-keyed first-write status
|
||||
|
||||
In `upo_test` / `фс_Отчеты`, copying the complete evidenced hash-key group
|
||||
from `ConfigCAS` to `ConfigCASSave` under unchanged hash names produced a
|
||||
byte-for-byte SQL readback, but Configurator continued to read the active
|
||||
`ConfigCAS` module. Therefore a same-name hash copy is **not** a working-copy
|
||||
protocol.
|
||||
|
||||
The active extension root has since been decoded as the equivalent logical
|
||||
file map: it contains `"<object-guid>[.suffix]",Base64(SHA-1(payload))`
|
||||
pairs, including the target descriptor and the selected BSL module. For the evidenced
|
||||
object-module family the initial overlay maps exactly three active files to:
|
||||
|
||||
```text
|
||||
root manifest -> E__configinfo
|
||||
object descriptor -> E__O
|
||||
object `.S` module -> E__O.S, where `.S` is the suffix of the exact resolved
|
||||
BSL stream (for example `.0` or `.2`)
|
||||
```
|
||||
|
||||
The adapter must reject any incomplete route and must never fall back to
|
||||
unchanged hash names. The map and all service atoms are copied verbatim on the
|
||||
first overlay; subsequent writes update only the proven file-SHA reference.
|
||||
|
||||
### Exact prepare/write algorithm
|
||||
|
||||
1. Resolve the extension, public object `O`, active descriptor and active `.S`
|
||||
BSL stream from the extension manifest.
|
||||
2. Decode the selected active root. Require exactly one map entry for `O` and
|
||||
exactly one for the selected `O.S`; require their SHA-1 values to equal the selected
|
||||
active descriptor/module payloads.
|
||||
3. If the overlay is absent, atomically copy only those three sources as
|
||||
`E__configinfo`, `E__O`, and `E__O.S`. Do not copy the whole extension.
|
||||
4. If it exists, preserve pending rows and maps; never overwrite another
|
||||
change. Prepare may add only missing object parts.
|
||||
5. Replace BSL only after the exact old fragment, source SHA-1, extension,
|
||||
public object and module stream agree. For an object module, update the one
|
||||
`O.S` SHA-1 value in `E__configinfo` in the same transaction and preserve
|
||||
service atoms byte-for-byte.
|
||||
6. Re-read the BSL and both changed rows. `apply_and_rollback` must restore
|
||||
the module and remove adapter-created first-overlay rows.
|
||||
|
||||
`code.write` callers provide only public selectors and the replacement. The
|
||||
adapter owns storage mapping, preparation, paired update and rollback.
|
||||
|
||||
## Rejected approaches (retain as regression hazards)
|
||||
|
||||
- Copying `ConfigCAS` hash rows to `ConfigCASSave` under the same names. It
|
||||
produced correct SQL readback but Configurator ignored it for `фс_Отчеты`.
|
||||
- Writing only the BSL module payload. The map continues to point to the old
|
||||
SHA-1 and Configurator reports a collection/hash-version error.
|
||||
- Generating `__configinfo`, its service atoms, or logical file mappings from
|
||||
names alone. The adapter must first decode the actual selected root map.
|
||||
- Replacing the entire compressed module container. Only the declared BSL
|
||||
prefix codec is allowed; opaque stream tail bytes must remain unchanged.
|
||||
- Resolving an already selected object-module path through generic metadata
|
||||
path traversal. Its module suffix is a BSL container, so this can fail before the
|
||||
saved-state writer sees the exact module route.
|
||||
|
||||
## Proven incremental write protocol
|
||||
|
||||
For a form module change:
|
||||
|
||||
1. Read the current `E__configinfo` from `ConfigCASSave` if it exists;
|
||||
otherwise derive a complete initial overlay from active `ConfigCAS`.
|
||||
2. Resolve the form descriptor and module hashes from that map.
|
||||
3. Patch the module with a unique BSL anchor and lossless payload codec.
|
||||
4. Replace exactly the Base64(SHA-1(raw module bytes)) value paired with
|
||||
logical name `O.0` in `E__configinfo`.
|
||||
5. Preserve every unrelated map entry and service atom byte-for-byte.
|
||||
6. In one transaction insert missing `E__O`/`E__O.0` rows and update
|
||||
`E__configinfo`, with compare-and-set SHA-1 preconditions.
|
||||
|
||||
The adapter core exposes a pure `build_extension_saved_state_pair_plan` helper
|
||||
for steps 3–5. It refuses a plan when the ConfigInfo map does not reference the
|
||||
current saved stream, so a later transaction cannot silently overwrite a
|
||||
divergent human overlay.
|
||||
|
||||
For an already existing single-part pending stream, the paired writer locks the
|
||||
module and `__configinfo`, verifies both preconditions, writes both payloads
|
||||
and their `DataSize` values in one transaction, keeps independent rollback
|
||||
evidence, and verifies both rows afterwards. `__configinfo` itself is never a
|
||||
primary editable stream. Missing overlay rows still use the separate prepare
|
||||
route before this writer may update them.
|
||||
|
||||
This protocol was activation-proven in the `test2` experiment. It is not yet
|
||||
a universal proof for every 1C platform version or every extension object
|
||||
class; new classes require their own evidence record.
|
||||
|
||||
## Important overlay behaviour
|
||||
|
||||
An external SQL overlay write does not set the Configurator’s in-memory dirty
|
||||
flag. Its visibility therefore depends on the current session. See
|
||||
[Configurator refresh behaviour](../operations/configurator-cache.md).
|
||||
@@ -0,0 +1,24 @@
|
||||
# Current adapter component map
|
||||
|
||||
This map says where to extend the project without losing protocol boundaries.
|
||||
It is not a substitute for reading the linked source before editing it.
|
||||
|
||||
| Component | Location | Responsibility | Evidence boundary |
|
||||
|---|---|---|---|
|
||||
| RPC/service orchestration | `plugins/1c/connector/adapter_1c_server.py` | Base resolution, live SQL calls, saved-state plans/apply, verification, backups | Must keep active layers read-only |
|
||||
| Payload codec | `plugins/1c/parser/payload.py` | Envelope detection, decompression, lossless encode metadata | Require byte-identical unchanged round trip |
|
||||
| Brace parser | `plugins/1c/parser/*` | Decode 1C serialized brace/value trees | A parse tree is not semantic proof by itself |
|
||||
| Extension routes | `plugins/1c/parser/extensions.py` and adapter extension resolvers | `_ExtensionsInfo` and `ConfigCAS` manifest routes | Never infer part role from suffix alone |
|
||||
| DBNames mapping | `plugins/1c/parser/dbnames.py` | Metadata-to-physical SQL role evidence | Names/roles must come from live DBNames evidence |
|
||||
| Storage access | adapter storage helpers | Single/multi-part row reads, hashes, paired extension map updates, compare-and-set and backups | Writes only to allowed saved-state tables |
|
||||
| Policy | `plugins/1c/connector/policies/` | Runtime boundary and base-access rules | Policy must match tested capability, not aspiration |
|
||||
| Regression tests | `tests/1c/` and `scripts/smoke_1c_*` | Preserve routes and observed protocol rules | Add fixture/test before promoting a decoder rule |
|
||||
|
||||
## Required update order for a new object type
|
||||
|
||||
1. Add an experiment record with before/after SQL evidence.
|
||||
2. Add/extend a decoder fixture and test.
|
||||
3. Add the narrow codec or route resolver.
|
||||
4. Add a writer only after lossless round-trip, paired-index handling, rollback,
|
||||
and human activation verification.
|
||||
5. Update the relevant topic document and this map if ownership changed.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Configuration storage layers
|
||||
|
||||
The following SQL tables have the same observed storage-row shape:
|
||||
|
||||
`FileName`, `Creation`, `Modified`, `Attributes`, `DataSize`, `BinaryData`,
|
||||
`PartNo`.
|
||||
|
||||
| Layer | Role | Direct adapter writes |
|
||||
|---|---|---|
|
||||
| `Config` | Active base configuration | Forbidden |
|
||||
| `ConfigSave` | Pending base configuration changes | Controlled `upo_test` only |
|
||||
| `ConfigCAS` | Active extension content-addressed store | Forbidden |
|
||||
| `ConfigCASSave` | Pending extension configuration overlay | Controlled `upo_test` only |
|
||||
|
||||
`PartNo` must be read and preserved. The currently proven writer handles a
|
||||
single-part stream only; a multi-part stream is unsupported until a
|
||||
table-aware round-trip codec exists.
|
||||
|
||||
## Addressing rules
|
||||
|
||||
Base `Config` objects are commonly addressed by metadata GUID. Extension active
|
||||
objects are reached through `_ExtensionsInfo` → extension root in `ConfigCAS`
|
||||
→ root manifest → object part SHA-1 key. Do not infer a semantic role from a
|
||||
suffix such as `.0`; inspect the payload and route evidence.
|
||||
|
||||
For normal content-addressed rows, `ConfigCAS.FileName` was observed to equal
|
||||
SHA-1 of the stored bytes. Always compute and compare the hash rather than
|
||||
trusting the name: an activation experiment left a legacy alias whose name was
|
||||
an old key while its bytes had the new SHA-1.
|
||||
|
||||
## Write sequence
|
||||
|
||||
1. Resolve public object/form/module against live SQL.
|
||||
2. Read active bytes and any existing saved-state rows.
|
||||
3. Prepare only missing saved rows; never overwrite a user’s existing rows.
|
||||
4. Encode the changed stream losslessly.
|
||||
5. Update every proved companion index in the same SQL transaction.
|
||||
6. Read back and validate hashes and semantic exact-match count.
|
||||
7. Tell the human which Configurator scope to reload.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Common form modules
|
||||
|
||||
## Proven form facts
|
||||
|
||||
The `test2` common forms `t_Форма` and `tt_Форма3` are distinct objects with
|
||||
distinct GUIDs and descriptors. A label must be decoded from the descriptor;
|
||||
do not shorten or normalize it by guesswork (`tt_Форма3` is not `t_Форма3`).
|
||||
|
||||
A form `.0` payload can contain more than a simple standalone BSL string. The
|
||||
adapter must use the proven container extractor and preserve all non-BSL
|
||||
segments, including form settings and command metadata.
|
||||
|
||||
## Module patch rules
|
||||
|
||||
- Obtain the BSL region from the decoded container, not from a global text
|
||||
search over compressed bytes.
|
||||
- Count the requested anchor in the relevant BSL region.
|
||||
- Replace a unique exact fragment once; report ambiguity otherwise.
|
||||
- Re-encode using the source payload’s detected codec and line-ending style.
|
||||
- Read back, re-extract BSL, and verify the target occurrence count.
|
||||
|
||||
## Pending-state resolution
|
||||
|
||||
When `ConfigCASSave` contains a `__configinfo` map, that map is authoritative
|
||||
for the pending overlay even if the corresponding module row is absent. The
|
||||
active `ConfigCAS` source must be selected through the saved map before a new
|
||||
delta row is created. Reading only active content can incorrectly conclude
|
||||
that a pending comment is absent and cause a duplicate insertion.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Граф составляющих объекта конфигурации
|
||||
|
||||
Объект конфигурации — это корень, а не минимальная единица работы. Его
|
||||
составляющие: модуль объекта, формы и их модули, макеты, схема компоновки
|
||||
данных (СКД), а после декодирования СКД — наборы данных, запросы, поля,
|
||||
ресурсы и варианты. Для записи нужен адрес именно составляющей и доказанный
|
||||
физический носитель этой составляющей.
|
||||
|
||||
## Публичная инвентаризация
|
||||
|
||||
`metadata.object.components` — read-only фасад над уже доказанными SQL
|
||||
декодерами. Он принимает обычный селектор владельца (`ref` либо `kind` и
|
||||
`name`, при необходимости `extension`) и возвращает граф:
|
||||
|
||||
- корень `metadata_object`;
|
||||
- только реально найденные `module`, `form`, `template` и `scd`;
|
||||
- публичные `path` и `read_selector` каждого потомка;
|
||||
- `unresolved` для областей, которые не были подтверждены.
|
||||
|
||||
Метод не создаёт потомок потому, что он обычно есть у такого типа объекта.
|
||||
Например, пустой ответ `metadata.object.modules` у общей формы означает
|
||||
«модуль этим маршрутом не найден», а не повод назвать форму модулем.
|
||||
|
||||
Пример запроса:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "metadata.object.components",
|
||||
"payload": {
|
||||
"base_id": "upo_test",
|
||||
"extension": "test2",
|
||||
"ref": "Report.tt_Отчет",
|
||||
"include_storage": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`read_selector` можно передать следующему read-only методу. Это не является
|
||||
разрешением на запись: запись выбирает компонент по его `path`, повторно
|
||||
подтверждает конкретный carrier/stream и разрешается только для семейства
|
||||
контейнеров с доказанным byte-preserving кодеком.
|
||||
|
||||
## Иерархия и кодеки
|
||||
|
||||
Логический BSL один и тот же независимо от владельца, но его физический
|
||||
носитель может различаться. Поэтому не нужны отдельные эвристики «для формы»
|
||||
и «для отчёта»: нужен реестр семейств carrier-кодеков. Один кодек применяется
|
||||
к нескольким типам объектов лишь после доказательства одинаковых границ,
|
||||
непрозрачных атомов и round-trip проверки.
|
||||
|
||||
Текущий пример: модуль общего формы в `upo_test/test2` имеет доказанный
|
||||
write-кодек saved-state; обнаруженный поток модуля отчёта — только
|
||||
read-only structural codec. Второй компонент может быть найден и прочитан,
|
||||
но не получит разрешение на SQL-запись, пока его служебный хвост не будет
|
||||
декодирован.
|
||||
@@ -0,0 +1,115 @@
|
||||
# Модуль объекта отчёта в расширении
|
||||
|
||||
Статус: чтение, точное разрешение владельца и контролируемая запись короткого
|
||||
фрагмента поддержаны для доказанного hash-keyed saved-state маршрута.
|
||||
|
||||
Наблюдение в `upo_test`, расширение `test2`, отчёт `tt_Отчет`: сохранённый файл
|
||||
`<extension-guid>__<report-guid>.0` является `raw_deflate` контейнером из пяти
|
||||
потоков. BSL-модуль расположен в потоке `4`.
|
||||
|
||||
Поток начинается читаемым UTF-8-комментарием, но последующий текст содержит
|
||||
нулевые байты и смешанное представление символов. Общий потоковый декодер
|
||||
позволяет найти комментарий, однако его обратное кодирование меняет байты
|
||||
неизменённого хвоста BSL. Экспериментальная запись показала это в Конфигураторе
|
||||
и была немедленно восстановлена из парной резервной копии.
|
||||
|
||||
Правило: наличие читаемого BSL-фрагмента не доказывает возможность записи.
|
||||
Для потока с `NUL` адаптер возвращает
|
||||
`mixed_encoding_module_stream_unsupported` и не создаёт SQL-изменений.
|
||||
Это не означает, что для каждого отчёта нужен свой кодер: один доказанный
|
||||
кодек может обслуживать все модули с одинаковым физическим носителем.
|
||||
|
||||
Два ручных образца определили безопасную границу записи: редактируется только
|
||||
объявленный UTF-8-префикс, а непрозрачный хвост и остальные потоки сохраняются
|
||||
побайтно. Для hash-keyed overlay рабочий слой создаётся доказанным копированием
|
||||
подтверждённых ключей `ConfigCAS → ConfigCASSave`; `__configinfo` для него не
|
||||
создаётся и не предполагается.
|
||||
|
||||
Текущая реализация `parser.cas_payload.stream_blocks_with_data` ищет похожие
|
||||
заголовки регулярным выражением по всему распакованному буферу. В потоке
|
||||
отчёта такие последовательности встречаются и внутри данных, поэтому это
|
||||
эвристика для чтения, а не структурный декодер. Нельзя использовать её индекс
|
||||
потока как основание для обратной записи.
|
||||
|
||||
Структурный read-only декодер `decode_declared_utf8_bsl_prefix` подтверждён на
|
||||
этом образце: пять последовательных блоков; пятый имеет `declared_1 = 68` и
|
||||
`declared_2 = 512`. Первые 68 байт — UTF-8 BOM и точный BSL-текст, оставшиеся
|
||||
444 байта — непрозрачный служебный хвост. Декодер вернул только:
|
||||
`// protocol-report-baseline-1` и `// protocol-report-manual-change-4`.
|
||||
|
||||
## Пара ручных образцов `2 → 3`
|
||||
|
||||
Образцы `samples/manual-change-2.json` и `samples/manual-change-3.json`
|
||||
содержат raw-deflate байты, сохранённые человеком в Конфигураторе. В
|
||||
распакованном контейнере длиной 1283 байта замена цифры `2` на `3` изменила
|
||||
BSL ровно в смещении `838` (`0x32 → 0x33`). Одновременно платформа изменила
|
||||
шесть служебных диапазонов: `110..113`, `230..252`, `437..464`, `590..593`,
|
||||
`598..601`, `716..719`. Трёхбайтовое значение повторяется в нескольких
|
||||
местах, а два диапазона содержат связанные Base64-представления.
|
||||
|
||||
Это доказывает, что нельзя перепаковывать поток общим writer'ом. Отдельный
|
||||
fixed-width кодек меняет только первые `declared_1` байт: короткий текст
|
||||
дополняется пробелами внутри этого поля, хвост и размер члена не меняются.
|
||||
Рост префикса или структурная правка процедуры явно отклоняются.
|
||||
|
||||
## Полный объявленный поток: переменная длина
|
||||
|
||||
Нельзя переносить ограничение fixed-width с описанного выше носителя на все
|
||||
объектные BSL-модули. На рабочем маршруте `upo / фс_Отчеты /
|
||||
Report.УОП_ПечатьЦенниковАссортимента / .2 / stream:4` подтверждён другой
|
||||
контейнер: у выбранного BSL-потока `declared_1 == declared_2 == 36101` и
|
||||
`opaque_tail_bytes == 0`. Это полный UTF-8 поток, а не префикс перед
|
||||
непрозрачными данными.
|
||||
|
||||
Для такого носителя адаптер использует обычный структурный stream writer:
|
||||
он меняет текст, пересобирает оба объявленных размера в заголовке и сдвигает
|
||||
только последующие байты контейнера. Локальная обратная проверка целевой
|
||||
замены `НоваяСтрока.Выбран = Истина;` на более длинный фрагмент дала размер
|
||||
потока `36101 → 36198`, новый заголовок `36198/36198`, одно новое вхождение и
|
||||
нулевое старое. Все байты до заголовка выбранного потока сохранились.
|
||||
|
||||
Правило выбора кодека: fixed-width применяется **только** если доказан
|
||||
ненулевой непрозрачный хвост; если `declared_1 == declared_2` и хвоста нет,
|
||||
безопасна контролируемая замена переменной длины через структурный writer.
|
||||
Неизвестный или частично декодированный контейнер остаётся заблокированным,
|
||||
а не переводится в переменную длину по предположению.
|
||||
|
||||
## Правило публичного маршрута
|
||||
|
||||
Если объектный модуль состоит только из комментариев, это всё равно BSL-модуль:
|
||||
у него нет маркеров `Процедура`/`Функция`, но его наличие подтверждает
|
||||
структурный UTF-8-префикс в потоке. Адаптер обязан вернуть владельца и точный
|
||||
селектор чтения, не заставляя клиента искать поток. При записи он обязан
|
||||
использовать только fixed-width кодек, а не общий stream writer, который
|
||||
перезаписывает непрозрачный хвост. Парное обновление `__configinfo` допустимо
|
||||
только в отдельно подтверждённом каноническом layout.
|
||||
|
||||
## Повтор `code.write` после успешной записи
|
||||
|
||||
Повтор одного и того же публичного `code.write` не является новой операцией.
|
||||
До автоматической подготовки `ConfigCASSave` адаптер читает указанную
|
||||
процедуру в `effective_working`. Если старого фрагмента уже нет, а точный
|
||||
новый фрагмент присутствует ровно один раз в этой же процедуре, результат —
|
||||
`status: already_applied`, `applied: false`. В этом случае запрещены и
|
||||
подготовка saved-state, и новая SQL-запись.
|
||||
|
||||
Это правило предотвращает опасный путь: повторный запрос нельзя начинать с
|
||||
активного `ConfigCAS`, потому что его копирование способно заново построить
|
||||
рабочую копию из доизменённого источника и скрыть факт уже выполненной
|
||||
операции. Если оба фрагмента отсутствуют, новый фрагмент встречается
|
||||
несколько раз либо процедура не подтверждена, идемпотентность не
|
||||
предполагается: применяется обычная безопасная ошибка `not_found`/
|
||||
`ambiguous` или диагностика маршрута.
|
||||
|
||||
## Цепочка версий `2 → 3 → 4`
|
||||
|
||||
Третий live-SQL образец подтвердил повторяемую часть протокола. 20-байтовое
|
||||
Base64-поле в каждой новой версии равно SHA-1 сырого файла предыдущей версии:
|
||||
запись `3` хранит SHA-1 записи `2`, а запись `4` — SHA-1 записи `3`. Это
|
||||
доказанная ссылка версии, а не случайный текст. Его контрольный SHA-1:
|
||||
`fc84f0a9ef17034f8d82f44c5f9b07064864b524`.
|
||||
|
||||
Рядом расположен 16-байтовый токен, который меняется при каждом сохранении и
|
||||
дублируется фрагментами в трёх служебных местах. Алгоритм его создания не
|
||||
декодирован: адаптер его не генерирует и не изменяет. Его нельзя считать
|
||||
основанием для создания или изменения `__configinfo` в hash-keyed overlay.
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"schema": "onec_report_module_stream_sample.v1",
|
||||
"origin": "Configurator manual save in upo_test/test2/tt_Отчет; no adapter write",
|
||||
"logical_change": "// protocol-report-manual-change-2",
|
||||
"physical_file_name": "<extension-guid>__<report-guid>.0",
|
||||
"compression": "raw_deflate",
|
||||
"raw_sha1": "89827a3c7fa07ae50a268d20a7cee34195d1d7a7",
|
||||
"raw_bytes": 618,
|
||||
"inflated_sha1": "6385a80972841eb8a97df43596ed15dd16966495",
|
||||
"inflated_bytes": 1283,
|
||||
"raw_base64": "7VLJbhNBEG2iPlnyBXHgBKMRByDTcc/S0zNCBtnEie2MvI2XwQJFPat3J/ZkV4TCgV/gCge+ggMfwE9w4MaBTzDtbLIFQYgzT+rq6q5+9apVNZvNXoMVAG6BCyQT+ByyIVw7NLyAkExs8idv+Zpx2kdO+7Zy4V/RFCxcOws0of/q4cvcCnj/+OzRfJ+jC0YgBOMlVRwKl+wl+o9Pn09USZawJIoSPrUyL5qqOQ39SafeLxxF5YlbpLvtDc9JJhMZfdUYD+L8gdHqWa2CWqNuX8aHekQ766GjlUqpIKodbzQcJ5M+lZKJE1MSZeK6MnMZ0onMkKYGKnJVipFHNdPHpoI9F4tSs1jp9OS6TTZ9u0GmTlVtDtrtmm9YuTTPYRjEoExHGtVVpOnYQKYcYkRNrCvU1TSdeaJU2S8PGo2jdaVXtVvTeF1TUsNi02rtVKp/mWONV7JVydojpRo6qtVNPW8acbe+29JLBWNvnoXyqjXKufwj/Dcm0RHzVA/JpumFLlYJ8xVROp760f6w5tml4n6l1GnQYSNbdFyl0MN/yHHd56vxUJbG46q/i31+AGwQgwkIAANDflrst2bc2G9dkgMiK4y5SP6H6Yq53iG3S2raTWqplLAzGcdjbzxAk2BnPImRy6bBoDsK5uq/CQ/ZaI8NkNdhoyhACtY9X2WUiFLZjywrzvhReJDP94ZRJqjn28pqPlcz0qdwjZcUg21wD2ZgGj6FCrcYlqHA/SfQgoIgfN2y30l3efzZ5R09f4dhlvuLvC1ILnkGvMNtGd7mUQJz8P4vTMLPBJrwe/YNl/jwxT4TBPAf5/gJ"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"schema": "onec_report_module_stream_sample.v1",
|
||||
"origin": "Configurator manual save in upo_test/test2/tt_Отчет; no adapter write",
|
||||
"logical_change": "// protocol-report-manual-change-3",
|
||||
"physical_file_name": "<extension-guid>__<report-guid>.0",
|
||||
"compression": "raw_deflate",
|
||||
"raw_sha1": "357c39a55e8f66c3efd8f7aac968a4db5d5eb5fb",
|
||||
"raw_bytes": 620,
|
||||
"inflated_sha1": "eb72cadfe12f68969cd278901a6f83e627ee1a53",
|
||||
"inflated_bytes": 1283,
|
||||
"raw_base64": "7VLLbhMxFDWVV5GyQSxYwWjEApRxa8+MxzOqAkrV0HQ6ah6TVyMQ8jyTNMmkybSlVBWCBb8AWxZ8BQs+gBV/wIIdCz4huE8lgiLEmiP5+trX555r3TubzV6CJQBugHNkM/gMxJSuHBadQ8pmNsSTN2LNBO2DoH1bOvcvaSqWrpw5mrT79P6T4hKofHn34HQ/RQ+MQASSBVUcSRfsBfqPj5+ONYUoWJFlBZ84hZ2mZk2jYNKt724exeWJZ7O9zmO/nc1mCkbOTAZp6dBs9Z3WplZj3i6h+lGQs8l2vZ0YNNnTUr5hr0/zJ0o2c2wpMqGeR7jHkUEJR7oWasjTGEY+060AWyr2PSwrTbvS7ZO6SzcCt0Gn7arWHHQ6tcB0inmRwzSpybiBdGZoSDewiSwSYcQsbKjM03WD+7JSOSgPGo2jdbVfdVvTdF1XV4Z202mNK9W/zLEsKunt2EallIvD/caWneB4bLJ+tdOuEcMXWZioWmeCKz4ifmNRA3Ff8xGxLD/ysEZ5oMrKi2kQHwxrvrttH1S2uw02bKzZbU/d7OM/5Ljq8+V4qAvjcdnf+T7fAy5IwQSEgIOhOM33Wzev7behkJASlXMPkX+YrlToPRd2QU2/Tm1lRRpPkjTxkwGahONkkiKPT8NBbxSeqv8mPOSjfT5AfpeP4hBp2PADjTMqK+Ugdpy0EMTRYanUH8aFsF7qqLlSsWbmT+CyKCkFz8AdWIB5+BCqwmJYhpLwV6EDJUn6uuW+VW6L+KOLO3b2DsM14c/ztiC94JnwlrBleFNEKSzCu78wqThTaMHva6+FxPvP7itJAv9xhp8="
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Configurator refresh behaviour
|
||||
|
||||
## Observed session model
|
||||
|
||||
`ConfigCASSave` is an SQL overlay, but writing it outside Configurator does not
|
||||
set Configurator’s in-memory changed/dirty state.
|
||||
|
||||
Observed consequences:
|
||||
|
||||
| State before adapter write | Minimal human action after write |
|
||||
|---|---|
|
||||
| Object already existed in saved-state | Close and reopen that object |
|
||||
| Adapter created the first pending object for an extension | Close and reopen the extension |
|
||||
| Adapter created the first pending object for base configuration | Close and reopen the configuration |
|
||||
|
||||
If the user manually edits and saves any object in an extension, Configurator
|
||||
marks the extension changed; reopening another object can then load its
|
||||
`ConfigCASSave` overlay.
|
||||
|
||||
## Required adapter response
|
||||
|
||||
Write results should return machine-readable guidance:
|
||||
|
||||
```json
|
||||
{
|
||||
"configurator_refresh": {
|
||||
"required": true,
|
||||
"scope": "object|extension|configuration",
|
||||
"action": "close_reopen_object|close_reopen_extension|close_reopen_configuration"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This guidance does not claim that the adapter controls Configurator; it merely
|
||||
reports the minimum observed reload boundary.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Known dead ends and prohibited shortcuts
|
||||
|
||||
## Do not repeat
|
||||
|
||||
- Do not write only a module `.0` row: `__configinfo` then references stale
|
||||
bytes and activation fails.
|
||||
- Do not use random, zeroed, copied-from-unrelated, or guessed HashVersion
|
||||
service atoms. A controlled random test produced a licensing/crypto error.
|
||||
- Do not write `Config` or `ConfigCAS` directly, even in tests.
|
||||
- Do not use a suffix such as `.0` as proof of “object module”.
|
||||
- Do not infer an object name from a GUI tree label, table suffix, or an
|
||||
approximate Russian name.
|
||||
- Do not overwrite all saved-state rows when adding a delta: preserve user
|
||||
work in other objects and every map entry.
|
||||
- Do not treat an open Configurator screen as SQL evidence.
|
||||
|
||||
## Open questions
|
||||
|
||||
- The generation algorithm and ownership of the 32-byte `__configinfo`
|
||||
service atom are unknown. Preservation is proven for the studied flow;
|
||||
generation is not.
|
||||
- Multi-part storage streams need a dedicated row-layout codec.
|
||||
- The extension protocol must be reproduced on another object class and a
|
||||
second platform build before being declared generally supported.
|
||||
- Configurator’s in-memory dirty-state implementation is inferred from
|
||||
behaviour, not decoded from platform source. Only the reload guidance is
|
||||
operationally relied upon.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Contract for an agent using the 1C SQL adapter
|
||||
|
||||
The agent is a consumer of evidence returned by the adapter. It must never
|
||||
turn a plausible interpretation into a fact.
|
||||
|
||||
## Fundamental adapter rule
|
||||
|
||||
The adapter is a **SQL codec**, not an expert system for 1C. It reads and
|
||||
writes only according to the versioned configuration-storage specification
|
||||
that has been decoded from live SQL and recorded in this knowledge base.
|
||||
It may expose a semantic name only when that mapping is proven by the decoder.
|
||||
For an unknown carrier, field, child object, byte range, checksum, or service
|
||||
atom, the only valid result is `unsupported`, `partial`, or `ambiguous` with
|
||||
the observed evidence. It must not synthesize a structure, BSL, or value to
|
||||
make an operation appear complete.
|
||||
|
||||
## Required behaviour
|
||||
|
||||
- Start from a public 1C name/ref supplied by the user.
|
||||
- Ask the adapter to resolve the live route; internal GUIDs, SQL numbers and
|
||||
file names remain adapter implementation details.
|
||||
- Use public `code.read`, `code.search`, and `code.write` for normal BSL work.
|
||||
Never pass or request `ConfigCAS`, `ConfigCASSave`, a payload hash, a
|
||||
canonical saved filename, or a stream index. Those are diagnostic evidence,
|
||||
not an agent-facing selector contract.
|
||||
- Read the target bytes before proposing any edit.
|
||||
- Quote the exact proven fragment, its count, and the selected layer.
|
||||
- For a write, require a plan/preflight and retain the returned rollback and
|
||||
refresh guidance.
|
||||
- State `unknown`, `ambiguous`, or `protocol_incomplete` when evidence is
|
||||
absent. Ask for a larger fragment or a human Configurator action instead of
|
||||
guessing.
|
||||
|
||||
## Forbidden behaviour
|
||||
|
||||
- Invent BSL procedures, form controls, field paths, joins, storage tables,
|
||||
module streams, extension ownership, or `__configinfo` atoms.
|
||||
- Claim that a SQL saved-state edit is active before active-layer verification.
|
||||
- Claim a repository lock merely because an adapter request was recorded.
|
||||
- Tell the user that the Configurator UI has refreshed unless the required
|
||||
close/reopen boundary was completed by the human.
|
||||
- Write directly to active configuration or application tables.
|
||||
- Work around a public-route failure by retrying against an internal module
|
||||
reference. Report the public `not_found`, `ambiguous`, `unsupported`, or
|
||||
`protocol_incomplete` result so the adapter can be corrected.
|
||||
|
||||
## Write-result language
|
||||
|
||||
Use the adapter’s `configurator_refresh` object verbatim in human-facing
|
||||
instructions. Do not collapse `object`, `extension`, and `configuration` into
|
||||
the same generic “restart” advice.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Evidence and safety rules
|
||||
|
||||
## Evidence levels
|
||||
|
||||
| Level | Meaning | Permitted use |
|
||||
|---|---|---|
|
||||
| Observed | Read from live SQL once | Diagnosis only |
|
||||
| Reproduced | Seen in independent before/after saves | Decoder rule candidate |
|
||||
| Round-trip proven | Decode → unchanged encode returns identical bytes | Safe read/transform component |
|
||||
| Activation proven | A human Configurator applied it and active SQL verified it | Controlled `upo_test` writer component |
|
||||
|
||||
No rule may be promoted because a name, suffix, or payload shape “looks right”.
|
||||
|
||||
## Codec boundary
|
||||
|
||||
The configuration-storage specification is the adapter's sole authority for
|
||||
decoding and encoding. A writer is enabled only when the relevant version of
|
||||
that specification defines every changed byte and every dependent integrity
|
||||
atom, and round-trip evidence proves the encoder. Any remaining opaque atom is
|
||||
preserved byte-for-byte; if a requested edit requires changing it, the write is
|
||||
unsupported until the specification is extended by a controlled experiment.
|
||||
|
||||
## Allowed mutation boundary
|
||||
|
||||
- The adapter runtime uses SQL only.
|
||||
- `upo_test` may receive controlled writes to `ConfigSave` and
|
||||
`ConfigCASSave` only.
|
||||
- `Config`, `ConfigCAS`, and application data are never direct write targets.
|
||||
- A write must have a live target resolution, optimistic SHA-1 precondition,
|
||||
reversible evidence, atomic transaction, and readback verification.
|
||||
- Repository coordination is a separate policy; an adapter marker is not a
|
||||
native repository lock.
|
||||
|
||||
## Exact edits
|
||||
|
||||
For BSL fragment replacement, provide one of:
|
||||
|
||||
- an old fragment occurring exactly once;
|
||||
- a larger unique surrounding fragment;
|
||||
- a proven structural container path/offset plus original SHA-1.
|
||||
|
||||
If a fragment occurs zero or more than once, do not choose arbitrarily. Return
|
||||
the count and candidate contexts. Deletion follows the same rule.
|
||||
|
||||
## What an agent must report
|
||||
|
||||
Every proposal and applied result must state:
|
||||
|
||||
- active and saved layers used;
|
||||
- public target and SQL evidence retained internally;
|
||||
- original and new SHA-1 values;
|
||||
- paired files changed;
|
||||
- exact-match count;
|
||||
- rollback reference;
|
||||
- Configurator refresh guidance.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Protocol experiment record template
|
||||
|
||||
Create one file per material experiment under `experiments/`.
|
||||
|
||||
```markdown
|
||||
# <date> — <short target and action>
|
||||
|
||||
## Scope
|
||||
- Base and classification:
|
||||
- Extension/object public names:
|
||||
- Runtime/platform build:
|
||||
- Authority for mutation:
|
||||
|
||||
## Before
|
||||
- Active source table/key/SHA-1:
|
||||
- Saved-state files and SHA-1:
|
||||
- Relevant descriptor/map entries:
|
||||
|
||||
## Exact action
|
||||
- Public target resolution evidence:
|
||||
- Old fragment / structural selector and occurrence count:
|
||||
- Payload codec and round-trip result:
|
||||
- Paired files written in one transaction:
|
||||
|
||||
## After SQL evidence
|
||||
- Readback SHA-1 values:
|
||||
- Map/reference validation:
|
||||
- Unrelated pending files preserved:
|
||||
|
||||
## Human Configurator verification
|
||||
- Reload action:
|
||||
- Visible result:
|
||||
- Apply result:
|
||||
- Active/saved postcondition:
|
||||
|
||||
## Outcome
|
||||
- Proven fact:
|
||||
- Failed hypothesis:
|
||||
- Remaining unknown:
|
||||
- Follow-up regression fixture/test:
|
||||
```
|
||||
Reference in New Issue
Block a user