matelab-python-sdk 0.1.0a16__tar.gz → 0.1.0a18__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.0a16 → matelab_python_sdk-0.1.0a18}/CHANGELOG.md +24 -0
  2. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/PKG-INFO +53 -30
  3. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/README.md +52 -29
  4. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/contracts/matelab-integration-v1.lock.json +3 -3
  5. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/contracts/matelab-integration-v1.openapi.yaml +81 -9
  6. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/docs/operation-coverage.yaml +24 -24
  7. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/pyproject.toml +1 -1
  8. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/_generated/models.py +407 -42
  9. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/_transport.py +9 -4
  10. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/errors.py +6 -3
  11. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_client.py +1 -1
  12. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_cloud_drive.py +3 -1
  13. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_errors.py +11 -1
  14. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_generation.py +17 -3
  15. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_streaming.py +8 -4
  16. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_template_lifecycle.py +9 -2
  17. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_transport.py +28 -13
  18. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/typing/consumer.py +1 -1
  19. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/uv.lock +1 -1
  20. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/.env.example +0 -0
  21. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/.github/workflows/release.yml +0 -0
  22. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/.gitignore +0 -0
  23. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/AGENTS.md +0 -0
  24. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/CONTEXT.md +0 -0
  25. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/LICENSE +0 -0
  26. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/NOTICE +0 -0
  27. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/scripts/check_installed_package.py +0 -0
  28. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/scripts/check_release.py +0 -0
  29. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/scripts/generate_models.py +0 -0
  30. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/__init__.py +0 -0
  31. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/_generated/__init__.py +0 -0
  32. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/_hashes.py +0 -0
  33. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/_wire_validation.py +0 -0
  34. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/client.py +0 -0
  35. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/__init__.py +0 -0
  36. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/_attachment_content.py +0 -0
  37. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/cloud_drive.py +0 -0
  38. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/groups.py +0 -0
  39. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/literature.py +0 -0
  40. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/notebooks.py +0 -0
  41. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/records.py +0 -0
  42. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/templates.py +0 -0
  43. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/uploads.py +0 -0
  44. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/domains/users.py +0 -0
  45. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/py.typed +0 -0
  46. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/session.py +0 -0
  47. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/src/matelab/streaming.py +0 -0
  48. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/conftest.py +0 -0
  49. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/provider/test_provider_smoke.py +0 -0
  50. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_async_attachment_upload.py +0 -0
  51. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_comments_and_downloads.py +0 -0
  52. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_consumer_smoke.py +0 -0
  53. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_extended_records.py +0 -0
  54. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_groups.py +0 -0
  55. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_notebook_lifecycle.py +0 -0
  56. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_notebooks.py +0 -0
  57. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_operation_coverage.py +0 -0
  58. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_record_lifecycle.py +0 -0
  59. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_record_mutations.py +0 -0
  60. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_records.py +0 -0
  61. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_release.py +0 -0
  62. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_templates.py +0 -0
  63. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_uploads_and_literature.py +0 -0
  64. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/test_users.py +0 -0
  65. {matelab_python_sdk-0.1.0a16 → matelab_python_sdk-0.1.0a18}/tests/typing/pyproject.toml +0 -0
@@ -3,6 +3,30 @@
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.0a18 - 2026-08-23
7
+
8
+ - Adopts immutable `matelab-spec v0.4.2` at commit `a51483f910440fbbbc3693cc32566482064bb3ab` and OpenAPI
9
+ SHA-256 `4c92b96ba3dfe7122b30b4db2e2c8054c06018291c8c52c15482112b51a32920`. The wire schema, methods,
10
+ paths, encodings, operation count, and public interface are unchanged.
11
+ - Records that compatibility evidence remains the stable Provider revision
12
+ `59101f006e9fd6d6ce0b951dfd34695a7949b54f`; the latest reviewed revision
13
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27` is incompatible. The SDK retains the stable multipart comment-upload
14
+ field, while integrations must account for that Provider's DOI rejection, encrypted-search omission, valid
15
+ files-folder-path rejection, and explicit-null table-file-import failure.
16
+
17
+ ## 0.1.0a17 - 2026-08-20
18
+
19
+ - Adopts immutable `matelab-spec v0.4.1` at commit `6f8ab3d14797385d0075d0aba38bf3bf529e674d` and OpenAPI
20
+ SHA-256 `73d899c9e60b59f9521062ffcfaaae5f073eea36f24f3e535fcb53f12242581c`. The standard wire structure is
21
+ unchanged from v0.4.0. PVD-041 and PCG-015 confirm that optional code-4 `errs` remains opaque, potentially sensitive
22
+ and unsafe to expose as a stable typed SDK interface without stronger Provider evidence and a future Contract release.
23
+ - Breaking: `MatelabProviderError` construction now requires `provider_code`, `provider_message`, and `category`.
24
+ Transport and download errors preserve the Provider envelope's numeric `code` and expose an SDK-owned safe summary
25
+ instead of copying Provider-authored diagnostics into exceptions. The stable recovery interface remains `category`
26
+ plus conservative `retryable=False`; raw Provider codes are diagnostic rather than stable routing identifiers.
27
+ Exceptions exclude the response body, top-level `msg`, legacy `errmsg`, opaque `errs`, uncontracted debug fields, and
28
+ request payloads because Provider text may contain stack traces, credentials, or submitted values.
29
+
6
30
  ## 0.1.0a16 - 2026-08-14
7
31
 
8
32
  - Breaking: `UserSummary.display_name` is renamed to `name`; the SDK exposes the Provider's raw nullable real name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matelab-python-sdk
3
- Version: 0.1.0a16
3
+ Version: 0.1.0a18
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.0a16`. `[project].version` in `pyproject.toml` is the sole SDK version source;
38
+ The current alpha is `0.1.0a18`. `[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.0` Contract Release. The sole release pin is
41
+ The SDK is pinned to the immutable `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,18 @@ 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.0a16-py3-none-any.whl
67
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a18-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 remain compatible with the stable Provider evidence at
74
+ `59101f006e9fd6d6ce0b951dfd34695a7949b54f`. The latest reviewed Provider,
75
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27`, is incompatible with that evidence. Its operation-specific
76
+ differences are documented alongside the affected interfaces below; do not treat a successful Contract adoption as
77
+ proof that this newer Provider revision is interchangeable.
78
+
73
79
  ## Design
74
80
 
75
81
  The public module is intentionally small:
@@ -93,29 +99,37 @@ explicitly when needed, for example `AsyncMatelab("https://custom.example/api")`
93
99
  ### Error handling
94
100
 
95
101
  Catch `MatelabError` once at an integration seam. Every instance exposes a stable `category: MatelabErrorCategory` and
96
- `retryable: bool`, so an integration can copy the message, category, and retry flag without inspecting subclasses or
97
- Provider details:
102
+ `retryable: bool`. `MatelabProviderError` additionally exposes `provider_code: int` and `provider_message: str`, so a
103
+ gateway can retain a stable diagnostic code and safe summary while routing recovery through the integration-level
104
+ category:
98
105
 
99
106
  | Error | Category | Retryable | Meaning and normal response |
100
107
  |---|---|---:|---|
101
108
  | `MatelabAuthenticationError` | `AUTHENTICATION` | No | The Session or credentials cannot authenticate; obtain valid authentication before making a new call. |
102
109
  | `MatelabUsageError` | `VALIDATION` | No | The call cannot be represented safely; correct its arguments. |
103
- | `MatelabProviderError` | `BUSINESS`, `VALIDATION`, or `UPSTREAM` | No | The Provider rejected the request; route directly by `category`. |
110
+ | `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. |
104
111
  | `MatelabTransportError` | `UPSTREAM` | No | The HTTP exchange failed; `status_code` is present for HTTP failures, and a mutation outcome may be unknown. |
105
112
  | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract; treat it as Provider drift or an SDK defect. |
106
113
 
107
114
  For `MatelabProviderError`, the SDK maps Provider wire code `2` to `BUSINESS`, `4` to `VALIDATION`, and `3` or an
108
- unknown code to `UPSTREAM`. Authentication codes are hidden behind `MatelabAuthenticationError`; raw Provider codes
109
- are not part of the public error interface. Code `5` triggers at most one refresh and replay only for authenticated
110
- operations that explicitly enable `retry_on_access_expired`; otherwise codes `1` and `5` raise
111
- `MatelabAuthenticationError` directly.
115
+ unknown code to `UPSTREAM`. `provider_code` is diagnostic metadata, not a stable routing identifier, and integrations
116
+ must not reinterpret it instead of `category`. `provider_message` and the exception string are SDK-owned safe summaries
117
+ selected from the code mapping; they do not reproduce Provider-authored text. Authentication codes remain hidden behind
118
+ `MatelabAuthenticationError`; code `5`
119
+ triggers at most one refresh and replay only for authenticated operations that explicitly enable
120
+ `retry_on_access_expired`, otherwise codes `1` and `5` raise `MatelabAuthenticationError` directly.
112
121
  Codes `0` and `10` remain operation-specific successes selected by the pinned Contract; an operation that receives a
113
122
  success code it does not allow raises `MatelabProtocolError` rather than assigning an error category.
114
- `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies and caller inputs are
115
- never attached to exceptions. `retryable` means the identical SDK call is safe to replay without further
116
- interpretation. It is conservatively `False` for every current SDK error because the Contract does not guarantee
117
- mutation idempotency or outcome; an integration may add a narrower operation-specific retry policy only when it owns
118
- that evidence.
123
+ `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
124
+ legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
125
+ Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
126
+ The pinned v0.4.2 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record incompatible observed
127
+ item/container shapes and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
128
+ therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
129
+ interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
130
+ means the identical SDK call is safe to replay without further interpretation. It is conservatively `False` for every
131
+ current SDK error because the Contract does not guarantee mutation idempotency or outcome; an integration may add a
132
+ narrower operation-specific retry policy only when it owns that evidence.
119
133
 
120
134
  ### Session ownership
121
135
 
@@ -438,7 +452,7 @@ targets = await client.users.search("Example Researcher", global_scope=False)
438
452
  `groups.list()` returns the `GroupSummary` tuple directly. Ordering remains Provider-unspecified and is documented
439
453
  rather than repeated as a constant result field. The Provider's members for an unstable first group remain wire-only;
440
454
  `users.search()` is the public recipient-discovery interface. These two discovery interfaces are experimental because
441
- group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029, PCG-011).
455
+ group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029).
442
456
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
443
457
  exposing the Provider's data-server routing value.
444
458
 
@@ -530,6 +544,8 @@ relations = await client.records.relations(source)
530
544
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
531
545
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
532
546
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
547
+ The latest reviewed Provider excludes encrypted records from search (PVD-043); an empty search result therefore does
548
+ not prove that no matching encrypted record exists.
533
549
 
534
550
  The Provider calls its notebook directory tree `subtype`; that name remains wire-only. The SDK exposes
535
551
  `RecordFolder`, `RecordSummary.folder_id`, and the `folders` returned with record listings. A top-level folder has
@@ -579,8 +595,9 @@ UID. Import validates the complete batch with generated wire models but cannot m
579
595
  individual inputs or promise atomicity (PCG-008); it therefore returns only the tuple of database IDs actually
580
596
  reported by the Provider. `RecordImportItem.keywords` is a tuple; the adapter owns the Provider's
581
597
  legacy semicolon encoding. Folder paths are ordered existing folder titles from the notebook root; they do not create
582
- missing folders. Delete means moving records into the recycle bin, not permanent
583
- deletion. Delete and restore return `None`; record mutations are not automatically retried.
598
+ missing folders. The latest reviewed Provider rejects explicit-null table-file imports (PVD-045), so integrations
599
+ targeting it must not interpret that rejection as an invalid SDK input. Delete means moving records into the recycle bin,
600
+ not permanent deletion. Delete and restore return `None`; record mutations are not automatically retried.
584
601
 
585
602
  `records.copy()` accepts an optional `new_record_uid`; when omitted, the SDK generates one locally. The Provider
586
603
  returns only the copied row's database ID, so retaining that UID lets the SDK return a complete `RecordLocator`
@@ -597,7 +614,9 @@ returns the acknowledgement classification
597
614
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
598
615
  retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
599
616
  `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
600
- password lifecycle remain unexposed.
617
+ password lifecycle remain unexposed. The latest reviewed Provider rejects a valid files-folder append path
618
+ (PVD-044); integrations targeting it must not reinterpret that rejection as invalid SDK input, and should treat a
619
+ staged attachment as indeterminate once the write has started.
601
620
 
602
621
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-019
603
622
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -609,8 +628,9 @@ ignores target notebook identity (PVD-020); its mutation likewise performs autho
609
628
  `records.comments()`. Each returned `RecordRelationRef` carries only the relation row and declared target IDs.
610
629
  Deletion accepts the source `RecordLocator` and one of those observed refs.
611
630
 
612
- Comment upload follows the Provider's literal one-request `upload` field, not the incompatible Front fragment
613
- protocol (PVD-037). Comment mutations return `None` after acknowledgement. Edit first verifies that the selected
631
+ Comment upload follows the stable Provider's literal one-request `upload` field. The latest reviewed Provider renames
632
+ that field (PVD-037), but the SDK retains the Contract-compatible `upload` encoding. Comment mutations return `None`
633
+ after acknowledgement. Edit first verifies that the selected
614
634
  comment is currently observed and caller-owned because the Provider otherwise reports a false success for a missing or
615
635
  other-user ID (PVD-004). Delete sends the typed ref directly because the Provider mutation itself enforces record and
616
636
  caller ownership. Neither operation performs a post-write read. Staged comment attachments have no Contract abort
@@ -689,7 +709,9 @@ The Provider's static literature form definition and extraction deployment flag
689
709
  `extract_metadata()` directly and handle an unavailable or failing optional backend as a Provider error. Extraction
690
710
  returns a `PublicationMetadataCandidate`: unstored, rich publication evidence rather than metadata already attached to
691
711
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
692
- completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. Literature list
712
+ completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. The latest reviewed Provider
713
+ rejects DOI formats accepted by the stable evidence (PVD-042), so a rejection from that revision does not by itself
714
+ make a DOI invalid for this SDK interface. Literature list
693
715
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
694
716
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
695
717
  JSON produces the Provider's empty-array fallback; otherwise it contains decoded stored metadata without arbitrary
@@ -714,7 +736,7 @@ canonical update preflights the raw item response and refuses to drop top-level
714
736
  `allow_source_metadata_loss=True` explicitly skips that preflight and sends the canonical replacement directly. The
715
737
  default read/check/write protection is best effort rather than atomic because the Provider offers no revision or
716
738
  compare-and-swap condition; this Provider-specific behavior remains internal to the update operation (PVD-027).
717
- PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata (PCG-010).
739
+ PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata.
718
740
  Permanent personal deletion is named `permanently_delete`, returns `None`, and is non-recoverable. Sharing requires
719
741
  list-observed item summaries, user-search summaries and a
720
742
  valid caller identity, then returns `None` because the Provider supplies no per-recipient IDs (PVD-012, PVD-036).
@@ -751,7 +773,7 @@ time strings.
751
773
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
752
774
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
753
775
  the Provider binds by temporary row ID without checking its owner (PVD-031), and finalize atomicity/idempotency remain
754
- absent (PCG-012). Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
776
+ absent. Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
755
777
  deletion is named `permanently_delete_files` and is non-recoverable. Cloud downloads
756
778
  resolve bytes from the final file identity and reuse `DownloadStream`, thumbnail/preview choices and the PVD-002-safe
757
779
  range subset. Cloud mutations are not automatically retried.
@@ -798,8 +820,9 @@ does not expose a signing operation, signature projection or credentials for the
798
820
  results only report whether Provider policy allows signing.
799
821
 
800
822
  Errors are separated into semantic Provider errors, authentication errors, HTTP/transport errors,
801
- Integration Contract response errors, and client-side usage errors. Provider response bodies and caller inputs do not
802
- enter exceptions.
823
+ Integration Contract response errors, and client-side usage errors. Semantic Provider errors retain only the
824
+ Contract-defined top-level code plus an SDK-owned safe summary; Provider-authored messages, response bodies, legacy
825
+ aliases, and unrelated fields do not enter exceptions.
803
826
 
804
827
  ## Development
805
828
 
@@ -892,6 +915,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
892
915
  ```
893
916
 
894
917
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
895
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.0`,
896
- commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7`, and OpenAPI SHA-256
897
- `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`.
918
+ byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.2`,
919
+ commit `a51483f910440fbbbc3693cc32566482064bb3ab`, and OpenAPI SHA-256
920
+ `4c92b96ba3dfe7122b30b4db2e2c8054c06018291c8c52c15482112b51a32920`.
@@ -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.0a16`. `[project].version` in `pyproject.toml` is the sole SDK version source;
10
+ The current alpha is `0.1.0a18`. `[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.0` Contract Release. The sole release pin is
13
+ The SDK is pinned to the immutable `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,18 @@ 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.0a16-py3-none-any.whl
39
+ python -m pip install dist/release/matelab_python_sdk-0.1.0a18-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 remain compatible with the stable Provider evidence at
46
+ `59101f006e9fd6d6ce0b951dfd34695a7949b54f`. The latest reviewed Provider,
47
+ `a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27`, is incompatible with that evidence. Its operation-specific
48
+ differences are documented alongside the affected interfaces below; do not treat a successful Contract adoption as
49
+ proof that this newer Provider revision is interchangeable.
50
+
45
51
  ## Design
46
52
 
47
53
  The public module is intentionally small:
@@ -65,29 +71,37 @@ explicitly when needed, for example `AsyncMatelab("https://custom.example/api")`
65
71
  ### Error handling
66
72
 
67
73
  Catch `MatelabError` once at an integration seam. Every instance exposes a stable `category: MatelabErrorCategory` and
68
- `retryable: bool`, so an integration can copy the message, category, and retry flag without inspecting subclasses or
69
- Provider details:
74
+ `retryable: bool`. `MatelabProviderError` additionally exposes `provider_code: int` and `provider_message: str`, so a
75
+ gateway can retain a stable diagnostic code and safe summary while routing recovery through the integration-level
76
+ category:
70
77
 
71
78
  | Error | Category | Retryable | Meaning and normal response |
72
79
  |---|---|---:|---|
73
80
  | `MatelabAuthenticationError` | `AUTHENTICATION` | No | The Session or credentials cannot authenticate; obtain valid authentication before making a new call. |
74
81
  | `MatelabUsageError` | `VALIDATION` | No | The call cannot be represented safely; correct its arguments. |
75
- | `MatelabProviderError` | `BUSINESS`, `VALIDATION`, or `UPSTREAM` | No | The Provider rejected the request; route directly by `category`. |
82
+ | `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. |
76
83
  | `MatelabTransportError` | `UPSTREAM` | No | The HTTP exchange failed; `status_code` is present for HTTP failures, and a mutation outcome may be unknown. |
77
84
  | `MatelabProtocolError` | `UPSTREAM` | No | The response violates the pinned Contract; treat it as Provider drift or an SDK defect. |
78
85
 
79
86
  For `MatelabProviderError`, the SDK maps Provider wire code `2` to `BUSINESS`, `4` to `VALIDATION`, and `3` or an
80
- unknown code to `UPSTREAM`. Authentication codes are hidden behind `MatelabAuthenticationError`; raw Provider codes
81
- are not part of the public error interface. Code `5` triggers at most one refresh and replay only for authenticated
82
- operations that explicitly enable `retry_on_access_expired`; otherwise codes `1` and `5` raise
83
- `MatelabAuthenticationError` directly.
87
+ unknown code to `UPSTREAM`. `provider_code` is diagnostic metadata, not a stable routing identifier, and integrations
88
+ must not reinterpret it instead of `category`. `provider_message` and the exception string are SDK-owned safe summaries
89
+ selected from the code mapping; they do not reproduce Provider-authored text. Authentication codes remain hidden behind
90
+ `MatelabAuthenticationError`; code `5`
91
+ triggers at most one refresh and replay only for authenticated operations that explicitly enable
92
+ `retry_on_access_expired`, otherwise codes `1` and `5` raise `MatelabAuthenticationError` directly.
84
93
  Codes `0` and `10` remain operation-specific successes selected by the pinned Contract; an operation that receives a
85
94
  success code it does not allow raises `MatelabProtocolError` rather than assigning an error category.
86
- `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies and caller inputs are
87
- never attached to exceptions. `retryable` means the identical SDK call is safe to replay without further
88
- interpretation. It is conservatively `False` for every current SDK error because the Contract does not guarantee
89
- mutation idempotency or outcome; an integration may add a narrower operation-specific retry policy only when it owns
90
- that evidence.
95
+ `MatelabTransportError.status_code` remains available for HTTP failures. Provider response bodies, top-level `msg`,
96
+ legacy `errmsg`, opaque `errs`, uncontracted debug fields, and request payloads are not attached to exceptions because
97
+ Provider-authored diagnostics may contain stack traces, credentials, or submitted values.
98
+ The pinned v0.4.2 Contract also declares optional code-4 `errs`, but PVD-041 and PCG-015 record incompatible observed
99
+ item/container shapes and insufficient evidence for requiredness, cardinality, or exclusion from other codes. The SDK
100
+ therefore keeps those diagnostics wire-only and does not expose `errs` as stable public metadata. A typed detail
101
+ interface remains blocked until a future Contract release can define one from stronger Provider evidence. `retryable`
102
+ means the identical SDK call is safe to replay without further interpretation. It is conservatively `False` for every
103
+ current SDK error because the Contract does not guarantee mutation idempotency or outcome; an integration may add a
104
+ narrower operation-specific retry policy only when it owns that evidence.
91
105
 
92
106
  ### Session ownership
93
107
 
@@ -410,7 +424,7 @@ targets = await client.users.search("Example Researcher", global_scope=False)
410
424
  `groups.list()` returns the `GroupSummary` tuple directly. Ordering remains Provider-unspecified and is documented
411
425
  rather than repeated as a constant result field. The Provider's members for an unstable first group remain wire-only;
412
426
  `users.search()` is the public recipient-discovery interface. These two discovery interfaces are experimental because
413
- group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029, PCG-011).
427
+ group order is unstable and user search is unpaged, unordered and not field-minimized (PVD-006, PVD-029).
414
428
  `GroupSummary.notebook_creation_available` expresses whether the group can currently host notebook creation without
415
429
  exposing the Provider's data-server routing value.
416
430
 
@@ -502,6 +516,8 @@ relations = await client.records.relations(source)
502
516
  as `modules`; it is not the template-shaped `RecordImportItem.data` accepted by record import.
503
517
  `records.search()` maps each requested field name to a stored record path. A match exposes only Provider-returned
504
518
  entries in `values`, so key membership distinguishes an absent result from an explicit JSON `null`.
519
+ The latest reviewed Provider excludes encrypted records from search (PVD-043); an empty search result therefore does
520
+ not prove that no matching encrypted record exists.
505
521
 
506
522
  The Provider calls its notebook directory tree `subtype`; that name remains wire-only. The SDK exposes
507
523
  `RecordFolder`, `RecordSummary.folder_id`, and the `folders` returned with record listings. A top-level folder has
@@ -551,8 +567,9 @@ UID. Import validates the complete batch with generated wire models but cannot m
551
567
  individual inputs or promise atomicity (PCG-008); it therefore returns only the tuple of database IDs actually
552
568
  reported by the Provider. `RecordImportItem.keywords` is a tuple; the adapter owns the Provider's
553
569
  legacy semicolon encoding. Folder paths are ordered existing folder titles from the notebook root; they do not create
554
- missing folders. Delete means moving records into the recycle bin, not permanent
555
- deletion. Delete and restore return `None`; record mutations are not automatically retried.
570
+ missing folders. The latest reviewed Provider rejects explicit-null table-file imports (PVD-045), so integrations
571
+ targeting it must not interpret that rejection as an invalid SDK input. Delete means moving records into the recycle bin,
572
+ not permanent deletion. Delete and restore return `None`; record mutations are not automatically retried.
556
573
 
557
574
  `records.copy()` accepts an optional `new_record_uid`; when omitted, the SDK generates one locally. The Provider
558
575
  returns only the copied row's database ID, so retaining that UID lets the SDK return a complete `RecordLocator`
@@ -569,7 +586,9 @@ returns the acknowledgement classification
569
586
  issue a post-write read. Database, active-browser, and unclassified acknowledgements remain distinct, and mutation
570
587
  retries stay disabled. Encrypted record content is outside the SDK's public read/update interface: the list-level
571
588
  `RecordSummary.encrypted` flag lets callers identify and skip it, while the Provider password field and frontend-only
572
- password lifecycle remain unexposed.
589
+ password lifecycle remain unexposed. The latest reviewed Provider rejects a valid files-folder append path
590
+ (PVD-044); integrations targeting it must not reinterpret that rejection as invalid SDK input, and should treat a
591
+ staged attachment as indeterminate once the write has started.
573
592
 
574
593
  Relation addition reads both endpoints and checks their resolved data server before writing; this reduces PVD-019
575
594
  risk but is not an atomic Provider authorization guarantee. It does not list relations merely to inspect the
@@ -581,8 +600,9 @@ ignores target notebook identity (PVD-020); its mutation likewise performs autho
581
600
  `records.comments()`. Each returned `RecordRelationRef` carries only the relation row and declared target IDs.
582
601
  Deletion accepts the source `RecordLocator` and one of those observed refs.
583
602
 
584
- Comment upload follows the Provider's literal one-request `upload` field, not the incompatible Front fragment
585
- protocol (PVD-037). Comment mutations return `None` after acknowledgement. Edit first verifies that the selected
603
+ Comment upload follows the stable Provider's literal one-request `upload` field. The latest reviewed Provider renames
604
+ that field (PVD-037), but the SDK retains the Contract-compatible `upload` encoding. Comment mutations return `None`
605
+ after acknowledgement. Edit first verifies that the selected
586
606
  comment is currently observed and caller-owned because the Provider otherwise reports a false success for a missing or
587
607
  other-user ID (PVD-004). Delete sends the typed ref directly because the Provider mutation itself enforces record and
588
608
  caller ownership. Neither operation performs a post-write read. Staged comment attachments have no Contract abort
@@ -661,7 +681,9 @@ The Provider's static literature form definition and extraction deployment flag
661
681
  `extract_metadata()` directly and handle an unavailable or failing optional backend as a Provider error. Extraction
662
682
  returns a `PublicationMetadataCandidate`: unstored, rich publication evidence rather than metadata already attached to
663
683
  a literature item. Its structured authors are `PublicationAuthorCandidate` values. Extraction accepts a DOI, a
664
- completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. Literature list
684
+ completed staged PDF, or both; a supplied DOI takes precedence over the staged PDF. The latest reviewed Provider
685
+ rejects DOI formats accepted by the stable evidence (PVD-042), so a rejection from that revision does not by itself
686
+ make a DOI invalid for this SDK interface. Literature list
665
687
  results likewise exclude Provider-generated citation HTML and author-highlight fragments; Consumers receive the
666
688
  underlying citation fields instead of presentation markup. `LiteratureDetail.metadata` is `None` when invalid legacy
667
689
  JSON produces the Provider's empty-array fallback; otherwise it contains decoded stored metadata without arbitrary
@@ -686,7 +708,7 @@ canonical update preflights the raw item response and refuses to drop top-level
686
708
  `allow_source_metadata_loss=True` explicitly skips that preflight and sends the canonical replacement directly. The
687
709
  default read/check/write protection is best effort rather than atomic because the Provider offers no revision or
688
710
  compare-and-swap condition; this Provider-specific behavior remains internal to the update operation (PVD-027).
689
- PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata (PCG-010).
711
+ PDF replace/delete are separate acknowledged mutations and are not presented as atomic with metadata.
690
712
  Permanent personal deletion is named `permanently_delete`, returns `None`, and is non-recoverable. Sharing requires
691
713
  list-observed item summaries, user-search summaries and a
692
714
  valid caller identity, then returns `None` because the Provider supplies no per-recipient IDs (PVD-012, PVD-036).
@@ -723,7 +745,7 @@ time strings.
723
745
  Folder create returns a `CloudFolderRef` built from the Provider ID. Other folder and file mutations return `None`
724
746
  after acknowledgement and do not automatically list the drive. Staged finalize accepts a completed `StagedFile`;
725
747
  the Provider binds by temporary row ID without checking its owner (PVD-031), and finalize atomicity/idempotency remain
726
- absent (PCG-012). Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
748
+ absent. Batch move and permanent delete do not claim Provider per-item results or atomicity. Permanent
727
749
  deletion is named `permanently_delete_files` and is non-recoverable. Cloud downloads
728
750
  resolve bytes from the final file identity and reuse `DownloadStream`, thumbnail/preview choices and the PVD-002-safe
729
751
  range subset. Cloud mutations are not automatically retried.
@@ -770,8 +792,9 @@ does not expose a signing operation, signature projection or credentials for the
770
792
  results only report whether Provider policy allows signing.
771
793
 
772
794
  Errors are separated into semantic Provider errors, authentication errors, HTTP/transport errors,
773
- Integration Contract response errors, and client-side usage errors. Provider response bodies and caller inputs do not
774
- enter exceptions.
795
+ Integration Contract response errors, and client-side usage errors. Semantic Provider errors retain only the
796
+ Contract-defined top-level code plus an SDK-owned safe summary; Provider-authored messages, response bodies, legacy
797
+ aliases, and unrelated fields do not enter exceptions.
775
798
 
776
799
  ## Development
777
800
 
@@ -864,6 +887,6 @@ uv run python scripts/check_release.py dist/release/*.whl dist/release/*.tar.gz
864
887
  ```
865
888
 
866
889
  Rebuilding the same commit with the same locked environment and `SOURCE_DATE_EPOCH` must produce
867
- byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.0`,
868
- commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7`, and OpenAPI SHA-256
869
- `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`.
890
+ byte-identical wheel and source distribution hashes. The release is bound to `matelab-spec v0.4.2`,
891
+ commit `a51483f910440fbbbc3693cc32566482064bb3ab`, and OpenAPI SHA-256
892
+ `4c92b96ba3dfe7122b30b4db2e2c8054c06018291c8c52c15482112b51a32920`.
@@ -2,12 +2,12 @@
2
2
  "schema_version": 1,
3
3
  "contract_line": "integration-v1",
4
4
  "release": {
5
- "tag": "v0.4.0",
6
- "commit": "7993a7bccc213f626b9cc8124423e2b2c9e48dd7"
5
+ "tag": "v0.4.2",
6
+ "commit": "a51483f910440fbbbc3693cc32566482064bb3ab"
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": "e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e"
11
+ "sha256": "4c92b96ba3dfe7122b30b4db2e2c8054c06018291c8c52c15482112b51a32920"
12
12
  }
13
13
  }
@@ -1,7 +1,7 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
3
  title: Matelab Integration Contract
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  description: |
6
6
  Stable PHP wire contract for the `integration-v1` contract line.
7
7
  Business failures are returned as JSON envelopes over HTTP 200.
@@ -32,10 +32,21 @@ info:
32
32
  - lib/Base.php
33
33
  - lib/Route.php
34
34
  - lib/HttpServer.php
35
+ - lib/MultiException.php
35
36
  - config/Channel.php
36
37
  - sql/eln.sql
37
38
  - sql/matelab.sql
38
39
  - sql/recommend.sql
40
+ x-provider-audit:
41
+ latestReviewedCommit: a3e6b961800f6b1ab666f0d3f6cd4c64c2a3ce27
42
+ stableEvidenceCommit: 59101f006e9fd6d6ce0b951dfd34695a7949b54f
43
+ compatibility: incompatible
44
+ regressions:
45
+ - {issue: PVD-037, operationId: uploadRecordCommentAttachment}
46
+ - {issue: PVD-042, operationId: extractLiteratureMetadata}
47
+ - {issue: PVD-043, operationId: searchRecordData}
48
+ - {issue: PVD-044, operationId: updateRecordData}
49
+ - {issue: PVD-045, operationId: importRecordDataset}
39
50
  x-consumer-evidence:
40
51
  - repository: /home/tnzhu/projects/matelab-mcp
41
52
  commit: 94a129b2df0ef0fbcf179c10550fb7c9a5dd2e6f
@@ -172,6 +183,25 @@ info:
172
183
  pathSegments: 2
173
184
  readback: column-absent-and-table-rows-preserved
174
185
  cellLikeThreeSegmentPath: deletes-whole-column-not-cell
186
+ x-provider-error-diagnostics:
187
+ status: evidence-gap
188
+ tracking: [PVD-041, PCG-015]
189
+ typedPublicInterface: unsafe
190
+ code4:
191
+ errsRequired: unverified
192
+ errsMinItems: unverified
193
+ errsOnOtherCodes: not-observed-but-not-contracted
194
+ releasedContainerShape: array
195
+ sourceConfirmedArrayItemShapes: [string, object, nested-object]
196
+ sourceConfirmedContractViolations: [object-container-from-file-validator-envelope-merge]
197
+ responsibilities:
198
+ codeAndErrcode: machine-readable-envelope-status
199
+ msgAndErrmsg: human-oriented-summary-not-a-stable-identifier
200
+ errs: opaque-provider-diagnostics
201
+ securityBoundary:
202
+ trust: untrusted-potentially-sensitive
203
+ observedContent: [localized-validation-text, request-derived-values, stored-field-names]
204
+ stackTraceExclusion: not-contractually-guaranteed
175
205
  servers:
176
206
  - url: https://matelab.example.invalid
177
207
  description: Placeholder; consumers supply their Provider base URL.
@@ -943,7 +973,7 @@ paths:
943
973
  product capability and the notebook/template share routes do not require
944
974
  common group membership. The contract still narrows the keyword to a
945
975
  bounded, non-blank 2–100-character string and records the unpaged global
946
- directory as PVD-029/PCG-011.
976
+ directory as PVD-029.
947
977
  x-consumer-use-case: Resolve same-institute or global target user ids before notebook, template, or literature sharing.
948
978
  x-known-provider-issues: [PVD-013, PVD-029]
949
979
  security: [{bearerAuth: []}]
@@ -1487,7 +1517,7 @@ paths:
1487
1517
  Consumers must split attachment-bearing imports into single-record
1488
1518
  requests with a distinct staged name for each request, and must not
1489
1519
  retry a failed finalize with the same name.
1490
- x-known-provider-issues: [PVD-023, PVD-024, PVD-040]
1520
+ x-known-provider-issues: [PVD-023, PVD-024, PVD-040, PVD-041, PVD-045]
1491
1521
  security: [{bearerAuth: []}]
1492
1522
  requestBody:
1493
1523
  required: true
@@ -1577,6 +1607,12 @@ paths:
1577
1607
  operationId: searchRecordData
1578
1608
  tags: [Records]
1579
1609
  summary: Search notebooks and extract requested dynamic fields
1610
+ description: |
1611
+ The released contract is backed by Provider commit `59101f0`. The latest
1612
+ reviewed Provider commit excludes encrypted records before applying the
1613
+ requested filters, which is a response-subtractive behavior change still
1614
+ awaiting policy confirmation and Provider Verification under PVD-043.
1615
+ x-known-provider-issues: [PVD-043]
1580
1616
  security: [{bearerAuth: []}]
1581
1617
  requestBody:
1582
1618
  required: true
@@ -1627,6 +1663,15 @@ paths:
1627
1663
  caller-owned staging or authorized existing file quotes, and binds the
1628
1664
  resulting attachments while saving the record.
1629
1665
 
1666
+ This operation does not modify record title or other record metadata.
1667
+ `UpdateRecordRequest` rejects a top-level `title`; the Front uses the
1668
+ separate, currently unsupported `/eln_items/edit` route for that use
1669
+ case. That candidate route remains outside Supported Routes and has not
1670
+ completed the request-boundary, permission, side-effect, response, and
1671
+ Provider Verification audit required for Integration use. MCP therefore
1672
+ deliberately omits title from `update_record`; the shared capability gap
1673
+ remains tracked as PCG-016.
1674
+
1630
1675
  Verified staged-name update shapes are enumerated by
1631
1676
  `info.x-record-attachment-staging.safeFinalizerShapes.update` and their
1632
1677
  dedicated component schemas. They cover a new form file field, setting
@@ -1649,7 +1694,7 @@ paths:
1649
1694
  consumption are not atomic. Once a finalizer begins, any write error,
1650
1695
  collaboration-pending response, response loss or failed readback leaves
1651
1696
  staging indeterminate and must not be retried.
1652
- x-known-provider-issues: [PVD-014, PVD-015, PVD-016, PVD-017, PVD-040]
1697
+ x-known-provider-issues: [PVD-014, PVD-015, PVD-016, PVD-017, PVD-040, PVD-041, PVD-044]
1653
1698
  security: [{bearerAuth: []}]
1654
1699
  requestBody:
1655
1700
  required: true
@@ -3373,6 +3418,7 @@ paths:
3373
3418
  external to the PHP Provider and can omit fields or return additional
3374
3419
  fields, so only the documented candidate fields are promised.
3375
3420
  x-consumer-use-case: Prefill canonical literature metadata before import from a DOI or staged PDF.
3421
+ x-known-provider-issues: [PVD-042]
3376
3422
  security: [{bearerAuth: []}]
3377
3423
  requestBody:
3378
3424
  required: true
@@ -3456,7 +3502,7 @@ paths:
3456
3502
  both branches must verify the stored result through
3457
3503
  `readLiteratureDetail`. Create-time file binding is affected by PVD-026.
3458
3504
  x-consumer-use-case: Create canonical personal literature with an optional staged PDF, or replace the canonical metadata of a writable item.
3459
- x-known-provider-issues: [PVD-011, PVD-026, PVD-027]
3505
+ x-known-provider-issues: [PVD-011, PVD-026, PVD-027, PVD-041]
3460
3506
  security: [{bearerAuth: []}]
3461
3507
  requestBody:
3462
3508
  required: true
@@ -4062,12 +4108,19 @@ components:
4062
4108
  type: integer
4063
4109
  msg:
4064
4110
  type: string
4111
+ description: |
4112
+ Human-oriented envelope summary. Consumers must use `code` for
4113
+ branching and must not parse this text as a stable identifier,
4114
+ field location, or retry signal.
4065
4115
  errcode:
4066
4116
  type: integer
4067
4117
  description: Legacy alias of `code`; always present in these operations.
4068
4118
  errmsg:
4069
4119
  type: string
4070
- description: Legacy alias of `msg`; always present in these operations.
4120
+ description: |
4121
+ Legacy alias of `msg`; always present in these operations. It has
4122
+ the same human-summary responsibility and is not a structured
4123
+ diagnostic field.
4071
4124
  BasicSuccessResponse:
4072
4125
  allOf:
4073
4126
  - $ref: "#/components/schemas/ResponseEnvelope"
@@ -4083,7 +4136,14 @@ components:
4083
4136
  code: {enum: [0, 10]}
4084
4137
  errcode: {enum: [0, 10]}
4085
4138
  ErrorDetail:
4086
- description: A stable per-field or per-location error value returned when code is 4.
4139
+ description: |
4140
+ Intentionally unconstrained Provider diagnostic array item. Source
4141
+ evidence includes strings, structured objects, sparse objects, and
4142
+ nested error groups. Integration-v1 therefore does not promise a stable
4143
+ item shape. The separate source-confirmed object-container branch
4144
+ violates ErrorResponse and is tracked by PVD-041 and PCG-015.
4145
+ x-contract-status: evidence-gap
4146
+ x-tracking: [PVD-041, PCG-015]
4087
4147
  ErrorResponse:
4088
4148
  allOf:
4089
4149
  - $ref: "#/components/schemas/ResponseEnvelope"
@@ -4106,11 +4166,23 @@ components:
4106
4166
  type: array
4107
4167
  items:
4108
4168
  $ref: "#/components/schemas/ErrorDetail"
4109
- description: Present for multi-error code 4; absent from ordinary errors.
4169
+ description: |
4170
+ Optional array of opaque, untrusted Provider diagnostics
4171
+ observed on code 4. Integration-v1 does not constrain its
4172
+ requiredness, cardinality, item shape, order, or absence on
4173
+ other codes. Values can contain localized validation text,
4174
+ request-derived values, or stored field names and must not be
4175
+ broadly logged or displayed without sanitization. No
4176
+ stack-trace exclusion is contractually guaranteed. The
4177
+ Provider's source-confirmed object-container branch violates
4178
+ this released array contract; see PVD-041 and PCG-015.
4179
+ x-known-provider-issues: [PVD-041]
4110
4180
  description: |
4111
4181
  Stable HTTP 200 error envelope. Codes observed in the common router are:
4112
4182
  1 authentication, 2 input/permission/business failure, 3 server failure,
4113
- 4 multiple errors (`errs` present), and 5 expired access token.
4183
+ 4 multiple errors (normally with `errs`), and 5 expired access token.
4184
+ `msg`/`errmsg` summarize the envelope for people; `errs`, when present,
4185
+ carries opaque diagnostics and is not a stable public detail interface.
4114
4186
  Sha256:
4115
4187
  type: string
4116
4188
  pattern: "^[0-9a-f]{64}$"