matelab-python-sdk 0.1.0a17__tar.gz → 0.1.0a19__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 (65) hide show
  1. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/CHANGELOG.md +25 -0
  2. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/PKG-INFO +30 -19
  3. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/README.md +29 -18
  4. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/contracts/matelab-integration-v1.lock.json +3 -3
  5. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/contracts/matelab-integration-v1.openapi.yaml +98 -55
  6. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/docs/operation-coverage.yaml +24 -24
  7. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/pyproject.toml +1 -1
  8. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/_generated/models.py +35 -34
  9. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/records.py +7 -11
  10. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_async_attachment_upload.py +2 -1
  11. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_generation.py +34 -3
  12. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_record_mutations.py +4 -11
  13. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_transport.py +1 -1
  14. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_uploads_and_literature.py +2 -0
  15. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/uv.lock +1 -1
  16. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/.env.example +0 -0
  17. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/.github/workflows/release.yml +0 -0
  18. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/.gitignore +0 -0
  19. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/AGENTS.md +0 -0
  20. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/CONTEXT.md +0 -0
  21. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/LICENSE +0 -0
  22. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/NOTICE +0 -0
  23. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/scripts/check_installed_package.py +0 -0
  24. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/scripts/check_release.py +0 -0
  25. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/scripts/generate_models.py +0 -0
  26. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/__init__.py +0 -0
  27. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/_generated/__init__.py +0 -0
  28. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/_hashes.py +0 -0
  29. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/_transport.py +0 -0
  30. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/_wire_validation.py +0 -0
  31. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/client.py +0 -0
  32. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/__init__.py +0 -0
  33. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/_attachment_content.py +0 -0
  34. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/cloud_drive.py +0 -0
  35. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/groups.py +0 -0
  36. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/literature.py +0 -0
  37. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/notebooks.py +0 -0
  38. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/templates.py +0 -0
  39. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/uploads.py +0 -0
  40. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/domains/users.py +0 -0
  41. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/errors.py +0 -0
  42. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/py.typed +0 -0
  43. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/session.py +0 -0
  44. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/src/matelab/streaming.py +0 -0
  45. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/conftest.py +0 -0
  46. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/provider/test_provider_smoke.py +0 -0
  47. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_client.py +0 -0
  48. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_cloud_drive.py +0 -0
  49. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_comments_and_downloads.py +0 -0
  50. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_consumer_smoke.py +0 -0
  51. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_errors.py +0 -0
  52. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_extended_records.py +0 -0
  53. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_groups.py +0 -0
  54. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_notebook_lifecycle.py +0 -0
  55. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_notebooks.py +0 -0
  56. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_operation_coverage.py +0 -0
  57. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_record_lifecycle.py +0 -0
  58. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_records.py +0 -0
  59. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_release.py +0 -0
  60. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_streaming.py +0 -0
  61. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_template_lifecycle.py +0 -0
  62. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_templates.py +0 -0
  63. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/test_users.py +0 -0
  64. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/typing/consumer.py +0 -0
  65. {matelab_python_sdk-0.1.0a17 → matelab_python_sdk-0.1.0a19}/tests/typing/pyproject.toml +0 -0
@@ -3,6 +3,31 @@
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.1.0a19 - 2026-08-23
7
+
8
+ - Re-adopts the force-rewritten `matelab-spec v0.4.2` at commit
9
+ `1a4b77721d782fccd2b1f26bcc16a7d876347686` and OpenAPI SHA-256
10
+ `1e737421aac636356487122ea89e20d54de07c8b9c0651cf6970a7123fe3b72b`. The published `0.1.0a18` entry below remains
11
+ historical evidence for the former `v0.4.2` target at `a51483f`; it is not rewritten.
12
+ - Aligns with current Provider evidence: comment attachment multipart uses `file`; temporary-file and comment identifiers
13
+ allow 100 characters; code-4 `errs` accepts opaque array or object containers; and DOI extraction validates
14
+ `^10\.[0-9]+/\S+$` before transport.
15
+ - Breaking: removes `RecordValueAddition.path` and `RecordFilesAttachmentAppend.folder_path` because the current
16
+ Provider's add-value shape no longer accepts `path`; files-module append now targets only the module root. Search
17
+ excludes encrypted records, and callers of arbitrary template-shaped imports must omit unset file-valued keys because
18
+ the Provider rejects their explicit `null`.
19
+
20
+ ## 0.1.0a18 - 2026-08-23
21
+
22
+ - Adopts immutable `matelab-spec v0.4.2` at commit `a51483f910440fbbbc3693cc32566482064bb3ab` and OpenAPI
23
+ SHA-256 `4c92b96ba3dfe7122b30b4db2e2c8054c06018291c8c52c15482112b51a32920`. The wire schema, methods,
24
+ paths, encodings, operation count, and public interface are unchanged.
25
+ - Records that compatibility evidence remains the stable Provider revision
26
+ `59101f006e9fd6d6ce0b951dfd34695a7949b54f`; the latest reviewed revision
27
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27` is incompatible. The SDK retains the stable multipart comment-upload
28
+ field, while integrations must account for that Provider's DOI rejection, encrypted-search omission, valid
29
+ files-folder-path rejection, and explicit-null table-file-import failure.
30
+
6
31
  ## 0.1.0a17 - 2026-08-20
7
32
 
8
33
  - Adopts immutable `matelab-spec v0.4.1` at commit `6f8ab3d14797385d0075d0aba38bf3bf529e674d` and OpenAPI
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matelab-python-sdk
3
- Version: 0.1.0a17
3
+ Version: 0.1.0a19
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,10 +35,10 @@ 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.0a17`. `[project].version` in `pyproject.toml` is the sole SDK version source;
38
+ The current alpha is `0.1.0a19`. `[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.4.1` Contract Release. The sole release pin is
41
+ The SDK is pinned to the rewritten `matelab-spec v0.4.2` Contract Release. The sole release pin is
42
42
  `contracts/matelab-integration-v1.lock.json`, which records
43
43
  the source tag, commit, OpenAPI path, local snapshot path, and SHA-256.
44
44
 
@@ -64,12 +64,16 @@ To test the same artifact a downstream Consumer will install, build and install
64
64
 
65
65
  ```bash
66
66
  uv build --no-build-isolation --out-dir dist/release
67
- python -m pip install dist/release/matelab_python_sdk-0.1.0a17-py3-none-any.whl
67
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a19-py3-none-any.whl
68
68
  ```
69
69
 
70
70
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
71
71
  tag, commit, and checksum recorded below.
72
72
 
73
+ The Contract and public SDK interface track the current reviewed Provider at
74
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27`. Provider limitations that remain relevant to integrations are documented
75
+ alongside the affected interfaces below.
76
+
73
77
  ## Design
74
78
 
75
79
  The public module is intentionally small:
@@ -117,8 +121,8 @@ success code it does not allow raises `MatelabProtocolError` rather than assigni
117
121
  `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
118
122
  legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
119
123
  Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
120
- The pinned v0.4.1 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record incompatible observed
121
- item/container shapes and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
124
+ The pinned v0.4.2 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record opaque array/object
125
+ containers and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
122
126
  therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
123
127
  interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
124
128
  means the identical SDK call is safe to replay without further interpretation. It is conservatively `False` for every
@@ -312,8 +316,8 @@ supports one file column. A locally rejected target does not spend the handle; o
312
316
  result cannot be retried through the same client.
313
317
 
314
318
  Files-module append and table/files replacement use the general record attachment intents and may be combined with
315
- other non-conflicting record changes. `RecordFilesAttachmentAppend` targets the module root by default; pass
316
- `folder_path=(...)` for an existing folder-title path:
319
+ other non-conflicting record changes. `RecordFilesAttachmentAppend` targets the module root; the current Provider does
320
+ not accept a files-folder path (PVD-044):
317
321
 
318
322
  ```python
319
323
  from matelab import RecordAttachmentReplacement, RecordFilesAttachmentAppend, RecordValueUpdate
@@ -446,7 +450,7 @@ targets = await client.users.search("Example Researcher", global_scope=False)
446
450
  `groups.list()` returns the `GroupSummary` tuple directly. Ordering remains Provider-unspecified and is documented
447
451
  rather than repeated as a constant result field. The Provider's members for an unstable first group remain wire-only;
448
452
  `users.search()` is the public recipient-discovery interface. These two discovery interfaces are experimental because
449
- group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029, PCG-011).
453
+ group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029).
450
454
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
451
455
  exposing the Provider's data-server routing value.
452
456
 
@@ -538,6 +542,8 @@ relations = await client.records.relations(source)
538
542
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
539
543
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
540
544
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
545
+ The current Provider excludes encrypted records from search (PVD-043); an empty search result therefore does
546
+ not prove that no matching encrypted record exists.
541
547
 
542
548
  The Provider calls its notebook directory tree `subtype`; that name remains wire-only. The SDK exposes
543
549
  `RecordFolder`, `RecordSummary.folder_id`, and the `folders` returned with record listings. A top-level folder has
@@ -587,7 +593,9 @@ UID. Import validates the complete batch with generated wire models but cannot m
587
593
  individual inputs or promise atomicity (PCG-008); it therefore returns only the tuple of database IDs actually
588
594
  reported by the Provider. `RecordImportItem.keywords` is a tuple; the adapter owns the Provider's
589
595
  legacy semicolon encoding. Folder paths are ordered existing folder titles from the notebook root; they do not create
590
- missing folders. Delete means moving records into the recycle bin, not permanent
596
+ missing folders. The current Provider rejects explicit-null table-file imports (PVD-045). Because the SDK accepts
597
+ arbitrary template-shaped data and cannot identify file columns without the template definition, integrations must omit
598
+ an unset file-valued key instead of sending it as `None`. Delete means moving records into the recycle bin, not permanent
591
599
  deletion. Delete and restore return `None`; record mutations are not automatically retried.
592
600
 
593
601
  `records.copy()` accepts an optional `new_record_uid`; when omitted, the SDK generates one locally. The Provider
@@ -605,7 +613,8 @@ returns the acknowledgement classification
605
613
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
606
614
  retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
607
615
  `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
608
- password lifecycle remain unexposed.
616
+ password lifecycle remain unexposed. Files-module attachment append is root-only because the current Provider rejects
617
+ folder-path segments (PVD-044). A staged attachment is indeterminate once the write has started.
609
618
 
610
619
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-019
611
620
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -617,8 +626,8 @@ ignores target notebook identity (PVD-020); its mutation likewise performs autho
617
626
  `records.comments()`. Each returned `RecordRelationRef` carries only the relation row and declared target IDs.
618
627
  Deletion accepts the source `RecordLocator` and one of those observed refs.
619
628
 
620
- Comment upload follows the Provider's literal one-request `upload` field, not the incompatible Front fragment
621
- protocol (PVD-037). Comment mutations return `None` after acknowledgement. Edit first verifies that the selected
629
+ Comment upload follows the current Provider's literal one-request `file` field (PVD-037). Comment mutations return `None`
630
+ after acknowledgement. Edit first verifies that the selected
622
631
  comment is currently observed and caller-owned because the Provider otherwise reports a false success for a missing or
623
632
  other-user ID (PVD-004). Delete sends the typed ref directly because the Provider mutation itself enforces record and
624
633
  caller ownership. Neither operation performs a post-write read. Staged comment attachments have no Contract abort
@@ -697,7 +706,9 @@ The Provider's static literature form definition and extraction deployment flag
697
706
  `extract_metadata()` directly and handle an unavailable or failing optional backend as a Provider error. Extraction
698
707
  returns a `PublicationMetadataCandidate`: unstored, rich publication evidence rather than metadata already attached to
699
708
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
700
- completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. Literature list
709
+ completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. A non-empty DOI must match
710
+ `^10\.[0-9]+/\S+$`; the generated request model rejects other values before sending them to the Provider (PVD-042).
711
+ Literature list
701
712
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
702
713
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
703
714
  JSON produces the Provider's empty-array fallback; otherwise it contains decoded stored metadata without arbitrary
@@ -722,7 +733,7 @@ canonical update preflights the raw item response and refuses to drop top-level
722
733
  `allow_source_metadata_loss=True` explicitly skips that preflight and sends the canonical replacement directly. The
723
734
  default read/check/write protection is best effort rather than atomic because the Provider offers no revision or
724
735
  compare-and-swap condition; this Provider-specific behavior remains internal to the update operation (PVD-027).
725
- PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata (PCG-010).
736
+ PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata.
726
737
  Permanent personal deletion is named `permanently_delete`, returns `None`, and is non-recoverable. Sharing requires
727
738
  list-observed item summaries, user-search summaries and a
728
739
  valid caller identity, then returns `None` because the Provider supplies no per-recipient IDs (PVD-012, PVD-036).
@@ -759,7 +770,7 @@ time strings.
759
770
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
760
771
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
761
772
  the Provider binds by temporary row ID without checking its owner (PVD-031), and finalize atomicity/idempotency remain
762
- absent (PCG-012). Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
773
+ absent. Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
763
774
  deletion is named `permanently_delete_files` and is non-recoverable. Cloud downloads
764
775
  resolve bytes from the final file identity and reuse `DownloadStream`, thumbnail/preview choices and the PVD-002-safe
765
776
  range subset. Cloud mutations are not automatically retried.
@@ -901,6 +912,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
901
912
  ```
902
913
 
903
914
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
904
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.1`,
905
- commit `6f8ab3d14797385d0075d0aba38bf3bf529e674d`, and OpenAPI SHA-256
906
- `73d899c9e60b59f9521062ffcfaaae5f073eea36f24f3e535fcb53f12242581c`.
915
+ byte-identical wheel and source distribution hashes. The release is bound to the rewritten `matelab-spec v0.4.2`,
916
+ commit `1a4b77721d782fccd2b1f26bcc16a7d876347686`, and OpenAPI SHA-256
917
+ `1e737421aac636356487122ea89e20d54de07c8b9c0651cf6970a7123fe3b72b`.
@@ -7,10 +7,10 @@ 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.0a17`. `[project].version` in `pyproject.toml` is the sole SDK version source;
10
+ The current alpha is `0.1.0a19`. `[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.4.1` Contract Release. The sole release pin is
13
+ The SDK is pinned to the rewritten `matelab-spec v0.4.2` Contract Release. The sole release pin is
14
14
  `contracts/matelab-integration-v1.lock.json`, which records
15
15
  the source tag, commit, OpenAPI path, local snapshot path, and SHA-256.
16
16
 
@@ -36,12 +36,16 @@ To test the same artifact a downstream Consumer will install, build and install
36
36
 
37
37
  ```bash
38
38
  uv build --no-build-isolation --out-dir dist/release
39
- python -m pip install dist/release/matelab_python_sdk-0.1.0a17-py3-none-any.whl
39
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a19-py3-none-any.whl
40
40
  ```
41
41
 
42
42
  Do not infer Provider compatibility from the SDK version alone. A release is also bound to the Contract
43
43
  tag, commit, and checksum recorded below.
44
44
 
45
+ The Contract and public SDK interface track the current reviewed Provider at
46
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27`. Provider limitations that remain relevant to integrations are documented
47
+ alongside the affected interfaces below.
48
+
45
49
  ## Design
46
50
 
47
51
  The public module is intentionally small:
@@ -89,8 +93,8 @@ success code it does not allow raises `MatelabProtocolError` rather than assigni
89
93
  `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
90
94
  legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
91
95
  Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
92
- The pinned v0.4.1 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record incompatible observed
93
- item/container shapes and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
96
+ The pinned v0.4.2 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record opaque array/object
97
+ containers and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
94
98
  therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
95
99
  interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
96
100
  means the identical SDK call is safe to replay without further interpretation. It is conservatively `False` for every
@@ -284,8 +288,8 @@ supports one file column. A locally rejected target does not spend the handle; o
284
288
  result cannot be retried through the same client.
285
289
 
286
290
  Files-module append and table/files replacement use the general record attachment intents and may be combined with
287
- other non-conflicting record changes. `RecordFilesAttachmentAppend` targets the module root by default; pass
288
- `folder_path=(...)` for an existing folder-title path:
291
+ other non-conflicting record changes. `RecordFilesAttachmentAppend` targets the module root; the current Provider does
292
+ not accept a files-folder path (PVD-044):
289
293
 
290
294
  ```python
291
295
  from matelab import RecordAttachmentReplacement, RecordFilesAttachmentAppend, RecordValueUpdate
@@ -418,7 +422,7 @@ targets = await client.users.search("Example Researcher", global_scope=False)
418
422
  `groups.list()` returns the `GroupSummary` tuple directly. Ordering remains Provider-unspecified and is documented
419
423
  rather than repeated as a constant result field. The Provider's members for an unstable first group remain wire-only;
420
424
  `users.search()` is the public recipient-discovery interface. These two discovery interfaces are experimental because
421
- group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029, PCG-011).
425
+ group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029).
422
426
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
423
427
  exposing the Provider's data-server routing value.
424
428
 
@@ -510,6 +514,8 @@ relations = await client.records.relations(source)
510
514
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
511
515
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
512
516
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
517
+ The current Provider excludes encrypted records from search (PVD-043); an empty search result therefore does
518
+ not prove that no matching encrypted record exists.
513
519
 
514
520
  The Provider calls its notebook directory tree `subtype`; that name remains wire-only. The SDK exposes
515
521
  `RecordFolder`, `RecordSummary.folder_id`, and the `folders` returned with record listings. A top-level folder has
@@ -559,7 +565,9 @@ UID. Import validates the complete batch with generated wire models but cannot m
559
565
  individual inputs or promise atomicity (PCG-008); it therefore returns only the tuple of database IDs actually
560
566
  reported by the Provider. `RecordImportItem.keywords` is a tuple; the adapter owns the Provider's
561
567
  legacy semicolon encoding. Folder paths are ordered existing folder titles from the notebook root; they do not create
562
- missing folders. Delete means moving records into the recycle bin, not permanent
568
+ missing folders. The current Provider rejects explicit-null table-file imports (PVD-045). Because the SDK accepts
569
+ arbitrary template-shaped data and cannot identify file columns without the template definition, integrations must omit
570
+ an unset file-valued key instead of sending it as `None`. Delete means moving records into the recycle bin, not permanent
563
571
  deletion. Delete and restore return `None`; record mutations are not automatically retried.
564
572
 
565
573
  `records.copy()` accepts an optional `new_record_uid`; when omitted, the SDK generates one locally. The Provider
@@ -577,7 +585,8 @@ returns the acknowledgement classification
577
585
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
578
586
  retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
579
587
  `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
580
- password lifecycle remain unexposed.
588
+ password lifecycle remain unexposed. Files-module attachment append is root-only because the current Provider rejects
589
+ folder-path segments (PVD-044). A staged attachment is indeterminate once the write has started.
581
590
 
582
591
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-019
583
592
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -589,8 +598,8 @@ ignores target notebook identity (PVD-020); its mutation likewise performs autho
589
598
  `records.comments()`. Each returned `RecordRelationRef` carries only the relation row and declared target IDs.
590
599
  Deletion accepts the source `RecordLocator` and one of those observed refs.
591
600
 
592
- Comment upload follows the Provider's literal one-request `upload` field, not the incompatible Front fragment
593
- protocol (PVD-037). Comment mutations return `None` after acknowledgement. Edit first verifies that the selected
601
+ Comment upload follows the current Provider's literal one-request `file` field (PVD-037). Comment mutations return `None`
602
+ after acknowledgement. Edit first verifies that the selected
594
603
  comment is currently observed and caller-owned because the Provider otherwise reports a false success for a missing or
595
604
  other-user ID (PVD-004). Delete sends the typed ref directly because the Provider mutation itself enforces record and
596
605
  caller ownership. Neither operation performs a post-write read. Staged comment attachments have no Contract abort
@@ -669,7 +678,9 @@ The Provider's static literature form definition and extraction deployment flag
669
678
  `extract_metadata()` directly and handle an unavailable or failing optional backend as a Provider error. Extraction
670
679
  returns a `PublicationMetadataCandidate`: unstored, rich publication evidence rather than metadata already attached to
671
680
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
672
- completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. Literature list
681
+ completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. A non-empty DOI must match
682
+ `^10\.[0-9]+/\S+$`; the generated request model rejects other values before sending them to the Provider (PVD-042).
683
+ Literature list
673
684
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
674
685
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
675
686
  JSON produces the Provider's empty-array fallback; otherwise it contains decoded stored metadata without arbitrary
@@ -694,7 +705,7 @@ canonical update preflights the raw item response and refuses to drop top-level
694
705
  `allow_source_metadata_loss=True` explicitly skips that preflight and sends the canonical replacement directly. The
695
706
  default read/check/write protection is best effort rather than atomic because the Provider offers no revision or
696
707
  compare-and-swap condition; this Provider-specific behavior remains internal to the update operation (PVD-027).
697
- PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata (PCG-010).
708
+ PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata.
698
709
  Permanent personal deletion is named `permanently_delete`, returns `None`, and is non-recoverable. Sharing requires
699
710
  list-observed item summaries, user-search summaries and a
700
711
  valid caller identity, then returns `None` because the Provider supplies no per-recipient IDs (PVD-012, PVD-036).
@@ -731,7 +742,7 @@ time strings.
731
742
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
732
743
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
733
744
  the Provider binds by temporary row ID without checking its owner (PVD-031), and finalize atomicity/idempotency remain
734
- absent (PCG-012). Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
745
+ absent. Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
735
746
  deletion is named `permanently_delete_files` and is non-recoverable. Cloud downloads
736
747
  resolve bytes from the final file identity and reuse `DownloadStream`, thumbnail/preview choices and the PVD-002-safe
737
748
  range subset. Cloud mutations are not automatically retried.
@@ -873,6 +884,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
873
884
  ```
874
885
 
875
886
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
876
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.1`,
877
- commit `6f8ab3d14797385d0075d0aba38bf3bf529e674d`, and OpenAPI SHA-256
878
- `73d899c9e60b59f9521062ffcfaaae5f073eea36f24f3e535fcb53f12242581c`.
887
+ byte-identical wheel and source distribution hashes. The release is bound to the rewritten `matelab-spec v0.4.2`,
888
+ commit `1a4b77721d782fccd2b1f26bcc16a7d876347686`, and OpenAPI SHA-256
889
+ `1e737421aac636356487122ea89e20d54de07c8b9c0651cf6970a7123fe3b72b`.
@@ -2,12 +2,12 @@
2
2
  "schema_version": 1,
3
3
  "contract_line": "integration-v1",
4
4
  "release": {
5
- "tag": "v0.4.1",
6
- "commit": "6f8ab3d14797385d0075d0aba38bf3bf529e674d"
5
+ "tag": "v0.4.2",
6
+ "commit": "1a4b77721d782fccd2b1f26bcc16a7d876347686"
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": "73d899c9e60b59f9521062ffcfaaae5f073eea36f24f3e535fcb53f12242581c"
11
+ "sha256": "1e737421aac636356487122ea89e20d54de07c8b9c0651cf6970a7123fe3b72b"
12
12
  }
13
13
  }