matelab-python-sdk 0.1.0a24__tar.gz → 0.2.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/CHANGELOG.md +32 -0
  2. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/CONTEXT.md +5 -0
  3. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/PKG-INFO +74 -31
  4. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/README.md +73 -30
  5. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/contracts/matelab-integration-v1.lock.json +3 -3
  6. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/contracts/matelab-integration-v1.openapi.yaml +465 -140
  7. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/docs/agent-workflows.md +5 -2
  8. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/docs/operation-coverage.yaml +22 -22
  9. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/pyproject.toml +1 -1
  10. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/scripts/generate_models.py +11 -1
  11. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/__init__.py +2 -0
  12. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/_generated/models.py +488 -169
  13. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/cloud_drive.py +1 -1
  14. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/groups.py +6 -2
  15. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/literature.py +11 -1
  16. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/notebooks.py +4 -0
  17. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/records.py +61 -23
  18. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/streaming.py +1 -0
  19. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_cloud_drive.py +10 -5
  20. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_comments_and_downloads.py +62 -1
  21. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_extended_records.py +32 -4
  22. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_generation.py +43 -8
  23. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_groups.py +4 -1
  24. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_notebook_lifecycle.py +33 -0
  25. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_record_lifecycle.py +1 -1
  26. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_record_mutations.py +82 -2
  27. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_records.py +75 -4
  28. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_transport.py +12 -15
  29. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_uploads_and_literature.py +42 -0
  30. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/uv.lock +1 -1
  31. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/.env.example +0 -0
  32. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/.github/workflows/release.yml +0 -0
  33. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/.gitignore +0 -0
  34. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/AGENTS.md +0 -0
  35. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/LICENSE +0 -0
  36. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/NOTICE +0 -0
  37. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/docs/agent-architecture.md +0 -0
  38. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/scripts/check_installed_package.py +0 -0
  39. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/scripts/check_release.py +0 -0
  40. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/_generated/__init__.py +0 -0
  41. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/_hashes.py +0 -0
  42. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/_transport.py +0 -0
  43. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/_wire_validation.py +0 -0
  44. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/client.py +0 -0
  45. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/__init__.py +0 -0
  46. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/_attachment_content.py +0 -0
  47. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/templates.py +0 -0
  48. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/uploads.py +0 -0
  49. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/domains/users.py +0 -0
  50. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/errors.py +0 -0
  51. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/py.typed +0 -0
  52. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/src/matelab/session.py +0 -0
  53. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/conftest.py +0 -0
  54. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/provider/test_provider_smoke.py +0 -0
  55. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_async_attachment_upload.py +0 -0
  56. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_client.py +0 -0
  57. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_consumer_smoke.py +0 -0
  58. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_errors.py +0 -0
  59. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_notebooks.py +0 -0
  60. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_operation_coverage.py +0 -0
  61. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_release.py +0 -0
  62. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_streaming.py +0 -0
  63. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_template_lifecycle.py +0 -0
  64. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_templates.py +0 -0
  65. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/test_users.py +0 -0
  66. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/typing/consumer.py +0 -0
  67. {matelab_python_sdk-0.1.0a24 → matelab_python_sdk-0.2.0a1}/tests/typing/pyproject.toml +0 -0
@@ -3,6 +3,38 @@
3
3
  This file records release-to-release changes and migration impact. It is not the authority for the current interface;
4
4
  see [README.md](README.md) for current behavior and [AGENTS.md](AGENTS.md) for maintenance policy.
5
5
 
6
+ ## 0.2.0a1 - 2026-10-02
7
+
8
+ - Establishes the `0.x` versioning rule: incompatible public changes advance the SDK minor version; alpha/beta/RC
9
+ counters identify successive candidates for the same target version. SDK and Contract versions remain independent.
10
+ - Adopts immutable `matelab-spec v2026.10.1` at commit `9941e2d623a1c2633adb459b823d78d4e62d3802`
11
+ (annotated tag object `ae8098e1b5178b69706bddd8b70c1b4cfe3e09ba`) and OpenAPI SHA-256
12
+ `a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813`, aligned with Provider evidence
13
+ `3f39d47b7ad43bed618b029a7d9cc51fab852eb6`. The Contract's calendar version identifies a Provider-specific
14
+ snapshot verified on an isolated Workerman instance with local data servers.
15
+ - Breaking: record JSON operations accept business code `0` only; Provider-internal forwarding code `10` is outside
16
+ the verified callable scope and raises `MatelabProtocolError` (PVD-049). Search aliases additionally reserve
17
+ `eln_id`, `title`, and `eln_name`; extraction paths reject numeric strings, negative indices and a numeric fourth
18
+ segment before HTTP. Generation retains these referenced scalar and positional JSON Schema constraints.
19
+ - Adds `Record.encrypted_modules` and public `EncryptedRecordModules`, preserving ciphertext and additive fields
20
+ without decryption. Encrypted reads have no plaintext modules or attachment refs. State-dependent updates reject
21
+ encrypted content locally; stateless module changes retain the Provider's pre-write password check. Unresolved
22
+ author descriptors map to `author_name=None` while remaining validated in the private wire layer (PVD-044).
23
+ - Restores `RecordFilesAttachmentAppend.folder_path` after the dedicated shape became valid within the top-level
24
+ update request. A non-empty path uses the staged-name finalizer, validates safe segments and requires an exclusive
25
+ mutation; reuse and ambiguous-finalization protections remain in effect (PVD-030). Inline base64 file input remains
26
+ outside the public write boundary (PVD-042).
27
+ - Breaking: `GroupSummary.ref` can be `None` for a dangling membership (PVD-048), and `CloudFile.modified_at` is now
28
+ a required string because stored null timestamps fail before a successful Provider row is returned (PVD-047).
29
+ Notebook reads accept non-null JSON type settings, but metadata updates reject settings or extraction requests that
30
+ cannot be preserved within the write Contract before mutation (PVD-046).
31
+ - Literature metadata extraction maps nested Provider errors to the usual safe SDK errors. Empty or opaque lists
32
+ raise `MatelabProtocolError` instead of being presented as publication candidates (PVD-045).
33
+ - Allows zero-byte comment attachment discovery/downloads and documents the 4097-byte cap on local open ranges
34
+ beginning at zero. Download metadata remains available for explicit continuation; no automatic replay is added.
35
+ - Retains the existing read-only missing table-attachment timestamp containment and the unexposed password,
36
+ signing, record-title-update and structured-error-detail capabilities.
37
+
6
38
  ## 0.1.0a24 - 2026-09-26
7
39
 
8
40
  - Adopts immutable `matelab-spec v0.5.0` at commit `4f2959472933da47d1ea3e275552884d51d4fdd9`
@@ -85,6 +85,11 @@ A template-shaped value composed of JSON-compatible scalars and containers, with
85
85
  allowed wherever the template expects a file.
86
86
  _Avoid_: Arbitrary object, stored record module, Provider attachment reference
87
87
 
88
+ **Encrypted record modules**:
89
+ Stored ciphertext returned without decryption, separate from a record's available plaintext modules and attachments.
90
+ The encrypted descriptor is read evidence; it does not provide a decryption or password management interface.
91
+ _Avoid_: Empty record content, decrypted modules
92
+
88
93
  **Staged attachment**:
89
94
  An upload prepared in a selected notebook for one later record import or update; uploading does not choose the target
90
95
  record.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matelab-python-sdk
3
- Version: 0.1.0a24
3
+ Version: 0.2.0a1
4
4
  Summary: Reusable async Python client for the Matelab Integration Contract
5
5
  Author-email: 朱天念 <zhutiannian@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -35,14 +35,14 @@ This README describes the current SDK interface, integration semantics, examples
35
35
  [AGENTS.md](AGENTS.md) for durable maintenance rules, and `docs/operation-coverage.yaml` for the machine-readable
36
36
  operation inventory.
37
37
 
38
- The current alpha is `0.1.0a24`. `[project].version` in `pyproject.toml` is the sole SDK version source;
38
+ The current alpha is `0.2.0a1`. `[project].version` in `pyproject.toml` is the sole SDK version source;
39
39
  `uv.lock` only mirrors that source.
40
40
 
41
- The SDK is pinned to the immutable `matelab-spec v0.5.0` Contract Release. The sole pin,
42
- `contracts/matelab-integration-v1.lock.json`, records peeled commit `4f2959472933da47d1ea3e275552884d51d4fdd9`,
41
+ The SDK is pinned to the immutable `matelab-spec v2026.10.1` Contract Release. The sole pin,
42
+ `contracts/matelab-integration-v1.lock.json`, records peeled commit `9941e2d623a1c2633adb459b823d78d4e62d3802`,
43
43
  source `openapi/matelab-integration-v1.openapi.yaml`, the local snapshot path, and SHA-256
44
- `dee14f76e24b2d7c3d97a6f30a9369ac093d615d132db85836ab86671eadcf18`. The annotated tag object is
45
- `cc362a9a36601f5d07d6e90c2c6994e33c202d88`.
44
+ `a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813`. The annotated tag object is
45
+ `ae8098e1b5178b69706bddd8b70c1b4cfe3e09ba`.
46
46
 
47
47
  ## Installation
48
48
 
@@ -66,18 +66,33 @@ To test the same artifact a downstream Consumer will install, build and install
66
66
 
67
67
  ```bash
68
68
  uv build --no-build-isolation --out-dir dist/release
69
- python -m pip install dist/release/matelab_python_sdk-0.1.0a24-py3-none-any.whl
69
+ python -m pip install dist/release/matelab_python_sdk-0.2.0a1-py3-none-any.whl
70
70
  ```
71
71
 
72
72
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
73
73
  tag, commit, and checksum recorded below.
74
74
 
75
- The Contract uses Provider source evidence from `acb0e12f2d62a8959ab9e9bddf38e34a67c19b48`; v0.5.0 validation ran
75
+ The Contract uses Provider source evidence from `3f39d47b7ad43bed618b029a7d9cc51fab852eb6`; v2026.10.1 validation ran
76
76
  against an isolated test instance and does not establish production behavior. The corresponding Front Consumer evidence
77
77
  is `0c985f5b6da8e8ef4627ca7065cea85e408ae981`; it informs cross-Consumer capability review but does not define the SDK
78
78
  interface. Provider limitations that remain relevant to integrations are documented alongside the affected interfaces
79
79
  below.
80
80
 
81
+ Contract releases now use calendar versions to identify Provider-specific snapshots. This snapshot covers the
82
+ Workerman runtime with the `localhost` data-server branch for ELN records and attachments; remote data-server
83
+ forwarding is outside its verified callable scope (PVD-049).
84
+
85
+ ## Versioning
86
+
87
+ SDK versions express compatibility of the public Python interface and behavior. Python prerelease spelling follows
88
+ PEP 440: `0.2.0a1` is the first alpha candidate for `0.2.0`. During `0.x` development, incompatible changes advance
89
+ the minor version. From `1.0.0`, compatible fixes advance patch, compatible additions advance minor, and incompatible
90
+ changes advance major. Successive candidates for the same target version use `aN`, `bN`, or `rcN`.
91
+
92
+ Contract calendar versions identify Provider wire snapshots independently. Each SDK release records its exact
93
+ Contract tag, commit and checksum in the lock; multiple SDK fixes can use the same Contract release. Adopting a new
94
+ Contract changes the SDK version according to its public impact. See [CHANGELOG.md](CHANGELOG.md) for migration details.
95
+
81
96
  ## Design
82
97
 
83
98
  The public module is intentionally small:
@@ -111,7 +126,7 @@ category:
111
126
  | `MatelabUsageError` | `VALIDATION` | No | The call cannot be represented safely; correct its arguments. |
112
127
  | `MatelabProviderError` | `BUSINESS`, `VALIDATION`, or `UPSTREAM` | No | The Provider rejected the request; record `provider_code` and route recovery by `category`; `provider_message` is an SDK-owned safe summary. |
113
128
  | `MatelabTransportError` | `UPSTREAM` | No | The HTTP exchange failed; `status_code` is present for HTTP failures, and a mutation outcome may be unknown. |
114
- | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract; treat it as Provider drift or an SDK defect. |
129
+ | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract or cannot supply the structured result required by the SDK operation; inspect the Provider result or SDK boundary. |
115
130
 
116
131
  For `MatelabProviderError`, the SDK maps Provider wire code `2` to `BUSINESS`, `4` to `VALIDATION`, and `3` or an
117
132
  unknown code to `UPSTREAM`. `provider_code` is diagnostic metadata, not a stable routing identifier, and integrations
@@ -120,12 +135,12 @@ selected from the code mapping; they do not reproduce Provider-authored text. Au
120
135
  `MatelabAuthenticationError`; code `5`
121
136
  triggers at most one refresh and replay only for authenticated operations that explicitly enable
122
137
  `retry_on_access_expired`, otherwise codes `1` and `5` raise `MatelabAuthenticationError` directly.
123
- Codes `0` and `10` remain operation-specific successes selected by the pinned Contract; an operation that receives a
124
- success code it does not allow raises `MatelabProtocolError` rather than assigning an error category.
138
+ Record operations accept business code `0`. Provider-internal forwarding code `10` is outside the pinned
139
+ callable Contract and raises `MatelabProtocolError` rather than assigning an error category.
125
140
  `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
126
141
  legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
127
142
  Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
128
- The pinned v0.5.0 Contract also declares optional code-4 `errs`, but PVD-029 and PCG-010 record opaque array/object
143
+ The pinned v2026.10.1 Contract also declares optional code-4 `errs`, but PVD-029 and PCG-010 record opaque array/object
129
144
  containers and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
130
145
  therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
131
146
  interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
@@ -319,11 +334,10 @@ These three operations use the Provider's staged-name finalizer and must be the
319
334
  supports one file column. A locally rejected target does not spend the handle; once transport starts, an ambiguous
320
335
  result cannot be retried through the same client.
321
336
 
322
- Files-module append and table/files replacement use the general record attachment intents and may be combined with
323
- other non-conflicting record changes. `RecordFilesAttachmentAppend` currently targets the module root. Although
324
- v0.5.0 records Provider evidence for safe folder paths, its top-level `UpdateRecordRequest.add[]` schema still excludes
325
- the `path` property declared by the dedicated staged-name append shape; the SDK therefore does not expose folder paths
326
- until that wire-schema conflict is resolved (PVD-030):
337
+ Files-module append at the module root and table/files replacement may be combined with other non-conflicting record
338
+ changes. `RecordFilesAttachmentAppend.folder_path` optionally selects folders within the files module. A non-empty
339
+ path uses the staged-name finalizer and must be the only mutation in its update request; the SDK validates every
340
+ segment before writing to avoid the Provider's malformed-path fallback to the module root (PVD-030):
327
341
 
328
342
  ```python
329
343
  from matelab import RecordAttachmentReplacement, RecordFilesAttachmentAppend, RecordValueUpdate
@@ -337,6 +351,15 @@ await client.records.update(
337
351
  )
338
352
  ```
339
353
 
354
+ To append within a folder, use a fresh upload in a separate update:
355
+
356
+ ```python
357
+ await client.records.update(
358
+ source,
359
+ (RecordFilesAttachmentAppend(module="Files", attachment=folder_uploaded, folder_path=("Evidence", "Raw Data")),),
360
+ )
361
+ ```
362
+
340
363
  For `RecordModuleCreation(module_type="code", language="json", style="echarts")`, omitted, null, and empty `data` all
341
364
  produce an empty string; explicit `"0"` stays `"0"`. Send the desired initial chart configuration as a JSON code string.
342
365
  Richtext/code module creation defaults missing `data` to `""`; form/table/files creation ignores it and initializes
@@ -480,6 +503,8 @@ rather than repeated as a constant result field. The Provider's members for an u
480
503
  group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-017, PVD-025).
481
504
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
482
505
  exposing the Provider's data-server routing value.
506
+ An observed dangling group membership has `GroupSummary.ref=None` and no usable group identity. If such a membership
507
+ is selected as the Provider's first group, the whole request can fail with a Provider error (PVD-048).
483
508
 
484
509
  Notebook create and direct sharing use the Provider acknowledgement without an automatic follow-up read:
485
510
 
@@ -505,6 +530,9 @@ is reused by record pages instead of maintaining a second nearly identical permi
505
530
  have implicit read access even when every optional permission is false (PVD-037).
506
531
  `provider_signing_allowed` only represents Provider policy, not an SDK signing operation. Share-list order remains
507
532
  unspecified.
533
+ Stored notebook type configuration may decode to any non-null JSON value, but metadata writes accept arrays only.
534
+ If the stored configuration or display extraction requests cannot be preserved within the write Contract, update
535
+ raises `MatelabProtocolError` before sending a mutation instead of silently replacing them (PVD-046).
508
536
 
509
537
  Template discovery keeps a template database identity separate from direct-share, market-acquisition, and group
510
538
  relation identities:
@@ -574,6 +602,9 @@ relations = await client.records.relations(source)
574
602
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
575
603
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
576
604
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
605
+ Extraction aliases cannot use `id`, `uid`, `eln_id`, `title`, or `eln_name`, which would overwrite result metadata
606
+ (PVD-043). Paths contain one to four segments: the first three accept non-empty, non-numeric names or non-negative
607
+ integer indices; a fourth segment must be a non-numeric property name. Numeric strings are rejected before HTTP.
577
608
  The current Provider excludes encrypted records from search (PVD-041); an empty search result therefore does
578
609
  not prove that no matching encrypted record exists.
579
610
 
@@ -597,8 +628,7 @@ Public summaries keep source notebook attribution but omit the Provider's unused
597
628
  email; their `notebook_title` follows the same naming used by export and search results. Relation refs retain only the
598
629
  stored relation row and declared target IDs; nullable JOIN previews and resolved target identity stay wire-only.
599
630
  Search and relation order remain unspecified, and no continuation token is invented. Export and search return tuples
600
- directly; Provider code `10` only reports transparent data-server forwarding and does not create a second public result
601
- shape.
631
+ directly. Remote data-server forwarding code `10` is rejected because only local data-server results are covered.
602
632
  `DeletedRecordPage` does not repeat its input notebook.
603
633
 
604
634
  Record creation keeps blank creation and structured import as separate capabilities:
@@ -643,11 +673,16 @@ ordinary module creation and deletion rely on the Provider's own canonical updat
643
673
  returns the acknowledgement classification
644
674
  `"persisted"`, `"pending"`, or `"unknown"`; it does not
645
675
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
646
- retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
647
- `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
648
- password lifecycle remain unexposed. Files-module attachment append remains root-only because the pinned top-level
649
- update request schema does not admit the dedicated staged-name append shape's folder `path`; malformed path containers
650
- may also silently append at root according to PVD-030. A staged attachment is indeterminate once the write has started.
676
+ retries stay disabled. Business code `0` alone does not distinguish persisted data from a browser collaboration
677
+ broadcast; the classification uses the observed Provider acknowledgement and supplies no revision or atomicity
678
+ guarantee. Current collaboration peers must be browsers viewing the same notebook and record.
679
+ Encrypted reads return `Record.encrypted_modules` as an `EncryptedRecordModules` containing the ciphertext,
680
+ algorithm and additive fields; `modules` and `attachments` are empty because no plaintext is available. Plaintext
681
+ reads have `encrypted_modules=None`. State-dependent updates reject encrypted content before mutation, while
682
+ ordinary module changes rely on the Provider's password validation before any write. The password and decryption
683
+ lifecycle remain unexposed. The list-level `RecordSummary.encrypted` flag remains available for discovery.
684
+ Unresolved author lookup descriptors remain wire-only and map to `author_name=None` on records and comments (PVD-044).
685
+ A staged attachment is indeterminate once the write has started.
651
686
 
652
687
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-009
653
688
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -687,6 +722,9 @@ async with await client.records.download_comment_attachment(
687
722
 
688
723
  `DownloadStream` exposes status, content type, length, range, and disposition metadata without buffering the
689
724
  complete file. Streams are not automatically replayed. `ByteRange` deliberately rejects `bytes=0-0` (PVD-015).
725
+ For local files, `ByteRange.from_start(0)` returns at most the first 4097 bytes. Inspect `content_range` and request
726
+ the next range starting at its end plus one, use a positive explicit end, or omit `byte_range` for the full file.
727
+ Zero-byte comment attachments can be discovered and downloaded without a range.
690
728
  Comment attachment refs contain only file identity. Pass the parent comment ref returned by the same read when
691
729
  downloading; current Providers do not verify that association (PVD-006).
692
730
 
@@ -741,6 +779,10 @@ returns a `PublicationMetadataCandidate`: unstored, rich publication evidence ra
741
779
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
742
780
  completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. A non-empty DOI must match
743
781
  `^10\.[0-9]+/\S+$`; the generated request model rejects other values before sending them to the Provider (PVD-040).
782
+ The Provider can wrap an error inside an outer successful extraction response. The SDK maps that nested error to
783
+ its usual safe Provider/authentication error. Empty or opaque backend lists raise `MatelabProtocolError` because they
784
+ provide no structured `PublicationMetadataCandidate`; an outer success code does not promise extracted metadata
785
+ (PVD-045).
744
786
  Literature list
745
787
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
746
788
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
@@ -797,8 +839,8 @@ snapshot and quota usage; pagination applies only to `files`, while request page
797
839
  metadata and permissions are synthetic/fixed for this Contract line and remain wire-only. File rows omit the constant
798
840
  caller owner fields and do not invent a folder location that the Provider fails to return for root-wide searches.
799
841
  Listings likewise omit search/order/direction request echoes. Ordering has no stable ID tie-breaker (PCG-011, PVD-038).
800
- Cloud files expose the nullable stored modification timestamp, not the Provider's duplicate display-formatted date and
801
- time strings.
842
+ `CloudFile.modified_at` contains the stored modification timestamp as a non-null string. A stored null causes a
843
+ Provider error before a successful file row can be returned (PVD-047). Display-formatted date and time remain wire-only.
802
844
 
803
845
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
804
846
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
@@ -832,8 +874,9 @@ names or groups, so those fields are `None`. Public summary and creation time re
832
874
  Contract, while the unified model uses the wider owned/shared nullable types.
833
875
 
834
876
  Provider `types`, `display`, and `requests` fields configure its notebook-list UI rather than notebook domain data.
835
- `types` is a list of user-defined classification tags used by the Provider frontend for client-side filtering. These
836
- fields are therefore absent from `NotebookSummary` and from create/update inputs; the SDK handles their update-time
877
+ `types` normally holds classification tags used by the Provider frontend for client-side filtering; legacy stored JSON
878
+ can have another non-null shape. These fields are absent from `NotebookSummary` and from create/update inputs;
879
+ the SDK handles their update-time
837
880
  preservation only as an internal Provider compatibility detail.
838
881
 
839
882
  Template render metadata is also excluded from template summaries and record reads. A `Record` has one
@@ -945,6 +988,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
945
988
  ```
946
989
 
947
990
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
948
- byte-identical wheel and source distribution hashes. The SDK Contract pin is immutable `matelab-spec v0.5.0`, commit
949
- `4f2959472933da47d1ea3e275552884d51d4fdd9`, and OpenAPI SHA-256
950
- `dee14f76e24b2d7c3d97a6f30a9369ac093d615d132db85836ab86671eadcf18`.
991
+ byte-identical wheel and source distribution hashes. The SDK Contract pin is immutable `matelab-spec v2026.10.1`, commit
992
+ `9941e2d623a1c2633adb459b823d78d4e62d3802`, and OpenAPI SHA-256
993
+ `a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813`.
@@ -7,14 +7,14 @@ This README describes the current SDK interface, integration semantics, examples
7
7
  [AGENTS.md](AGENTS.md) for durable maintenance rules, and `docs/operation-coverage.yaml` for the machine-readable
8
8
  operation inventory.
9
9
 
10
- The current alpha is `0.1.0a24`. `[project].version` in `pyproject.toml` is the sole SDK version source;
10
+ The current alpha is `0.2.0a1`. `[project].version` in `pyproject.toml` is the sole SDK version source;
11
11
  `uv.lock` only mirrors that source.
12
12
 
13
- The SDK is pinned to the immutable `matelab-spec v0.5.0` Contract Release. The sole pin,
14
- `contracts/matelab-integration-v1.lock.json`, records peeled commit `4f2959472933da47d1ea3e275552884d51d4fdd9`,
13
+ The SDK is pinned to the immutable `matelab-spec v2026.10.1` Contract Release. The sole pin,
14
+ `contracts/matelab-integration-v1.lock.json`, records peeled commit `9941e2d623a1c2633adb459b823d78d4e62d3802`,
15
15
  source `openapi/matelab-integration-v1.openapi.yaml`, the local snapshot path, and SHA-256
16
- `dee14f76e24b2d7c3d97a6f30a9369ac093d615d132db85836ab86671eadcf18`. The annotated tag object is
17
- `cc362a9a36601f5d07d6e90c2c6994e33c202d88`.
16
+ `a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813`. The annotated tag object is
17
+ `ae8098e1b5178b69706bddd8b70c1b4cfe3e09ba`.
18
18
 
19
19
  ## Installation
20
20
 
@@ -38,18 +38,33 @@ To test the same artifact a downstream Consumer will install, build and install
38
38
 
39
39
  ```bash
40
40
  uv build --no-build-isolation --out-dir dist/release
41
- python -m pip install dist/release/matelab_python_sdk-0.1.0a24-py3-none-any.whl
41
+ python -m pip install dist/release/matelab_python_sdk-0.2.0a1-py3-none-any.whl
42
42
  ```
43
43
 
44
44
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
45
45
  tag, commit, and checksum recorded below.
46
46
 
47
- The Contract uses Provider source evidence from `acb0e12f2d62a8959ab9e9bddf38e34a67c19b48`; v0.5.0 validation ran
47
+ The Contract uses Provider source evidence from `3f39d47b7ad43bed618b029a7d9cc51fab852eb6`; v2026.10.1 validation ran
48
48
  against an isolated test instance and does not establish production behavior. The corresponding Front Consumer evidence
49
49
  is `0c985f5b6da8e8ef4627ca7065cea85e408ae981`; it informs cross-Consumer capability review but does not define the SDK
50
50
  interface. Provider limitations that remain relevant to integrations are documented alongside the affected interfaces
51
51
  below.
52
52
 
53
+ Contract releases now use calendar versions to identify Provider-specific snapshots. This snapshot covers the
54
+ Workerman runtime with the `localhost` data-server branch for ELN records and attachments; remote data-server
55
+ forwarding is outside its verified callable scope (PVD-049).
56
+
57
+ ## Versioning
58
+
59
+ SDK versions express compatibility of the public Python interface and behavior. Python prerelease spelling follows
60
+ PEP 440: `0.2.0a1` is the first alpha candidate for `0.2.0`. During `0.x` development, incompatible changes advance
61
+ the minor version. From `1.0.0`, compatible fixes advance patch, compatible additions advance minor, and incompatible
62
+ changes advance major. Successive candidates for the same target version use `aN`, `bN`, or `rcN`.
63
+
64
+ Contract calendar versions identify Provider wire snapshots independently. Each SDK release records its exact
65
+ Contract tag, commit and checksum in the lock; multiple SDK fixes can use the same Contract release. Adopting a new
66
+ Contract changes the SDK version according to its public impact. See [CHANGELOG.md](CHANGELOG.md) for migration details.
67
+
53
68
  ## Design
54
69
 
55
70
  The public module is intentionally small:
@@ -83,7 +98,7 @@ category:
83
98
  | `MatelabUsageError` | `VALIDATION` | No | The call cannot be represented safely; correct its arguments. |
84
99
  | `MatelabProviderError` | `BUSINESS`, `VALIDATION`, or `UPSTREAM` | No | The Provider rejected the request; record `provider_code` and route recovery by `category`; `provider_message` is an SDK-owned safe summary. |
85
100
  | `MatelabTransportError` | `UPSTREAM` | No | The HTTP exchange failed; `status_code` is present for HTTP failures, and a mutation outcome may be unknown. |
86
- | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract; treat it as Provider drift or an SDK defect. |
101
+ | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract or cannot supply the structured result required by the SDK operation; inspect the Provider result or SDK boundary. |
87
102
 
88
103
  For `MatelabProviderError`, the SDK maps Provider wire code `2` to `BUSINESS`, `4` to `VALIDATION`, and `3` or an
89
104
  unknown code to `UPSTREAM`. `provider_code` is diagnostic metadata, not a stable routing identifier, and integrations
@@ -92,12 +107,12 @@ selected from the code mapping; they do not reproduce Provider-authored text. Au
92
107
  `MatelabAuthenticationError`; code `5`
93
108
  triggers at most one refresh and replay only for authenticated operations that explicitly enable
94
109
  `retry_on_access_expired`, otherwise codes `1` and `5` raise `MatelabAuthenticationError` directly.
95
- Codes `0` and `10` remain operation-specific successes selected by the pinned Contract; an operation that receives a
96
- success code it does not allow raises `MatelabProtocolError` rather than assigning an error category.
110
+ Record operations accept business code `0`. Provider-internal forwarding code `10` is outside the pinned
111
+ callable Contract and raises `MatelabProtocolError` rather than assigning an error category.
97
112
  `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
98
113
  legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
99
114
  Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
100
- The pinned v0.5.0 Contract also declares optional code-4 `errs`, but PVD-029 and PCG-010 record opaque array/object
115
+ The pinned v2026.10.1 Contract also declares optional code-4 `errs`, but PVD-029 and PCG-010 record opaque array/object
101
116
  containers and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
102
117
  therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
103
118
  interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
@@ -291,11 +306,10 @@ These three operations use the Provider's staged-name finalizer and must be the
291
306
  supports one file column. A locally rejected target does not spend the handle; once transport starts, an ambiguous
292
307
  result cannot be retried through the same client.
293
308
 
294
- Files-module append and table/files replacement use the general record attachment intents and may be combined with
295
- other non-conflicting record changes. `RecordFilesAttachmentAppend` currently targets the module root. Although
296
- v0.5.0 records Provider evidence for safe folder paths, its top-level `UpdateRecordRequest.add[]` schema still excludes
297
- the `path` property declared by the dedicated staged-name append shape; the SDK therefore does not expose folder paths
298
- until that wire-schema conflict is resolved (PVD-030):
309
+ Files-module append at the module root and table/files replacement may be combined with other non-conflicting record
310
+ changes. `RecordFilesAttachmentAppend.folder_path` optionally selects folders within the files module. A non-empty
311
+ path uses the staged-name finalizer and must be the only mutation in its update request; the SDK validates every
312
+ segment before writing to avoid the Provider's malformed-path fallback to the module root (PVD-030):
299
313
 
300
314
  ```python
301
315
  from matelab import RecordAttachmentReplacement, RecordFilesAttachmentAppend, RecordValueUpdate
@@ -309,6 +323,15 @@ await client.records.update(
309
323
  )
310
324
  ```
311
325
 
326
+ To append within a folder, use a fresh upload in a separate update:
327
+
328
+ ```python
329
+ await client.records.update(
330
+ source,
331
+ (RecordFilesAttachmentAppend(module="Files", attachment=folder_uploaded, folder_path=("Evidence", "Raw Data")),),
332
+ )
333
+ ```
334
+
312
335
  For `RecordModuleCreation(module_type="code", language="json", style="echarts")`, omitted, null, and empty `data` all
313
336
  produce an empty string; explicit `"0"` stays `"0"`. Send the desired initial chart configuration as a JSON code string.
314
337
  Richtext/code module creation defaults missing `data` to `""`; form/table/files creation ignores it and initializes
@@ -452,6 +475,8 @@ rather than repeated as a constant result field. The Provider's members for an u
452
475
  group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-017, PVD-025).
453
476
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
454
477
  exposing the Provider's data-server routing value.
478
+ An observed dangling group membership has `GroupSummary.ref=None` and no usable group identity. If such a membership
479
+ is selected as the Provider's first group, the whole request can fail with a Provider error (PVD-048).
455
480
 
456
481
  Notebook create and direct sharing use the Provider acknowledgement without an automatic follow-up read:
457
482
 
@@ -477,6 +502,9 @@ is reused by record pages instead of maintaining a second nearly identical permi
477
502
  have implicit read access even when every optional permission is false (PVD-037).
478
503
  `provider_signing_allowed` only represents Provider policy, not an SDK signing operation. Share-list order remains
479
504
  unspecified.
505
+ Stored notebook type configuration may decode to any non-null JSON value, but metadata writes accept arrays only.
506
+ If the stored configuration or display extraction requests cannot be preserved within the write Contract, update
507
+ raises `MatelabProtocolError` before sending a mutation instead of silently replacing them (PVD-046).
480
508
 
481
509
  Template discovery keeps a template database identity separate from direct-share, market-acquisition, and group
482
510
  relation identities:
@@ -546,6 +574,9 @@ relations = await client.records.relations(source)
546
574
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
547
575
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
548
576
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
577
+ Extraction aliases cannot use `id`, `uid`, `eln_id`, `title`, or `eln_name`, which would overwrite result metadata
578
+ (PVD-043). Paths contain one to four segments: the first three accept non-empty, non-numeric names or non-negative
579
+ integer indices; a fourth segment must be a non-numeric property name. Numeric strings are rejected before HTTP.
549
580
  The current Provider excludes encrypted records from search (PVD-041); an empty search result therefore does
550
581
  not prove that no matching encrypted record exists.
551
582
 
@@ -569,8 +600,7 @@ Public summaries keep source notebook attribution but omit the Provider's unused
569
600
  email; their `notebook_title` follows the same naming used by export and search results. Relation refs retain only the
570
601
  stored relation row and declared target IDs; nullable JOIN previews and resolved target identity stay wire-only.
571
602
  Search and relation order remain unspecified, and no continuation token is invented. Export and search return tuples
572
- directly; Provider code `10` only reports transparent data-server forwarding and does not create a second public result
573
- shape.
603
+ directly. Remote data-server forwarding code `10` is rejected because only local data-server results are covered.
574
604
  `DeletedRecordPage` does not repeat its input notebook.
575
605
 
576
606
  Record creation keeps blank creation and structured import as separate capabilities:
@@ -615,11 +645,16 @@ ordinary module creation and deletion rely on the Provider's own canonical updat
615
645
  returns the acknowledgement classification
616
646
  `"persisted"`, `"pending"`, or `"unknown"`; it does not
617
647
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
618
- retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
619
- `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
620
- password lifecycle remain unexposed. Files-module attachment append remains root-only because the pinned top-level
621
- update request schema does not admit the dedicated staged-name append shape's folder `path`; malformed path containers
622
- may also silently append at root according to PVD-030. A staged attachment is indeterminate once the write has started.
648
+ retries stay disabled. Business code `0` alone does not distinguish persisted data from a browser collaboration
649
+ broadcast; the classification uses the observed Provider acknowledgement and supplies no revision or atomicity
650
+ guarantee. Current collaboration peers must be browsers viewing the same notebook and record.
651
+ Encrypted reads return `Record.encrypted_modules` as an `EncryptedRecordModules` containing the ciphertext,
652
+ algorithm and additive fields; `modules` and `attachments` are empty because no plaintext is available. Plaintext
653
+ reads have `encrypted_modules=None`. State-dependent updates reject encrypted content before mutation, while
654
+ ordinary module changes rely on the Provider's password validation before any write. The password and decryption
655
+ lifecycle remain unexposed. The list-level `RecordSummary.encrypted` flag remains available for discovery.
656
+ Unresolved author lookup descriptors remain wire-only and map to `author_name=None` on records and comments (PVD-044).
657
+ A staged attachment is indeterminate once the write has started.
623
658
 
624
659
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-009
625
660
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -659,6 +694,9 @@ async with await client.records.download_comment_attachment(
659
694
 
660
695
  `DownloadStream` exposes status, content type, length, range, and disposition metadata without buffering the
661
696
  complete file. Streams are not automatically replayed. `ByteRange` deliberately rejects `bytes=0-0` (PVD-015).
697
+ For local files, `ByteRange.from_start(0)` returns at most the first 4097 bytes. Inspect `content_range` and request
698
+ the next range starting at its end plus one, use a positive explicit end, or omit `byte_range` for the full file.
699
+ Zero-byte comment attachments can be discovered and downloaded without a range.
662
700
  Comment attachment refs contain only file identity. Pass the parent comment ref returned by the same read when
663
701
  downloading; current Providers do not verify that association (PVD-006).
664
702
 
@@ -713,6 +751,10 @@ returns a `PublicationMetadataCandidate`: unstored, rich publication evidence ra
713
751
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
714
752
  completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. A non-empty DOI must match
715
753
  `^10\.[0-9]+/\S+$`; the generated request model rejects other values before sending them to the Provider (PVD-040).
754
+ The Provider can wrap an error inside an outer successful extraction response. The SDK maps that nested error to
755
+ its usual safe Provider/authentication error. Empty or opaque backend lists raise `MatelabProtocolError` because they
756
+ provide no structured `PublicationMetadataCandidate`; an outer success code does not promise extracted metadata
757
+ (PVD-045).
716
758
  Literature list
717
759
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
718
760
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
@@ -769,8 +811,8 @@ snapshot and quota usage; pagination applies only to `files`, while request page
769
811
  metadata and permissions are synthetic/fixed for this Contract line and remain wire-only. File rows omit the constant
770
812
  caller owner fields and do not invent a folder location that the Provider fails to return for root-wide searches.
771
813
  Listings likewise omit search/order/direction request echoes. Ordering has no stable ID tie-breaker (PCG-011, PVD-038).
772
- Cloud files expose the nullable stored modification timestamp, not the Provider's duplicate display-formatted date and
773
- time strings.
814
+ `CloudFile.modified_at` contains the stored modification timestamp as a non-null string. A stored null causes a
815
+ Provider error before a successful file row can be returned (PVD-047). Display-formatted date and time remain wire-only.
774
816
 
775
817
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
776
818
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
@@ -804,8 +846,9 @@ names or groups, so those fields are `None`. Public summary and creation time re
804
846
  Contract, while the unified model uses the wider owned/shared nullable types.
805
847
 
806
848
  Provider `types`, `display`, and `requests` fields configure its notebook-list UI rather than notebook domain data.
807
- `types` is a list of user-defined classification tags used by the Provider frontend for client-side filtering. These
808
- fields are therefore absent from `NotebookSummary` and from create/update inputs; the SDK handles their update-time
849
+ `types` normally holds classification tags used by the Provider frontend for client-side filtering; legacy stored JSON
850
+ can have another non-null shape. These fields are absent from `NotebookSummary` and from create/update inputs;
851
+ the SDK handles their update-time
809
852
  preservation only as an internal Provider compatibility detail.
810
853
 
811
854
  Template render metadata is also excluded from template summaries and record reads. A `Record` has one
@@ -917,6 +960,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
917
960
  ```
918
961
 
919
962
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
920
- byte-identical wheel and source distribution hashes. The SDK Contract pin is immutable `matelab-spec v0.5.0`, commit
921
- `4f2959472933da47d1ea3e275552884d51d4fdd9`, and OpenAPI SHA-256
922
- `dee14f76e24b2d7c3d97a6f30a9369ac093d615d132db85836ab86671eadcf18`.
963
+ byte-identical wheel and source distribution hashes. The SDK Contract pin is immutable `matelab-spec v2026.10.1`, commit
964
+ `9941e2d623a1c2633adb459b823d78d4e62d3802`, and OpenAPI SHA-256
965
+ `a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813`.
@@ -2,12 +2,12 @@
2
2
  "schema_version": 1,
3
3
  "contract_line": "integration-v1",
4
4
  "release": {
5
- "tag": "v0.5.0",
6
- "commit": "4f2959472933da47d1ea3e275552884d51d4fdd9"
5
+ "tag": "v2026.10.1",
6
+ "commit": "9941e2d623a1c2633adb459b823d78d4e62d3802"
7
7
  },
8
8
  "openapi": {
9
9
  "source_path": "openapi/matelab-integration-v1.openapi.yaml",
10
10
  "snapshot": "matelab-integration-v1.openapi.yaml",
11
- "sha256": "dee14f76e24b2d7c3d97a6f30a9369ac093d615d132db85836ab86671eadcf18"
11
+ "sha256": "a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813"
12
12
  }
13
13
  }