matelab-python-sdk 0.2.0a3__tar.gz → 0.2.0a5__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 (71) hide show
  1. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/.github/workflows/release.yml +1 -1
  2. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/AGENTS.md +10 -10
  3. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/CONTEXT.md +6 -1
  4. matelab_python_sdk-0.2.0a5/PKG-INFO +69 -0
  5. matelab_python_sdk-0.2.0a5/README.md +41 -0
  6. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/contracts/matelab-integration-v1.lock.json +3 -3
  7. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/contracts/matelab-integration-v1.openapi.yaml +95 -39
  8. matelab_python_sdk-0.2.0a5/docs/agent-workflows.md +100 -0
  9. matelab_python_sdk-0.2.0a3/README.md → matelab_python_sdk-0.2.0a5/docs/api.md +34 -153
  10. matelab_python_sdk-0.2.0a5/docs/development.md +68 -0
  11. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/docs/operation-coverage.yaml +3 -3
  12. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/pyproject.toml +14 -13
  13. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/scripts/check_release.py +0 -1
  14. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/__init__.py +2 -0
  15. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/_generated/models.py +16 -1
  16. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/records.py +51 -10
  17. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_records.py +105 -0
  18. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_release.py +2 -2
  19. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/typing/consumer.py +8 -0
  20. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/uv.lock +12 -12
  21. matelab_python_sdk-0.2.0a3/CHANGELOG.md +0 -470
  22. matelab_python_sdk-0.2.0a3/PKG-INFO +0 -26
  23. matelab_python_sdk-0.2.0a3/docs/agent-workflows.md +0 -129
  24. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/.env.example +0 -0
  25. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/.gitignore +0 -0
  26. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/LICENSE +0 -0
  27. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/NOTICE +0 -0
  28. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/docs/agent-architecture.md +0 -0
  29. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/scripts/check_installed_package.py +0 -0
  30. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/scripts/generate_models.py +0 -0
  31. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/_generated/__init__.py +0 -0
  32. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/_hashes.py +0 -0
  33. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/_transport.py +0 -0
  34. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/_wire_validation.py +0 -0
  35. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/client.py +0 -0
  36. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/__init__.py +0 -0
  37. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/_attachment_content.py +0 -0
  38. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/cloud_drive.py +0 -0
  39. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/groups.py +0 -0
  40. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/literature.py +0 -0
  41. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/notebooks.py +0 -0
  42. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/templates.py +0 -0
  43. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/uploads.py +0 -0
  44. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/domains/users.py +0 -0
  45. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/errors.py +0 -0
  46. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/py.typed +0 -0
  47. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/session.py +0 -0
  48. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/src/matelab/streaming.py +0 -0
  49. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/conftest.py +0 -0
  50. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/provider/test_provider_smoke.py +0 -0
  51. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_async_attachment_upload.py +0 -0
  52. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_client.py +0 -0
  53. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_cloud_drive.py +0 -0
  54. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_comments_and_downloads.py +0 -0
  55. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_consumer_smoke.py +0 -0
  56. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_errors.py +0 -0
  57. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_extended_records.py +0 -0
  58. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_generation.py +0 -0
  59. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_groups.py +0 -0
  60. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_notebook_lifecycle.py +0 -0
  61. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_notebooks.py +0 -0
  62. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_operation_coverage.py +0 -0
  63. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_record_lifecycle.py +0 -0
  64. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_record_mutations.py +0 -0
  65. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_streaming.py +0 -0
  66. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_template_lifecycle.py +0 -0
  67. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_templates.py +0 -0
  68. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_transport.py +0 -0
  69. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_uploads_and_literature.py +0 -0
  70. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/test_users.py +0 -0
  71. {matelab_python_sdk-0.2.0a3 → matelab_python_sdk-0.2.0a5}/tests/typing/pyproject.toml +0 -0
@@ -84,7 +84,7 @@ jobs:
84
84
  uv pip install \
85
85
  --python "${RUNNER_TEMP}/matelab-consumer/bin/python" \
86
86
  dist/release/*.whl \
87
- "basedpyright<2,>=1.40.1" \
87
+ "basedpyright>=1.40.1" \
88
88
  "nodejs-wheel-binaries==22.20.0"
89
89
  "${RUNNER_TEMP}/matelab-consumer/bin/python" scripts/check_installed_package.py
90
90
  "${RUNNER_TEMP}/matelab-consumer/bin/basedpyright" \
@@ -4,14 +4,16 @@
4
4
 
5
5
  ## 维护顺序
6
6
 
7
- 1. **定界**:先读 `git status` 和适用权威;完成标准是任务范围、用户现有改动和所需外部权限均已识别。
7
+ 1. **定界**:先读 `git status` 和适用权威,确定任务范围、用户现有改动和所需权限。
8
8
  2. **查证**:涉及 SDK 行为或 Contract 时,沿 public intent → wire operation → Provider evidence 核对受影响
9
9
  operation 的 request、response、security、examples、成功码及 PVD/PCG,明确报告 Contract 缺口。文档、排版和
10
10
  工具配置修改只核对相关权威。
11
11
  3. **收敛**:只修改任务必需的层,检查 public、adapter、generated、tests、coverage 和 docs 中受影响的内容。
12
- 4. **验证**:按变更类型选择 [delivery gate](docs/agent-workflows.md#delivery-gate),先运行相关检查;代码变更先跑
13
- 聚焦测试,再跑完整门槛。完成标准是必需命令全部退出为零,skip 和 deselected 分别说明。
14
- 5. **交付**:复核最终 diff、状态和验证证据;完成标准是结果、限制和未执行项都可由用户独立核对。
12
+ 4. **验证**:按变更类型执行 [delivery gate](docs/agent-workflows.md#delivery-gate),复用仍覆盖当前变更的有效结果。
13
+ 5. **交付**:复核最终 diff 和状态,报告结果、验证证据、限制及未执行项。
14
+
15
+ 本地仅为打包配置、构建元数据、发布脚本变化或制品故障按需构建。正式可复现构建、制品审计和安装后消费由
16
+ 发布 CI 执行,本地无需重复构建或保留历史 `dist/` 产物。
15
17
 
16
18
  ## 分支指针
17
19
 
@@ -23,8 +25,6 @@
23
25
  [`docs/agent-workflows.md#contract-adoption`](docs/agent-workflows.md#contract-adoption)。
24
26
  - **Configuration and dependencies**:修改 `pyproject.toml`、依赖范围、lock 或对应 CI 配置时读
25
27
  [`docs/agent-workflows.md#configuration-and-dependencies`](docs/agent-workflows.md#configuration-and-dependencies)。
26
- - **Delivery gate**:交付前按变更类型执行
27
- [`docs/agent-workflows.md#delivery-gate`](docs/agent-workflows.md#delivery-gate)。
28
28
  - **Provider validation**:任何实时 Provider smoke、读取或 mutation 前执行
29
29
  [`docs/agent-workflows.md#provider-validation`](docs/agent-workflows.md#provider-validation)。
30
30
  - **Release**:准备版本或发布制品时执行;普通 commit/push 只应用其中的授权与 diff 审查要求
@@ -34,16 +34,16 @@
34
34
 
35
35
  | 权威 | 负责内容 |
36
36
  | --- | --- |
37
- | `README.md` | 当前 public interface、集成语义、示例及人类流程 |
37
+ | `README.md` | 项目介绍、安装及快速入门 |
38
+ | `docs/api.md` | 当前 public interface、集成语义、完整示例和 Provider 限制 |
39
+ | `docs/development.md` | 开发、验证、版本与构建流程 |
38
40
  | `CONTEXT.md` | public 类型和命名采用的领域词汇 |
39
- | `CHANGELOG.md` | SDK 版本变化与迁移影响;不定义当前接口 |
40
41
  | `docs/operation-coverage.yaml` | operation 状态、公开入口、稳定性和已知问题 |
41
42
  | `pyproject.toml` | SDK 版本、依赖范围、构建与工具配置;`uv.lock` 只锁定本仓库环境 |
42
43
  | Contract lock 与 snapshot | Contract pin 与 wire schema |
43
44
  | `src/matelab/__init__.py::__all__` | 公开导入边界 |
44
45
 
45
- 机器权威变化时,同一变更同步受影响的当前态文档;历史只追加到 `CHANGELOG.md`。测试提供行为证据,不替代
46
- 接口、coverage 或 Contract 权威。
46
+ 机器权威变化时,同一变更同步受影响的当前态文档。测试提供行为证据,不替代接口、coverage 或 Contract 权威。
47
47
 
48
48
  ## 范围与授权
49
49
 
@@ -63,9 +63,14 @@ _Avoid_: Record locator, public record ref, deleted record ref
63
63
 
64
64
  **Record locator**:
65
65
  A record ref paired with the owned or shared notebook in which it was observed. It is the complete source identity
66
- used by record reads and record-scoped operations.
66
+ used by owned/shared record reads and record-scoped operations.
67
67
  _Avoid_: Record ref, notebook ID
68
68
 
69
+ **Public record ref**:
70
+ A public association's row ID, paired source notebook and record IDs, and nullable association UID metadata.
71
+ The source ID pair locates its current body; it does not grant notebook-wide access.
72
+ _Avoid_: Record locator, public notebook ID, association ID as record ID
73
+
69
74
  **Record version ref**:
70
75
  A historical version ID bound to its record locator. It identifies observed historical content, not a separate active
71
76
  record.
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.5
2
+ Name: matelab-python-sdk
3
+ Version: 0.2.0a5
4
+ Summary: Reusable async Python client for the Matelab Integration Contract
5
+ Author: CMPDC, Institute of Physics, Chinese Academy of Sciences
6
+ License-Expression: Apache-2.0
7
+ License-File: LICENSE
8
+ License-File: NOTICE
9
+ Keywords: asyncio,electronic-lab-notebook,eln,matelab,sdk
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: AsyncIO
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: httpx2>=2.13.1
24
+ Requires-Dist: jsonschema>=4.26.0
25
+ Requires-Dist: pydantic>=2.13.5
26
+ Requires-Dist: typing-extensions>=4.16.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # matelab-python-sdk
30
+
31
+ Async Python client for the Matelab Integration Contract, with typed interfaces for authentication,
32
+ notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.11 or newer.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ uv add matelab-python-sdk
38
+ ```
39
+
40
+ Or use `python -m pip install matelab-python-sdk`.
41
+
42
+ ## Quick start
43
+
44
+ Replace the example credentials with your own:
45
+
46
+ ```python
47
+ import asyncio
48
+
49
+ from matelab import AsyncMatelab
50
+
51
+
52
+ async def main() -> None:
53
+ async with AsyncMatelab() as client:
54
+ await client.authenticate("user@example.org", "password")
55
+ notebooks = await client.notebooks.list()
56
+ for notebook in notebooks.owned:
57
+ print(notebook.ref)
58
+
59
+
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ `AsyncMatelab()` uses `https://matelab.iphy.ac.cn/api` by default. Pass another API root as its first argument.
64
+
65
+ ## Documentation
66
+
67
+ - [API reference](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/api.md): Session persistence, errors, examples, and Provider limits.
68
+ - [Operation coverage](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/operation-coverage.yaml): supported operations.
69
+ - [Development and releases](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/development.md): checks, Provider smoke, versioning, and builds.
@@ -0,0 +1,41 @@
1
+ # matelab-python-sdk
2
+
3
+ Async Python client for the Matelab Integration Contract, with typed interfaces for authentication,
4
+ notebooks, records, attachments, cloud files, templates, and literature. Requires Python 3.11 or newer.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ uv add matelab-python-sdk
10
+ ```
11
+
12
+ Or use `python -m pip install matelab-python-sdk`.
13
+
14
+ ## Quick start
15
+
16
+ Replace the example credentials with your own:
17
+
18
+ ```python
19
+ import asyncio
20
+
21
+ from matelab import AsyncMatelab
22
+
23
+
24
+ async def main() -> None:
25
+ async with AsyncMatelab() as client:
26
+ await client.authenticate("user@example.org", "password")
27
+ notebooks = await client.notebooks.list()
28
+ for notebook in notebooks.owned:
29
+ print(notebook.ref)
30
+
31
+
32
+ asyncio.run(main())
33
+ ```
34
+
35
+ `AsyncMatelab()` uses `https://matelab.iphy.ac.cn/api` by default. Pass another API root as its first argument.
36
+
37
+ ## Documentation
38
+
39
+ - [API reference](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/api.md): Session persistence, errors, examples, and Provider limits.
40
+ - [Operation coverage](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/operation-coverage.yaml): supported operations.
41
+ - [Development and releases](https://github.com/tiannianzhu/matelab-python-sdk/blob/main/docs/development.md): checks, Provider smoke, versioning, and builds.
@@ -2,12 +2,12 @@
2
2
  "schema_version": 1,
3
3
  "contract_line": "integration-v1",
4
4
  "release": {
5
- "tag": "v2026.10.1",
6
- "commit": "9941e2d623a1c2633adb459b823d78d4e62d3802"
5
+ "tag": "v2026.10.2",
6
+ "commit": "1183d6833d88a6904598357321ef2d30cf944339"
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": "a07997128c1df17a03724c5af8e11b45a34166f9d6e15558e66e0a301f2e0813"
11
+ "sha256": "4806fc2e4b4cb4cf94464be6f1b5f574f5a44745bf7cbc03d8644a13e57f8ec9"
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: "2026.10.1"
4
+ version: "2026.10.2"
5
5
  description: |
6
6
  Current PHP wire contract for generating SDKs against the selected
7
7
  `matelab-server` Provider version.
@@ -26,6 +26,7 @@ info:
26
26
  - controller/Eln.php
27
27
  - controller/Eln_api.php
28
28
  - controller/Eln_items.php
29
+ - controller/Eln_public.php
29
30
  - controller/Eln_template.php
30
31
  - controller/Eln_url.php
31
32
  - controller/Files.php
@@ -36,6 +37,7 @@ info:
36
37
  - model/FileQuoteModel.php
37
38
  - model/FilesModel.php
38
39
  - traits/ElnTrait.php
40
+ - traits/ElnPublicTrait.php
39
41
  - traits/RecommendTrait.php
40
42
  - service/ElnApiImport.php
41
43
  - service/ElnApiUpdate.php
@@ -53,7 +55,7 @@ info:
53
55
  - sql/recommend.sql
54
56
  x-provider-audit:
55
57
  currentCommit: 3f39d47b7ad43bed618b029a7d9cc51fab852eb6
56
- previousReleaseEvidenceCommit: acb0e12f2d62a8959ab9e9bddf38e34a67c19b48
58
+ previousReleaseEvidenceCommit: 3f39d47b7ad43bed618b029a7d9cc51fab852eb6
57
59
  lastProviderVerifiedCommit: 3f39d47b7ad43bed618b029a7d9cc51fab852eb6
58
60
  contractStatus: current-provider-aligned
59
61
  # Summary of changes adopted by current Supported Routes since the last
@@ -62,36 +64,8 @@ info:
62
64
  # updates against that fixed release baseline; use [] if no relevant changes.
63
65
  # Entries are not per-change verification results or a cumulative history.
64
66
  incorporatedChanges:
65
- - {operationId: readApplicationBootstrap, change: array-valued-query-token-rejected-as-missing-authentication}
66
- - {operationId: updateRecordData, change: collaboration-source-restricted-to-same-notebook-record-web-peer}
67
- - {operationId: readRecord, change: encrypted-modules-and-unresolved-user-fields-modeled}
68
- - {operationId: listRecordComments, change: unresolved-author-descriptors-modeled}
69
- - {operationId: listRecordRelations, change: unresolved-comment-author-descriptors-modeled}
70
- - {operationId: updateRecordData, change: staged-files-folder-append-wired-into-request-and-base64-excluded}
71
- - {operationId: importRecordDataset, change: unreachable-base64-file-input-excluded}
72
- - {operationId: searchRecordData, change: fixed-result-field-aliases-reserved-and-extraction-path-constrained}
73
- - {operationId: saveNotebookMetadata, change: decoded-list-display-requests-reject-null-uid-and-invalid-path}
74
- - {operationId: updateRecordData, change: quote-extraction-path-constrained-and-collaboration-code-0-documented}
75
- - {operationId: listNotebooks, change: stored-types-return-non-null-decoded-json}
76
- - {operationId: extractLiteratureMetadata, change: nested-errors-and-opaque-array-results-modeled}
77
- - {operationId: listCloudDriveFiles, change: unreachable-null-timestamp-success-removed}
78
- - {operationId: downloadRecordAttachment, change: zero-start-open-range-4097-byte-cap-documented}
79
- - {operationId: downloadRecordCommentAttachment, change: zero-start-open-range-4097-byte-cap-documented}
80
- - {operationId: downloadLiteraturePdf, change: zero-start-open-range-4097-byte-cap-documented}
81
- - {operationId: downloadCloudDriveFile, change: zero-start-open-range-4097-byte-cap-documented}
82
- - {operationId: listCurrentUserElnGroups, change: dangling-group-id-null-and-first-group-error-modeled}
83
- - {operationId: downloadRecordCommentAttachment, change: zero-byte-attachment-download-supported}
84
- - {operationId: listNotebookRecords, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
85
- - {operationId: exportRecords, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
86
- - {operationId: searchRecordData, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
87
- - {operationId: listDeletedRecordPage, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
88
- - {operationId: copyRecord, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
89
- - {operationId: addRecordRelation, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
90
- - {operationId: deleteRecordRelation, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
91
- - {operationId: saveRecordComment, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
92
- - {operationId: deleteRecordComment, change: local-data-server-success-code-zero-internal-forwarding-code-excluded}
93
- - {operationId: downloadRecordAttachment, change: remote-data-server-download-excluded-pending-proxy-verification}
94
- - {operationId: downloadRecordCommentAttachment, change: remote-data-server-download-excluded-pending-proxy-verification}
67
+ - {operationId: readRecord, change: public-only-body-access-and-source-record-identity-documented}
68
+ - {operationId: listPublicNotebookRecords, change: source-record-identifiers-distinguished-from-public-association-id}
95
69
  x-consumer-evidence:
96
70
  - repository: /home/tnzhu/projects/matelab-mcp
97
71
  commit: 94a129b2df0ef0fbcf179c10550fb7c9a5dd2e6f
@@ -2054,6 +2028,17 @@ paths:
2054
2028
  operationId: listPublicNotebookRecords
2055
2029
  tags: [Records]
2056
2030
  summary: List records in a visible public notebook
2031
+ description: |
2032
+ Authentication is required even for a globally visible public directory.
2033
+ `eln` is the public directory's name. Visibility comes from a global
2034
+ directory (`eln_public.userid=0`) or the caller's directory membership;
2035
+ owning or sharing the source notebook is not required.
2036
+ To read an item's current body, call `readRecord` with query
2037
+ `eln=items[n].eln_id&id=items[n].item_id&version=0`. The directory's own
2038
+ id and each returned association `id` are different identities and must
2039
+ not be substituted. `uid` is nullable association metadata, not a body
2040
+ selector. An association can survive a missing source notebook or record;
2041
+ listing it does not guarantee that its body can still be read.
2057
2042
  security: [{bearerAuth: []}]
2058
2043
  requestBody:
2059
2044
  required: true
@@ -2092,6 +2077,8 @@ paths:
2092
2077
  - {id: 52, item_id: 9002, eln_id: 12, uid: null, title: null, comm: null, locked: false, eln_name: null, userid: null, username: null, email: null, owner: false}
2093
2078
  error:
2094
2079
  value: {code: 2, msg: Public notebook not found, errcode: 2, errmsg: Public notebook not found}
2080
+ authenticationError:
2081
+ value: {code: 1, msg: Authentication required, errcode: 1, errmsg: Authentication required}
2095
2082
  /eln_items/items:
2096
2083
  get:
2097
2084
  operationId: listNotebookRecordPage
@@ -2676,19 +2663,37 @@ paths:
2676
2663
  operation uses query parameters. Reading records writes an audit-log entry;
2677
2664
  that incidental access logging does not turn the resource read into a
2678
2665
  mutation operation.
2666
+ Public-record bodies use this same operation and `ItemViewResponse`.
2667
+ After `listPublicNotebookRecords`, pass that item's `eln_id` as `eln` and
2668
+ `item_id` as `id`; keep them paired and use `version=0` for current content.
2669
+ Do not substitute the public directory id, the public association's `id`,
2670
+ or its nullable `uid`.
2671
+ Authentication is still required. For a caller with no source-notebook
2672
+ owner/share grant, an exact `(eln_id, item_id)` association in a global
2673
+ public directory or one they belong to grants record-level read access.
2674
+ This does not grant ownership or access to other records in that notebook.
2675
+ Global public access is read-only; a member directory can separately
2676
+ grant editing through the association's `editable` setting.
2677
+ `modules` contains the canonical body or the existing encrypted descriptor;
2678
+ this endpoint does not decrypt it. The required `uid` field can be null
2679
+ for historical content and is not needed to construct the body request.
2680
+ Missing/invalid authentication returns business code 1; denied access or
2681
+ an invalid current-record identity returns code 2, both over HTTP 200.
2682
+ Historical reads must use a version from this record's own `modify_log`;
2683
+ the Provider does not enforce historical-version ownership (PVD-005).
2679
2684
  security:
2680
2685
  - bearerAuth: []
2681
2686
  parameters:
2682
2687
  - name: eln
2683
2688
  in: query
2684
2689
  required: true
2685
- description: Notebook database identifier.
2690
+ description: Source notebook database identifier; use PublicRecordItem.eln_id for a public record, not the public directory id.
2686
2691
  schema: {type: integer, minimum: 1}
2687
2692
  example: 12
2688
2693
  - name: id
2689
2694
  in: query
2690
2695
  required: true
2691
- description: Record database identifier.
2696
+ description: Source record database identifier; use PublicRecordItem.item_id for a public record, not its association id or UID.
2692
2697
  schema: {type: integer, minimum: 1}
2693
2698
  example: 9001
2694
2699
  - name: version
@@ -2766,6 +2771,38 @@ paths:
2766
2771
  template_show: ""
2767
2772
  template_text: Calibration Template
2768
2773
  template_intro: ""
2774
+ public:
2775
+ summary: Current body for a public-only reader without source-notebook sharing
2776
+ value:
2777
+ code: 0
2778
+ msg: ""
2779
+ errcode: 0
2780
+ errmsg: ""
2781
+ title: Calibration Run
2782
+ keywords: [calibration]
2783
+ modules:
2784
+ - {type: richtext, name: Notes, uid: module-example, data: Sanitized content}
2785
+ template_id: 8
2786
+ datetime_modify: 1767946200000
2787
+ username: Example User
2788
+ modify_log: []
2789
+ uid: REC-EXAMPLE-001
2790
+ current_version: 0
2791
+ item_id: 9001
2792
+ datetime_locked: 0
2793
+ locked: false
2794
+ signs: []
2795
+ signed: false
2796
+ owner: false
2797
+ eln_text: Example Notebook
2798
+ eln_server: localhost
2799
+ eln_id: 12
2800
+ editable: false
2801
+ keyword_eln: [calibration]
2802
+ pdf_enable: true
2803
+ template_show: ""
2804
+ template_text: Calibration Template
2805
+ template_intro: ""
2769
2806
  nullable:
2770
2807
  summary: Historical record with nullable UID, user, template, and keywords
2771
2808
  value:
@@ -2902,6 +2939,11 @@ paths:
2902
2939
  msg: No operation permission
2903
2940
  errcode: 2
2904
2941
  errmsg: No operation permission
2942
+ authenticationError:
2943
+ value: {code: 1, msg: Authentication required, errcode: 1, errmsg: Authentication required}
2944
+ identityError:
2945
+ summary: Source notebook and record identifiers do not identify the same current record
2946
+ value: {code: 2, msg: Illegal operation, errcode: 2, errmsg: Illegal operation}
2905
2947
  /eln_url/eln:
2906
2948
  get:
2907
2949
  operationId: downloadRecordAttachment
@@ -5677,7 +5719,10 @@ components:
5677
5719
  type: object
5678
5720
  required: [eln]
5679
5721
  properties:
5680
- eln: {type: string, minLength: 1}
5722
+ eln:
5723
+ type: string
5724
+ minLength: 1
5725
+ description: Public directory name, not the source notebook name or numeric id.
5681
5726
  additionalProperties: false
5682
5727
  CreateRecordRequest:
5683
5728
  type: object
@@ -6214,10 +6259,21 @@ components:
6214
6259
  type: object
6215
6260
  required: [id, item_id, eln_id, uid, title, comm, locked, eln_name, userid, username, email, owner]
6216
6261
  properties:
6217
- id: {type: integer, minimum: 1}
6218
- item_id: {type: integer, minimum: 1}
6219
- eln_id: {type: integer, minimum: 1}
6220
- uid: {type: [string, "null"]}
6262
+ id:
6263
+ type: integer
6264
+ minimum: 1
6265
+ description: Public association row identifier; not the record id accepted by readRecord.
6266
+ item_id:
6267
+ type: integer
6268
+ minimum: 1
6269
+ description: Source record identifier; pass as readRecord query id together with this row's eln_id.
6270
+ eln_id:
6271
+ type: integer
6272
+ minimum: 1
6273
+ description: Source notebook identifier; pass as readRecord query eln, not the public directory id.
6274
+ uid:
6275
+ type: [string, "null"]
6276
+ description: Nullable UID copied into the association; not required for the numeric readRecord selector.
6221
6277
  title: {type: [string, "null"]}
6222
6278
  comm: {type: [string, "null"]}
6223
6279
  locked: {type: boolean}
@@ -0,0 +1,100 @@
1
+ # Agent Maintenance Workflows
2
+
3
+ 本文件只在对应分支触发时加载。机器值始终从仓库读取;这里记录顺序、授权边界和完成标准。
4
+
5
+ ## Contract adoption
6
+
7
+ 1. 读取 Contract lock 和远端 release refs。只选择新的 annotated tag;移动分支和改写后的旧
8
+ snapshot 不能成为 SDK pin。记录 tag object、peeled commit、OpenAPI path 与 SHA-256。完成标准:四者固定且
9
+ 互相一致。
10
+ 2. 比较当前 snapshot 与 release commit。逐项核对 operation request、response、security、examples、成功码、
11
+ Provider evidence 及 PVD/PCG。完成标准:每个 schema/operation 差异都分类为 generated-only、adapter、public
12
+ interface、test、coverage 或 docs 影响。
13
+ 3. request/response 均由生成 wire model 校验,adapter 只映射 public Python 名称与 wire 字段。required nullable
14
+ 使用无默认值的 `T | None`;request 拒绝未知字段,response 接受新增字段。若专用 schema、顶层 request 或
15
+ Provider evidence 相互矛盾,保留当前安全边界并报告缺口。
16
+ 4. 从 release commit 复制 OpenAPI snapshot;同一变更更新 lock 的 tag、commit、snapshot path 和 SHA-256,运行
17
+ 生成脚本并审查完整 generated diff。`_generated` 只由生成脚本修改;projection 只补偿生成器表达能力并保留
18
+ inherited required、`if/then`、`oneOf`、`anyOf` 和 `not`。完成标准:snapshot hash 与 lock 相等,生成差异
19
+ 全部可由 OpenAPI 差异解释,`--check` 确定、非写入且能发现 stale output。
20
+ 5. 同步 runtime、测试、operation coverage、README、`docs/api.md`、`docs/development.md`、`pyproject.toml` 与 `uv.lock`
21
+ 中受影响的当前态。
22
+ 完成标准:每个 Contract 差异都有实现或明确 containment,当前文档与采用后的 Contract 一致。
23
+ 6. 执行 [delivery gate](#delivery-gate)。
24
+
25
+ ## Configuration and dependencies
26
+
27
+ 配置值以 `pyproject.toml` 为准,`uv.lock` 固定本仓库的解析环境,不反向定义发布依赖范围。
28
+
29
+ - `[project]` 字段依次为 `name`、`version`、`description`、`requires-python`、`keywords`、`authors`、
30
+ `dependencies`,其他字段放在其后。
31
+ - `[tool.basedpyright]` 字段依次为 `pythonVersion`、`typeCheckingMode`、`include`、`exclude`、
32
+ `reportUnannotatedClassAttribute`、`reportIncompatibleUnannotatedOverride`,其他设置放在其后。沿用 SDK 的目标
33
+ Python 版本与检查路径,不照搬其他项目的值。
34
+ - runtime、build 和 dev 依赖仅声明已验证的 `>=` 下限;`nodejs-wheel-binaries` 保留系统所需的精确版本。
35
+ 更新声明时同步 lock 和安装后消费检查使用的 CI requirement。
36
+ - 构建后端依赖和 wheel package 显式配置;metadata 与制品检查从这些声明推导预期值。
37
+
38
+ 完成标准:配置可解析、声明与 lock 一致、受影响 CI 使用同一约束;字段重排不改变配置含义。
39
+
40
+ ## Delivery gate
41
+
42
+ 按本次变更选择验证范围:
43
+
44
+ - 纯文档修改检查相关事实、本地路径和 Markdown 引用;示例或接口说明变化要对照当前 public interface。
45
+ - 字段重排或显式写出既有默认值,检查语法与有效配置一致性。工具配置的有效设置变化运行对应工具。
46
+ - SDK 代码、测试行为、Contract、依赖范围或影响制品的构建元数据变化,先跑聚焦测试,再完成下列完整门槛。
47
+
48
+ ### SDK test scope
49
+
50
+ SDK 测试覆盖 public interface 到 wire adapter 的映射、认证与 Session、错误与重试、stream/上传生命周期及
51
+ 分发制品;Provider 的逐路由原始 HTTP conformance 由 `matelab-spec` 负责。
52
+
53
+ 新增或修改 operation 覆盖 method/path/encoding、认证、成功映射及适用的空结果、
54
+ required nullable 和 additive response fields;operation coverage 与 pinned OpenAPI exact match,implemented
55
+ operation 同时具备 public interface、wire adapter 和测试。删除或收紧 public interface 时同步移除过时测试,
56
+ 不保留无承诺的墓碑 alias。生成测试覆盖 metadata/checksum、schema、required/nullable、extra policy、确定性和
57
+ stale detection。
58
+
59
+ 优先使用 pinned sanitized examples 或小型受控 fixture 验证稳定行为。operation 数量从 pinned Contract 推导,
60
+ 不固定当前数量;当前服务地址和依赖版本值不作为回归断言,除非它们本身就是明确的稳定契约。
61
+ 配置值变化只验证语法、约束及相关行为,不另加冻结新值或重复实现逻辑的测试。
62
+
63
+ Ruff/Basedpyright 诊断通过修复代码或精确 ignore 解决,不缩小检查范围;Basedpyright 目标为 0 errors / 0 warnings。
64
+
65
+ ### Full gate
66
+
67
+ 完整命令见 [开发文档](development.md#development)。离线验证不配置 Provider 连接变量;实时 smoke 按
68
+ [Provider validation](#provider-validation) 执行。
69
+
70
+ 检查因权限失败或无进展时,先查看输出和自己启动的进程,区分普通失败与文件、socket、网络或子进程限制。
71
+ 有沙箱阻塞证据后停止自己启动的停滞测试,通过工具审批机制申请最小范围重试;保留配置,不改权限、凭证或测试
72
+ 行为来绕过限制。超时本身不是沙箱拒绝的证据;无法升级或被拒绝时报告阻塞。
73
+
74
+ 完成标准:必需检查退出为零,`git diff --check` 无错误;skip 报告测试名称和原因,deselected 说明筛选范围。
75
+
76
+ ## Provider validation
77
+
78
+ 1. 实时验证仅在任务需要且会话授权覆盖目标及副作用时执行;连接设置和 smoke 命令见
79
+ [开发文档](development.md#opt-in-provider-consumer-smoke)。
80
+ 2. 执行前确认目标是隔离服务、`.env.test` 处于 Git ignore、命令显式加载该文件,并列出 authentication、refresh、
81
+ mutation 或带写痕迹读取的副作用。
82
+ 3. mutation 场景在写前记录 fixture,在写后回读,并尽力清理。完成标准:目标、Provider commit、命令、通过数、
83
+ skip/failure 和清理结果均可追溯;凭证及敏感 payload 未进入输出或提交。
84
+
85
+ ## Release
86
+
87
+ 普通 commit/push 只处理已授权的 diff,不自动改版本、建 tag 或发布。发布准备完成但缺少外部操作授权时,
88
+ 先交付可审查结果,再请求执行授权。以下步骤适用于实际发布:
89
+
90
+ 1. 按 [版本规则](development.md#versioning) 选择 SDK 版本,读取 `[project].version`,确认待发布版本未发布
91
+ 且 Contract pin 完整。公开接口删除、重命名、类型收紧或不兼容行为变化按 breaking change 处理。
92
+ 完成标准:版本、当前文档和 tag 名 `v{version}` 一致。
93
+ 2. 提交前同步受影响的当前文档,完成 [delivery gate](#delivery-gate)。构建元数据或发布流程变化时,核对
94
+ metadata 版本与固定的 PyPI 发布 Action 是否兼容;需要本地制品证据时使用
95
+ [手工构建命令](development.md#reproducible-release-build)。创建已审查、已授权的 release commit。
96
+ 3. 创建指向 release commit 的 annotated `v{version}` tag。先推送 `origin` 的 main/tag,再推送 GitHub mirror 的
97
+ main/tag;只有与项目版本完全匹配的 tag 触发 Trusted Publishing workflow,第三方 Action 固定 immutable
98
+ commit SHA。
99
+ 4. 跟踪 [发布 CI](../.github/workflows/release.yml) 的测试、可复现构建、制品审计、安装后消费和 PyPI publish。
100
+ 完成标准:两个远端 main/tag 对应 release commit,CI 全部通过,PyPI 对应版本可读取。