Initial project import
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user