# Golden `.sientia` fixtures Binary conformance vectors for `laborious/utils/bundle/`. They are **bytes the producer's own code emitted**, not bytes this repository knows how to write: there is no production writer here (change `import-model-workflow`, design D1). If the producer's layout moves, the reader's tests fail against these files instead of failing in production. | File | What it is | |---|---| | `golden_model_v3.sientia` | `format_version` 1 bundle, 110767 bytes, plaintext zip 110569 bytes — **two chunks**, so `MESSAGE`/`FINAL` framing is exercised by the golden fixture itself | | `golden_model_v3.metadata.json` | the `metadata.json` that went into that bundle, in plaintext, so a test can assert the recovered value without decrypting first | | `regenerate.py` | the script that produced them, importing the producer's `bundle.py`/`crypto.py` by path | ## Password ``` Import1Model!Fixture ``` Recorded deliberately: the fixture protects nothing. It satisfies the producer's export-side strength rule (≥ 12 characters, upper, lower, digit, symbol), which is checked by `crypto.validate_password_strength` at generation time. ## Provenance - Producer repository: `sientia-projects-templates` - Producer commit: `8d3c1fd117c697e8b352c34f11c732809a4a129b` (`8d3c1fd QTZPOC-7: adapt to lint rules picked up from merging main`) - Producer modules used: `app/src/operations/model_export/bundle.py`, `app/src/operations/model_export/crypto.py` — loaded by path, so every constant, the `struct` layout, the zip layout, the KDF parameters and the chunk framing come from the producer and none of them is re-implemented here - Producer pin honoured: `pynacl==1.5.0` (this repository pins the same version) One deviation from task 0.3, recorded rather than hidden: the bytes were generated with the producer's **code** under *this* repository's venv, not inside the producer's own venv, because that venv has neither `pynacl` nor `mlflow` installed. The dependency that matters for the bytes is `pynacl`, pinned identically on both sides, and `mlflow` is not reached — `regenerate.py` builds the artifact tree itself instead of calling `client.download_artifacts`. ## Contents of the bundle ``` metadata.json (written first, no indent, by bundle.build_zip) artifacts/prediction_model/MLmodel artifacts/prediction_model/model.pkl (90 KiB of incompressible filler) artifacts/prediction_model/conda.yaml artifacts/prediction_model/python_env.yaml artifacts/prediction_model/requirements.txt artifacts/data_model/MLmodel artifacts/data_model/model.pkl (8 KiB) artifacts/data_model/conda.yaml artifacts/data_model/python_env.yaml artifacts/data_model/requirements.txt artifacts/model_card/model_card.json artifacts/train_data.csv artifacts/test_data.csv artifacts/raw_data.csv ``` No directory entries are stored — the producer only adds paths for which `is_file()` is true. `parameters` carries `target_variable: "SE"`, which gate 6 requires and which becomes `model_config.target` in the MongoDB model document. ## Digest boundary — the reason this fixture exists The header's `ciphertext_digest` is `sha256(file[164:])`: the producer computes `hashlib.sha256(ciphertext)` over the joined chunks and only then writes `header + stream_header + ciphertext`, so the 24-byte `secretstream` header is **not** covered. Verified against this fixture and against a freshly produced bundle. Earlier prose (this change's own first draft, and `aig-docs/03-sientia-bundle-format.md`) said "everything after the plaintext header", i.e. from offset 140 — that is wrong, and `tests/laborious/utils/bundle/test_format.py` asserts both directions so it cannot come back. ## Regenerating ```bash source ./venv/bin/activate PRODUCER_REPO=../sientia-projects-templates python tests/fixtures/bundle/regenerate.py ``` Two fields change on every run and are expected to: the 16-byte salt (`os.urandom`) and `metadata.metadata.export_timestamp` (`datetime.now(UTC)`). Everything else is deterministic — the filler bytes come from a seeded PRNG. After regenerating, update the producer commit above and the byte counts in the table.