matelab-python-sdk 0.1.0a15__tar.gz → 0.1.0a16__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 (78) hide show
  1. matelab_python_sdk-0.1.0a16/AGENTS.md +94 -0
  2. matelab_python_sdk-0.1.0a16/CHANGELOG.md +317 -0
  3. matelab_python_sdk-0.1.0a16/CONTEXT.md +91 -0
  4. matelab_python_sdk-0.1.0a16/PKG-INFO +897 -0
  5. matelab_python_sdk-0.1.0a16/README.md +869 -0
  6. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/docs/operation-coverage.yaml +12 -8
  7. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/pyproject.toml +3 -1
  8. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/scripts/generate_models.py +1 -2
  9. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/__init__.py +33 -132
  10. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/_generated/models.py +153 -595
  11. matelab_python_sdk-0.1.0a16/src/matelab/_hashes.py +8 -0
  12. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/_transport.py +21 -18
  13. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/_wire_validation.py +11 -8
  14. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/client.py +7 -13
  15. matelab_python_sdk-0.1.0a16/src/matelab/domains/_attachment_content.py +45 -0
  16. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/domains/cloud_drive.py +21 -76
  17. matelab_python_sdk-0.1.0a16/src/matelab/domains/groups.py +41 -0
  18. matelab_python_sdk-0.1.0a16/src/matelab/domains/literature.py +722 -0
  19. matelab_python_sdk-0.1.0a16/src/matelab/domains/notebooks.py +335 -0
  20. matelab_python_sdk-0.1.0a16/src/matelab/domains/records.py +2150 -0
  21. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/domains/templates.py +113 -210
  22. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/domains/uploads.py +36 -37
  23. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/domains/users.py +3 -5
  24. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_async_attachment_upload.py +145 -104
  25. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_cloud_drive.py +10 -37
  26. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_comments_and_downloads.py +10 -15
  27. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_consumer_smoke.py +7 -3
  28. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_errors.py +1 -6
  29. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_extended_records.py +66 -81
  30. matelab_python_sdk-0.1.0a16/tests/test_groups.py +61 -0
  31. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_notebook_lifecycle.py +74 -62
  32. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_notebooks.py +33 -5
  33. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_operation_coverage.py +6 -12
  34. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_record_lifecycle.py +75 -48
  35. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_record_mutations.py +286 -254
  36. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_records.py +32 -49
  37. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_streaming.py +20 -14
  38. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_template_lifecycle.py +31 -115
  39. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_templates.py +23 -28
  40. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_transport.py +65 -25
  41. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_uploads_and_literature.py +371 -118
  42. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_users.py +3 -9
  43. matelab_python_sdk-0.1.0a16/tests/typing/consumer.py +125 -0
  44. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/uv.lock +1 -1
  45. matelab_python_sdk-0.1.0a15/AGENTS.md +0 -127
  46. matelab_python_sdk-0.1.0a15/CHANGELOG.md +0 -145
  47. matelab_python_sdk-0.1.0a15/PKG-INFO +0 -769
  48. matelab_python_sdk-0.1.0a15/README.md +0 -741
  49. matelab_python_sdk-0.1.0a15/src/matelab/domains/_attachment_content.py +0 -71
  50. matelab_python_sdk-0.1.0a15/src/matelab/domains/groups.py +0 -78
  51. matelab_python_sdk-0.1.0a15/src/matelab/domains/literature.py +0 -832
  52. matelab_python_sdk-0.1.0a15/src/matelab/domains/notebooks.py +0 -379
  53. matelab_python_sdk-0.1.0a15/src/matelab/domains/records.py +0 -2690
  54. matelab_python_sdk-0.1.0a15/src/matelab/domains/template_documents.py +0 -527
  55. matelab_python_sdk-0.1.0a15/tests/test_groups.py +0 -101
  56. matelab_python_sdk-0.1.0a15/tests/test_template_documents.py +0 -393
  57. matelab_python_sdk-0.1.0a15/tests/typing/consumer.py +0 -119
  58. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/.env.example +0 -0
  59. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/.github/workflows/release.yml +0 -0
  60. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/.gitignore +0 -0
  61. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/LICENSE +0 -0
  62. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/NOTICE +0 -0
  63. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/contracts/matelab-integration-v1.lock.json +0 -0
  64. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/contracts/matelab-integration-v1.openapi.yaml +0 -0
  65. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/scripts/check_installed_package.py +0 -0
  66. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/scripts/check_release.py +0 -0
  67. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/_generated/__init__.py +0 -0
  68. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/domains/__init__.py +0 -0
  69. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/errors.py +0 -0
  70. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/py.typed +0 -0
  71. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/session.py +0 -0
  72. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/src/matelab/streaming.py +0 -0
  73. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/conftest.py +0 -0
  74. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/provider/test_provider_smoke.py +0 -0
  75. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_client.py +0 -0
  76. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_generation.py +0 -0
  77. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/test_release.py +0 -0
  78. {matelab_python_sdk-0.1.0a15 → matelab_python_sdk-0.1.0a16}/tests/typing/pyproject.toml +0 -0
@@ -0,0 +1,94 @@
1
+ # AGENTS.md
2
+
3
+ 本文档只保留维护 `matelab-python-sdk` 必须长期遵守的约束,不记录当前功能清单、迁移历史、阶段性状态或
4
+ 一次性验收数字。
5
+
6
+ ## 文档与权威边界
7
+
8
+ - `README.md`:当前 public interface、集成语义、示例及可执行的开发/发布流程;不承担版本迁移历史。
9
+ - `CONTEXT.md`:公共领域术语及易混概念的统一词汇;不记录实现或协议细节。
10
+ - `CHANGELOG.md`:按 SDK 版本记录变化和迁移影响;不作为当前接口说明。
11
+ - `docs/operation-coverage.yaml`:operation 状态、公开入口、稳定性和已知问题的机器权威;不写叙述性用法。
12
+ - `pyproject.toml`:SDK 版本、依赖范围、构建和工具配置的机器权威;`uv.lock` 只锁定本仓库环境。
13
+ - `contracts/matelab-integration-v1.lock.json` 及其 snapshot:Contract pin 和 wire schema 的唯一机器权威。
14
+ - `src/matelab/__init__.py::__all__`:公开导入边界;测试是行为证据,不替代上述文档。
15
+ - 本文件只规定维护原则和质量门槛。机器权威变化时,同一变更必须同步受影响的叙述文档,避免复制无归属的
16
+ 版本号、配置值或 operation 清单。
17
+
18
+ ## 工作范围与 public interface
19
+
20
+ - 本项目是 Matelab Integration Contract 的通用异步 Python Consumer,负责隐藏 HTTP 编码、认证刷新、业务
21
+ 错误、wire model 和 Provider 兼容细节。
22
+ - `/home/tnzhu/projects/matelab-spec` 负责 Wire Contract、兼容策略及 Provider 问题;`matelab-server` 是 Provider
23
+ 实现,`matelab-mcp` 只是 Consumer 证据,均不能反向定义 SDK interface。
24
+ - 修改前执行 `git status`,现有改动视为用户工作。默认只修改本仓库;未经明确授权,不修改相邻仓库、不迁移
25
+ MCP、不 commit/push/tag/publish,也不对真实 Provider 执行 mutation。
26
+ - `AsyncMatelab` 是稳定入口,能力按领域组织。public interface 只表达用户意图,不泄漏 controller、path、
27
+ opcode、wire 字段、generated model 或认证刷新细节。
28
+ - 公共类型必须区分 userid、database id、UID、relation id、staging id 等身份空间。Provider 未返回的 identity、
29
+ affected rows、排序、分页、原子性、CAS、幂等性或持久化结果不得推测;legacy 限制应诚实表达。
30
+ - MCP typed refs、capabilities、fingerprints、FastMCP/Redis context 和 Agent 展示模型不得进入 SDK。仅在存在真实
31
+ 第二种实现时增加 seam,不为测试预设抽象。
32
+ - 支持 Python 3.11+;源码不使用 `from __future__ import annotations`,前向引用优先通过定义顺序解决。
33
+
34
+ ## Contract、生成与 transport
35
+
36
+ - 每个 operation 必须核对 pinned OpenAPI 的 request、response、security、examples 和成功码,并查看相关
37
+ PVD/PCG。Contract 不足时可只读参考 Provider/Consumer;仍无法安全表达就报告缺口,不猜测或静默适配漂移。
38
+ - Contract Adoption 只能来自不可变 release tag,并在同一变更中更新唯一 lock 的 tag、commit、snapshot path
39
+ 和 SHA-256,重新生成并复核差异;不得跟踪移动分支或改写正式 snapshot。
40
+ - request/response 均由生成 wire model 校验,adapter 只负责 public Python 名称与 wire 字段映射。required
41
+ nullable 使用无默认值的 `T | None`;request 拒绝未知字段,response 兼容新增字段。
42
+ - 不手工编辑 `_generated`。generation projection 只能补偿生成器表达能力,并保留 inherited required 及
43
+ `if/then`、`oneOf`、`anyOf`、`not`;生成变化必须可追溯,`--check` 必须确定、非写入且能发现 stale output。
44
+ - `base_url` 是 Provider API 根;query、JSON、form、multipart、streaming、bearer 和成功码均按 operation 配置,
45
+ 不能用全局默认掩盖差异。
46
+ - `Token`、`Identity` 和 `Session` 是冻结、拒绝额外字段的 public model,组成规范化 Session JSON。每个
47
+ `AsyncMatelab` 最多持有一个最新 Session;SDK 不绑定裸 token,持久化、加密、撤销、身份归属和跨进程锁
48
+ 属于集成方。不同逻辑 Session 不共享 client,但可共享注入的 `httpx.AsyncClient`。
49
+ - token 在 repr 中隐藏,显式 Session JSON 保留凭证;凭证、SSO 参数、附件内容及敏感 payload 不得进入日志、
50
+ 异常或提交内容。
51
+ - access 到期前刷新;并发刷新使用单锁;安全请求遇到 `code=5` 最多刷新重试一次。mutation 默认不重试,
52
+ multipart/stream 仅在可重放时重试,download stream 必须可显式关闭。
53
+ - transport、Provider business/authentication、Contract/schema 和 usage 错误必须稳定区分;公开错误直接提供
54
+ 集成级 `category` 和保守的 `retryable`,下游不应重新解释 Provider 数字 code。
55
+
56
+ ## 测试与质量门槛
57
+
58
+ - 测试以 public interface 为主。新增或修改 operation 至少覆盖 method/path/encoding、认证、成功映射及适用的
59
+ 空结果、required nullable、additive response fields;通用 transport/auth/error 语义在集中测试中覆盖。
60
+ - 删除或收紧 public interface 时同步删除过时测试;无明确兼容承诺时不保留墓碑 alias 或测试。
61
+ - operation coverage 必须与 pinned OpenAPI exact match;implemented operation 必须同时具备 public interface、
62
+ wire adapter 和测试。生成测试必须覆盖 metadata/checksum、schema、required/nullable、extra policy、确定性和
63
+ stale detection。
64
+ - Provider smoke 默认 skip 且不自动读取 `.env`;本地 `.env.test` 必须保持 Git ignore。只能通过显式
65
+ `uv run --env-file .env.test` 对已确认的隔离目标 opt in;生产目标、mutation 或带写痕迹的读取必须获得本轮
66
+ 明确授权,并回读、尽力清理。
67
+ - Ruff/Basedpyright 的具体配置以 `pyproject.toml` 为准;不得通过排除测试、全局关规则或缩小检查范围消除诊断。
68
+ Basedpyright 目标为 0 errors / 0 warnings,必要 ignore 必须精确并说明原因。
69
+ - 先跑相关测试,交付前跑完整门槛;skip 必须说明原因,不能报告为通过:
70
+
71
+ ```bash
72
+ uv sync --frozen
73
+ uv run python scripts/generate_models.py --check
74
+ uv run ruff check .
75
+ uv run ruff format --check .
76
+ uv run basedpyright
77
+ uv run pytest
78
+ uv build --no-build-isolation
79
+ ```
80
+
81
+ 若沙箱造成缓存、Node wheel 或解释器发现失败,应在沙箱外复核同一命令,不得改配置或使用未锁定工具绕过。
82
+
83
+ ## 依赖、版本与发布
84
+
85
+ - runtime dependency 必须声明经支持 Python 版本验证的下限,并排除未经验证的下一个 major;构建后端范围和
86
+ wheel package 必须显式配置,不能依赖自动发现。
87
+ - `[project].version` 是唯一 SDK 版本源;SDK 使用 SemVer,Contract Line 不是 SDK 版本。公开接口删除、重命名、
88
+ 类型收紧或行为变化均按 breaking change 处理。
89
+ - 发行采用 Apache-2.0;`LICENSE`、`NOTICE`、PEP 639 metadata 和制品内容必须一致,wheel 包含 `py.typed` 且
90
+ 不公开 `_generated`。
91
+ - Gitee `origin` 是内部主仓库,私有 GitHub mirror 只承载 PyPI Trusted Publishing。release workflow 仅由与
92
+ 项目版本完全匹配的 `v*` tag 触发,第三方 Action 固定不可变 commit SHA。
93
+ - release 必须来自干净 revision、锁定环境和固定 `SOURCE_DATE_EPOCH`,记录 Contract 与制品 checksum;候选
94
+ 制品须审计内容/METADATA、验证安装后的公开导入和类型消费、覆盖 Python 版本边界并确认可复现构建。
@@ -0,0 +1,317 @@
1
+ # Changelog
2
+
3
+ This file records release-to-release changes and migration impact. It is not the authority for the current interface;
4
+ see [README.md](README.md) for current behavior and [AGENTS.md](AGENTS.md) for maintenance policy.
5
+
6
+ ## 0.1.0a16 - 2026-08-14
7
+
8
+ - Breaking: `UserSummary.display_name` is renamed to `name`; the SDK exposes the Provider's raw nullable real name
9
+ without implying presentation formatting. `NotebookShare.recipient_display_name` similarly becomes
10
+ `recipient_name`.
11
+ - Breaking: `templates.list()` now returns the `TemplateSummary` tuple directly and replaces `source` with the
12
+ `owned/shared/group/public` string-literal `scope`; `TemplateCollection`, `TemplateSource`, and
13
+ `TemplateLibraryRelationKind` are removed. Provider marketplace acquisitions and defaults share public scope, with
14
+ the optional user-library relation distinguishing an acquisition. The administrator-only `pending[]` queue is not
15
+ emitted as a visible template; owned rows expose their actual `pub` submission state as `market_review_pending`.
16
+ `TemplateLibraryEntryRef.kind` now identifies only the real user-library versus group-library relation identity
17
+ space, and one `remove_from_library()` operation replaces `unshare()`, `remove_market_acquisition()`, and
18
+ `remove_from_group()`. Template metadata `update()` requires all replaceable fields and returns `None`; generic
19
+ revision fields are renamed to `content_version`, `published_content_version`, and `market_review_reason`.
20
+ `TemplateMarketPage` retains its items, Provider-reported total and SDK-derived `has_more` without echoing request
21
+ pagination. Owned transfer provenance and pending-review publisher attribution are no longer mislabeled as
22
+ a uniform owner field; `owner` remains populated only where shared/group rows actually return the current owner.
23
+ Template summaries and marketplace entries consistently name stored usage content `usage_html`.
24
+ `update_usage()` replaces `update_intro()` and generates the Provider-only upload correlation value internally;
25
+ usage attachments remain unsupported while PVD-026 is open.
26
+ - Breaking: removes the frontend-derived `TemplateDocument`, semantic module/field/change models, and
27
+ `templates.read_document()`, `save_document()`, and `patch_content()`. Template content now has one public model,
28
+ `TemplateModule`, read with `templates.read()` and written as a full replacement with `templates.save_content()`.
29
+ Consumers that provide an editor should own its layout defaults and patch model; the Provider exposes neither an
30
+ atomic template patch nor compare-and-swap semantics.
31
+ - Centralizes outbound request serialization in the transport. Domain adapters now pass validated Pydantic wire models
32
+ directly; the transport emits wire aliases and explicitly supplied fields, reveals `SecretStr` values only in the
33
+ outbound payload, and separates multipart file fields without call-site `model_dump()` projections.
34
+ - Breaking: replaces notebook sharing's raw permission masks and seven boolean update arguments with
35
+ `NotebookPermissions`, shared with record-page capability results. `NotebookShareRef` now contains only
36
+ notebook/share-row identity; recipient metadata belongs to `NotebookShare`, while caller-relative
37
+ `belongs_to_caller` and redundant `caller_is_owner` are removed.
38
+ `NotebookShares` also drops its duplicate notebook field because each share ref already carries that context.
39
+ The Provider signing permission remains policy-only and does not introduce an SDK signing operation.
40
+ - Breaking: removes `NotebookListField`, notebook-list display fields and type tags from `NotebookSummary`, and UI
41
+ display/type-tag inputs from notebook creation and update. Provider `types`/`display`/`requests` remain wire-only
42
+ compatibility details; metadata updates pre-read the current owned notebook and preserve that configuration on a
43
+ best-effort basis because no atomic read-modify-write or compare-and-swap operation exists.
44
+ - Breaking: removes `PublicNotebookSummary`. Owned, shared, and public catalog entries now all use `NotebookSummary`;
45
+ public owner/group metadata that the Contract does not return is represented as `None` rather than an empty value
46
+ inferred by the SDK.
47
+ - Breaking: removes template render metadata, cloud-drive display-formatted dates, literature citation HTML/search
48
+ highlighting, and the Provider's literature form-definition models from the public interface. Removes
49
+ `literature.creation_schema()` without exposing its frontend template or deployment capability flag; Consumers call
50
+ `literature.extract_metadata()` directly and handle an unavailable optional backend as a Provider error. Metadata
51
+ extraction accepts either source and gives a supplied DOI precedence over a staged PDF.
52
+ - Breaking: `TemplateLibraryEntryRef` drops its duplicate template identity. `TemplateSummary` no longer projects
53
+ owner/group display names or the Provider's UI-oriented group `admin` flag.
54
+ - Breaking: removes `RecordSignature`, record lock/signature projections and `RecordVersionSummary`. `Record.versions`
55
+ now contains `RecordVersionRef` values directly; Provider version metadata and signature state remain wire-only.
56
+ - Breaking: removes `RecordPageContext` and `RecordPagePermissions`; `RecordPage` exposes the common
57
+ `NotebookPermissions` directly, without duplicate input notebook, request pagination, owner display name or template
58
+ UI context.
59
+ Provider finalization and additional-signature mutations remain deliberately outside the pinned Contract and SDK.
60
+ - Breaking: unifies personal and shared literature identities as `LiteratureLibraryRef` and `LiteratureItemRef`,
61
+ with `LiteratureLibraryRef.scope` derived from its identity rather than accepted as a second constructor value:
62
+ zero identifies the synthetic personal library and positive IDs identify shared libraries. Replaces raw literature
63
+ permission masks with `LiteratureLibraryPermissions`. `literature.libraries()` now returns usable summaries directly
64
+ and removes `LiteratureLibraries`, `PendingLiteratureShare`, and `PendingLiteratureShareComment`; dangling membership
65
+ rows and pending-share projections remain wire-only until a complete accept/reject Contract exists. Raw
66
+ source/backend extension maps remain wire-compatible but are no longer public; canonical-update loss detection stays
67
+ inside the update operation, covers top-level and nested source fields, and reports affected field paths only when
68
+ refusing a lossy update. Explicit loss opt-in skips the otherwise best-effort, non-atomic detail preflight. Comment
69
+ creation and update are now explicit `create_comment()` and `update_comment()` operations. `LiteratureCommentRef`
70
+ retains only the Provider comment-row ID. Creation pre-reads detail and rejects an existing caller-owned comment to
71
+ maintain the Integration Contract's one-caller-comment invariant despite the Provider's non-atomic PVD-035 gap;
72
+ update/delete avoid a duplicate read and rely on the mutation's ownership and permission checks. Invalid stored JSON
73
+ is represented by `LiteratureDetail.metadata=None` instead of a special metadata object with a wire-shaped validity
74
+ flag.
75
+ `LiteraturePage` shortens `library_name` to `name` and calls library classification labels `tags` rather than
76
+ overloading bibliographic `keywords`. `LiteratureLibrarySummary`, `LiteratureItemSummary`, and `LiteratureDetail`
77
+ use the same tag vocabulary; `literature.list(tags=...)` maps it to the legacy wire `keywords` filter.
78
+ Renames `LiteratureMetadata` to `LiteratureMetadataInput`, `LiteratureStoredMetadata` to
79
+ `StoredLiteratureMetadata`, `ExtractedLiteratureMetadata` to `PublicationMetadataCandidate`, and
80
+ `ExtractedLiteratureAuthor` to `PublicationAuthorCandidate`, distinguishing canonical write input, decoded stored
81
+ state, and unstored DOI/PDF evidence. The old public names are removed without aliases. `StoredLiteratureMetadata`
82
+ removes the duplicate legacy `authors` array and normalizes it into the canonical `author` text only when that
83
+ canonical field is absent; raw legacy fields remain available to internal update-loss detection.
84
+ `LiteratureItemSummary` and `LiteratureDetail` expose nullable `rating` instead of the Provider's zero-sentinel `star`,
85
+ represent a missing PDF as `None`, and require a non-null SHA-256 on each exposed `LiteraturePdf`; filename and size
86
+ remain optional. The falsely named list `publication_date` is removed, and optional list metadata uses `None` instead
87
+ of Provider empty-string sentinels.
88
+ - Breaking: record export and search now return tuples directly, and routing/forwarding flags are no longer public.
89
+ `ExportedRecord.modules` replaces the wire-shaped `data` field and distinguishes canonical stored modules from
90
+ template-shaped `RecordImportItem.data`. `records.search()` accepts its required field-to-path mapping as the primary
91
+ positional argument; `RecordSearchMatch.values` replaces `extracted` and the redundant `missing_extractions`, with
92
+ absent keys distinguishing missing Provider results from explicit JSON nulls.
93
+ Record lists/pages omit the Provider's full UI selection/filter payload, call their free-text filter `search`, and
94
+ use semantic permission names; record reads accept one `RecordLocator` or `RecordVersionRef` and expose the resolved
95
+ locator once as `Record.source`. Owner/editable UI flags, duplicated identity, template-rendering, PDF-capability,
96
+ data-server, and redundant selected-UID fields are removed. `Record.version` identifies historical content. Record
97
+ versions retain only their typed refs; Provider version/signature metadata stays wire-only.
98
+ `records.import_dataset()` returns the Provider-reported database-ID tuple directly and removes the one-field
99
+ `RecordImportResult`. The Provider-built notebook echo in paged record responses is not revalidated because server
100
+ code constructs it from the request. Record update does not expose the Provider's `password` field: the pinned read
101
+ Contract cannot represent encrypted record content, and the frontend's separate set/change/remove-password
102
+ lifecycle is not a safe generic SDK capability. `RecordImportItem.keywords`
103
+ replaces the Provider's singular semicolon-encoded `keyword` input. The Provider's misleading record `subtype`
104
+ terminology is now wire-only:
105
+ `RecordFolder`, `folder_id`, `folder_path`, and `folders` describe the notebook directory tree. Root-parent and
106
+ root-record zero sentinels become `None`, empty-folder SQL counts become zero, and `NotebookPermissions` uses
107
+ `can_manage_record_folders`. Record identities consistently use `record_id` for the Provider database row and
108
+ `record_uid` for its UID; the redundant `record_database_id` spelling is removed. Record copy now accepts an
109
+ optional caller-chosen `new_record_uid`, generates one locally when omitted, and returns a complete
110
+ `RecordLocator`; the partial one-field `RecordCopyResult` is removed. Deleted-record summaries and restore inputs
111
+ reuse `RecordRef`; the identical `DeletedRecordRef` type is removed without an alias.
112
+ - Breaking: replaces the eight mutation-family keyword arguments on `records.update()` with one required
113
+ `changes: Sequence[RecordChange]`. `RecordValueUpdate`, `RecordValueDeletion`, and `RecordModuleDeletion` complete
114
+ the typed intent union alongside the existing module, attachment, file-structure, and rich-text changes. The
115
+ category-only `RecordAttachmentChange` and `RecordFileStructureChange` aliases are removed; the SDK now keeps
116
+ Provider `modify`/`del`/`addModule`/`delModule`/`add` classification entirely inside the update implementation.
117
+ Removes `Record.content_sha256` and `records.update(expected_content_sha256=...)`: the value was only an SDK-side
118
+ read/prewrite comparison and could not provide Provider compare-and-swap semantics. Current-state reads now serve
119
+ only attachment/path safety rules; ordinary module creation and deletion use the Provider's canonical validation
120
+ without an additional SDK read. The update acknowledgement values are shortened to `"persisted"`, `"pending"`,
121
+ and `"unknown"`; the last value remains a conservative fallback for an unrecognized successful Provider message.
122
+ - Breaking: record relations now return a tuple directly and remove `RecordRelations`; the relation endpoint's legacy
123
+ comment duplicate and caller-relative `editable` value remain wire-only. `RecordCommentRef` now carries its typed
124
+ record source, update/delete accept that ref, and `RecordComment` no longer publishes duplicate source or
125
+ `owned_by_caller` UI state. Comment attachment refs no longer duplicate their parent comment; downloads accept the
126
+ parent ref explicitly. `RecordVersionRef` likewise carries a `RecordLocator` instead of three repeated primitive
127
+ identity fields. Historical reads now accept that version ref
128
+ directly instead of requiring the same locator a second time. Public record summaries drop the unused
129
+ caller-ownership flag, stale publication-lock state and owner email, and use the common `notebook_title` name.
130
+ `RecordRelationRef` now carries only its relation row and declared target IDs. The one-use `RelatedRecordIdentity`
131
+ wrapper and preview-oriented `RecordRelation` are removed; `relations()` returns refs directly, while
132
+ `delete_relation()` takes the source locator explicitly instead of duplicating it in every listed relation.
133
+ Deleted-record pages do not repeat request pagination or the input notebook and impose no SDK-only size range beyond
134
+ the Contract minimum. Relation writes no longer list relations solely to
135
+ inspect the caller-relative `editable` flag; Provider mutation authorization remains authoritative, while the reads
136
+ required for cross-server addition and target-ID-safe deletion remain. Record comment create/update use `body`;
137
+ update retains the PVD-004 ownership preflight, while deletion relies on the Provider's own ownership check and
138
+ avoids a duplicate list request. Comment bodies are not display-normalized before the Provider's documented trim.
139
+ - Breaking: unifies record attachment staging as `records.upload_attachment(notebook, ...) -> StagedAttachment`.
140
+ Uploading does not choose a target record; the handle retains its notebook selector, authenticated uploader, binding,
141
+ filename, and hash and is accepted by either one later import or update. `stage_attachment()`,
142
+ `StagedNotebookAttachment`, and `StagedRecordAttachment` are removed without aliases.
143
+ `upload_attachment()` no longer accepts caller-supplied staging metadata: the SDK generates the upload event,
144
+ calculates the SHA-256, omits the Provider's equivalent `name` and `last=1` defaults, and uses the validated response
145
+ as the completed staging result. Both attachment upload methods remove caller-supplied size, checksum, and multipart
146
+ content type because the Provider derives the metadata and both Contracts fix opaque binary attachment parts.
147
+ Comment uploads no longer expose `UploadBindingRef`; the SDK generates the Provider binding internally, while a
148
+ prior staged comment attachment may be passed as `batch=` when several uploads will be saved into one comment.
149
+ `RecordFilesAttachmentRootAppend`, `RecordTableFileAttachmentReplacement`, and
150
+ `RecordFilesAttachmentReplacement` are also removed: `RecordFilesAttachmentAppend` and
151
+ `RecordAttachmentReplacement` cover those intents, and files append now calls its optional location `folder_path`
152
+ instead of the wire-shaped `path`. Final operations centrally reject a different notebook or uploader, duplicate
153
+ references, and reuse after an attempted finalization. Provider temporary row IDs and caller-known response echoes
154
+ remain internal, while upload responses are still validated. `RecordImportItem.data` uses the recursive
155
+ `RecordImportValue` type instead of `object`, matching the JSON-or-staged-attachment values accepted at runtime.
156
+ - Breaking: group discovery replaces the raw data-server selector with `notebook_creation_available`.
157
+ `groups.list()` now returns the `GroupSummary` tuple directly and removes `GroupCollection` and `GroupMember`; the
158
+ Provider's unstable first-group member projection remains wire-only. Cloud-drive listings no longer expose synthetic
159
+ root metadata, constant caller ownership, inferred file locations or request echoes. `CloudDriveListing` retains
160
+ `total_count` and SDK-derived `has_more` directly and removes the one-use `CloudFilePage` wrapper. Completed staged files
161
+ keep their temporary Provider URL as an internal cross-operation binding detail rather than public metadata.
162
+ - Breaking: `StagedFile` now exposes its downstream `binding` directly instead of embedding the completed upload's
163
+ `StagedUploadSession`; `next_offset` remains exclusive to active sessions, while the upload-session identity remains
164
+ internal for cleanup. Non-final staging now returns the next `StagedUploadSession` directly and removes the shallow
165
+ `StagedFileFragment` wrapper. Byte fragments derive their size when omitted; file-like fragments still require it.
166
+ Provider-returned filename and size are still validated but no longer repeat caller-known values on the completed
167
+ result. `uploads.abort()` accepts either an active session or a completed staged file.
168
+ - Simplifies notebook operation boundaries around one internal allowed-scope validator. `NotebookRef.title` rejects
169
+ blank values but preserves surrounding whitespace because legacy private operations use the exact title as a
170
+ selector. Its `Literal` already defines the three possible scope values; operation seams state whether they accept
171
+ owned, shared, or public refs without a redundant constructor check.
172
+ - Makes the repository Ruff configuration authoritative for generated models. Generator emission uses its built-in
173
+ formatter before the explicit project-configured Ruff normalization, avoiding two competing Ruff configurations.
174
+
175
+ ## 0.1.0a15 - 2026-08-10
176
+
177
+ - Breaking: removes `PublicNotebookRef` and uses one `NotebookRef` with `scope="owned"`, `"shared"`, or `"public"`.
178
+ Public `notebook_id` values identify `eln_public` catalog rows rather than source ELNs; public record results retain
179
+ their separate source notebook identity.
180
+ - Centralizes notebook-scope validation: public record listing accepts only a public ref with a non-empty title,
181
+ private operations reject public refs, and owned-only notebook mutations reject shared/public refs. `NotebookRef.title`
182
+ is a non-empty `str` preserved without whitespace normalization; an unexpected null from the wider owned/shared wire
183
+ contract is reported as a protocol violation, matching Provider write validation and audited runtime data.
184
+
185
+ ## 0.1.0a14 - 2026-08-10
186
+
187
+ - Adds immutable semantic template modules, editable `TemplateDocument` values, ordered name-based patch intents,
188
+ stable content fingerprints, and `Templates.read_document()`, `save_document()`, and `patch_content()` while
189
+ retaining the low-level `TemplateModule`, `read()`, and `save_content()` interface.
190
+
191
+ ## 0.1.0a13 - 2026-08-08
192
+
193
+ - Breaking: `Identity.username` now removes surrounding whitespace and rejects values that become empty.
194
+ - Keeps `ByteRange` typed through the transport adapter and closes the underlying HTTPX2 response when download reads
195
+ or iteration finish or fail, while retaining explicit `DownloadStream.aclose()` for deferred framework consumers.
196
+ - Consolidates Provider session validation through the public `Session` models and simplifies private wire-rule and
197
+ token-refresh validation without changing the pinned Integration Contract.
198
+
199
+ ## 0.1.0a12 - 2026-08-07
200
+
201
+ - Breaking: removes `MatelabAttachmentValidationError`; local attachment size and checksum mismatches now use the
202
+ existing `MatelabUsageError` without a separate reason/value interface.
203
+ - Adopts immutable `matelab-spec v0.4.0` at commit `7993a7bccc213f626b9cc8124423e2b2c9e48dd7` and OpenAPI
204
+ SHA-256 `e725c9649700d5b4d1c7d75fb9422d64b04a68e0308ddec29ba274d774104c8e`. Fixed response models now
205
+ accept but ignore additive Provider fields; only the Contract's seven semantically open models preserve them.
206
+ - Breaking: removes the unused `StagedUploadSession.new()` constructor and the caller-echoed
207
+ `StagedFileFragment.fragment_size` field. `uploads.stage()` now owns fresh-session creation while retaining explicit
208
+ restored sessions, automatic single-`bytes` checksums, and required complete checksums for resumed final fragments.
209
+ - Breaking: removes untyped pass-through attributes from cloud-drive results, literature schema fields, and extracted
210
+ literature authors. Unknown response fields remain parse-compatible but are ignored unless the Contract defines an
211
+ open data shape. Template publication reasons now use only the Contract-declared Provider key.
212
+
213
+ ## 0.1.0a11 - 2026-08-05
214
+
215
+ - Adds `AsyncIterable[bytes]` support to the three complete record-attachment upload interfaces without adding new
216
+ methods. Async content is spooled, size/checksum validated, rewound, and cleaned up without blocking the event loop;
217
+ `sha256` may now be omitted and computed by the SDK.
218
+ - Adds structured `MatelabAttachmentValidationError` reasons and expected/actual values so integrations can distinguish
219
+ size and checksum failures without parsing exception text. Validation failures occur before Provider staging, while
220
+ source exceptions propagate unchanged.
221
+
222
+ ## 0.1.0a10 - 2026-08-05
223
+
224
+ - Keeps synchronous multipart file length probes and chunk reads off the event-loop thread while preserving streamed
225
+ uploads, correct content length, the bytes fast path, and existing non-replay retry restrictions.
226
+ - Replaces implicit-override suppressions with explicit `@override` declarations, simplifies inferred model attributes,
227
+ and declares the Python 3.11 `typing-extensions` runtime dependency directly.
228
+
229
+ ## 0.1.0a9 - 2026-08-04
230
+
231
+ - Breaking: removes `MatelabProviderErrorKind` and `MatelabProviderError.kind`; Provider wire codes now map directly
232
+ to the final `MatelabErrorCategory`, which integrations consume through `MatelabError.category`. This public API
233
+ removal requires a subsequent SemVer-appropriate release before distribution. Operation-specific code `0`/`10`
234
+ success handling and the bounded code `5` authentication refresh remain unchanged.
235
+ - Adds a conservative `retryable` flag to every public SDK error.
236
+
237
+ ## 0.1.0a8 - 2026-08-04
238
+
239
+ - Adds a unified `MatelabErrorCategory` and conservative `retryable` flag to every public SDK error, centralizing
240
+ Provider error semantics so integrations no longer reinterpret `MatelabProviderErrorKind`.
241
+
242
+ ## 0.1.0a7 - 2026-08-04
243
+
244
+ - Replaces the hand-maintained wire-validation rule tables with deterministic generated JSON Schema 2020-12 rules.
245
+ - Simplifies transport, streaming, error mapping, and domain adapters while retaining the pinned `matelab-spec v0.3.0`
246
+ behavior and automatic Session refresh guarantees.
247
+ - Breaking: tightens several public domain inputs and results, and exposes stable `MatelabProviderErrorKind` values
248
+ instead of raw Provider error codes.
249
+ - Removes completed roadmap and work-package bookkeeping; refreshes release checks, documentation, and tests.
250
+
251
+ ## 0.1.0a6 - 2026-08-01
252
+
253
+ - Adopts the immutable `matelab-spec v0.3.0` Contract release and its form-encoding updates.
254
+ - Tightens the public authentication/session contract around complete, serializable Pydantic `Session` models while
255
+ retaining automatic access-token refresh and Provider SSO exchange.
256
+ - Simplifies transport and domain interfaces, removes external-token binding and identity-attachment seams, and
257
+ restores strict runtime validation for byte-range inputs.
258
+
259
+ ## 0.1.0a5 - 2026-07-29
260
+
261
+ - Adopts immutable `matelab-spec v0.1.2` at commit `6dd674ac001ae61197495ace5eba489d585cb825` and OpenAPI
262
+ SHA-256 `7ccaf3116c8dcec7a6e49ff51fb1a5ecc83a140e013ec600516f5c2ffb3b5378`.
263
+ - Adds notebook-scoped staged finalizers for a null table file cell, an attachment-bearing appended table row,
264
+ files-module root append, and table/files occurrence replacement, with exact provenance, one-shot transport, and
265
+ canonical readback checks.
266
+ - Adds typed intents for an empty file table column and complete form file-field/table file-column deletion.
267
+ - Allows `records.update(..., module_deletions=...)` to delete a canonical module even when the current record read
268
+ observes attachments in it, verifies absence on persisted readback, and does not claim attachment-quote or byte
269
+ cleanup beyond the pinned Contract.
270
+ - Rejects cross-scope staged attachment handles before the record read, preserving the public static types while
271
+ avoiding the Provider's read-audit side effect for invalid runtime input.
272
+ - Keeps notebook-staged rich-text binding and attachment-bearing multi-record import explicitly unsupported because
273
+ v0.1.2 Provider Verification does not provide safe one-shot semantics for either.
274
+
275
+ ## 0.1.0a4 - 2026-07-28
276
+
277
+ - Further reduces the alpha public surface from 150 to 126 symbols by accepting direct keyword arguments and existing
278
+ domain values instead of request-shaped wrapper dataclasses.
279
+ - Centralizes safe request-model validation, strengthens generated Contract constraints, and preserves structured field
280
+ diagnostics without exposing credentials, tokens, or sensitive payload values.
281
+ - Tightens Session replacement, refresh races, multipart retry safety, streaming cleanup, and exact HTTP success
282
+ handling while retaining stable transport, authentication, Provider, protocol, usage, and verification errors.
283
+ - Collects all business capabilities under `matelab.domains`, keeps client/session/error/transport primitives at the
284
+ package root, and hardens generation and release-artifact audits.
285
+
286
+ ## 0.1.0a3 - 2026-07-28
287
+
288
+ - Replaces HTTPX with HTTPX2 2.9.1 and raises the Pydantic compatibility floor to 2.13.4. Injected clients must now
289
+ be `httpx2.AsyncClient` instances; HTTPX and HTTPX2 objects are not interchangeable. Default TLS verification now
290
+ uses the operating system trust store.
291
+ - Shrinks the alpha public surface from 184 to 150 symbols by returning existing domain values, tuples, booleans, or
292
+ `None` from simple mutations instead of defining endpoint-shaped result dataclasses. Contract invariants remain
293
+ documented operation semantics rather than repeated constant fields.
294
+ - Reorganizes the record and literature implementations into domain packages and keeps generated wire imports behind
295
+ one private namespace without changing the generated-model boundary.
296
+ - Aligns the opt-in SDK Provider smoke with the isolated test service's shared `MATELAB_PROVIDER_*` environment
297
+ variables and adds a safe `.env.example`.
298
+
299
+ ## 0.1.0a2 - 2026-07-27
300
+
301
+ - Adopts the immutable `matelab-spec v0.1.1` release.
302
+ - Adds notebook-scoped, uploader-bound record attachment staging before a target record exists.
303
+ - Finalizes staged attachments through a single-record import or one new form-file-field update without exposing
304
+ Provider-native attachment syntax or private transport details.
305
+ - Enforces exact notebook/user provenance and one finalization attempt per staged handle in one SDK client.
306
+
307
+ ## 0.1.0a1 - 2026-07-27
308
+
309
+ First public alpha candidate of the asynchronous Matelab Integration Contract SDK.
310
+
311
+ - Binds the immutable `matelab-spec v0.1.0` release.
312
+ - Exposes all 71 pinned Contract operations through public domain interfaces: 15 are stable and 56 remain
313
+ experimental.
314
+ - Provides instance-owned immutable Sessions, bounded token refresh, typed public models, streaming downloads,
315
+ and generated private wire validation.
316
+ - Ships as a typed package for Python 3.11 through 3.14.
317
+ - Uses the Apache License 2.0 with PEP 639 package metadata.
@@ -0,0 +1,91 @@
1
+ # Matelab SDK Domain Language
2
+
3
+ This glossary distinguishes public domain concepts whose names would otherwise be easy to conflate.
4
+
5
+ ## Templates
6
+
7
+ **Template ref**:
8
+ The Provider database identity of one template, independent of how it appears in a user's or group's library.
9
+ _Avoid_: Template library entry ref
10
+
11
+ **Template library entry ref**:
12
+ The relation-row identity for a template in either the authenticated user's library or a group library. User-library
13
+ and group-library relation IDs belong to different identity spaces and select different removal operations.
14
+ _Avoid_: Template ref, template ID
15
+
16
+ **Template scope**:
17
+ How the caller can access a template: owned, directly shared, through a group, or public. A public template's optional
18
+ user-library relation indicates whether the caller acquired it; marketplace review is separate state, not a scope.
19
+ _Avoid_: Template source ID, library relation kind
20
+
21
+ **Template module**:
22
+ One canonical Provider content module. Additive properties and the missing-versus-null `data` distinction are
23
+ preserved across read/save; frontend editor defaults and Agent editing intents are not part of this model.
24
+ _Avoid_: Template document, UI module
25
+
26
+ ## Literature
27
+
28
+ **Literature metadata input**:
29
+ A complete canonical set of bibliographic values proposed for creating or replacing a literature item.
30
+ _Avoid_: Stored metadata, metadata snapshot
31
+
32
+ **Stored literature metadata**:
33
+ The bibliographic values currently stored for a literature item, including readable values that may not be accepted in
34
+ a canonical replacement.
35
+ _Avoid_: Metadata input, update payload
36
+
37
+ **Publication metadata candidate**:
38
+ Unstored bibliographic evidence extracted from a DOI or publication file for review and possible reuse.
39
+ _Avoid_: Stored metadata, canonical metadata
40
+
41
+ **Publication author candidate**:
42
+ A structured author candidate supplied by publication metadata extraction.
43
+ _Avoid_: Literature author text
44
+
45
+ **Literature author text**:
46
+ A single textual representation of a literature item's authors, whether it has one author or many.
47
+ _Avoid_: Authors array, author list
48
+
49
+ **Literature keyword**:
50
+ A bibliographic subject term describing a literature item, independent of any library that contains the item.
51
+ _Avoid_: Tag, library keyword
52
+
53
+ **Literature tag**:
54
+ A classification label associated with a literature item within a particular library. A library's tag set is the
55
+ aggregate of its item tags.
56
+ _Avoid_: Keyword, item keyword, library keyword
57
+
58
+ ## Records
59
+
60
+ **Record ref**:
61
+ The Provider database row identity and UID of one active or deleted record, without notebook context.
62
+ _Avoid_: Record locator, public record ref, deleted record ref
63
+
64
+ **Record locator**:
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.
67
+ _Avoid_: Record ref, notebook ID
68
+
69
+ **Record version ref**:
70
+ A historical version ID bound to its record locator. It identifies observed historical content, not a separate active
71
+ record.
72
+ _Avoid_: Record ref, current version number
73
+
74
+ **Record relation ref**:
75
+ An observed relation-row ID and its declared target notebook/record IDs. The source locator is supplied separately to
76
+ relation deletion; nullable joined target previews and resolved identities remain wire-only.
77
+ _Avoid_: Relation summary, target record locator
78
+
79
+ **Record folder**:
80
+ A notebook-scoped hierarchical container used to organize records. Records at the notebook root have no folder.
81
+ _Avoid_: Subtype, record type, template
82
+
83
+ **Record import value**:
84
+ A template-shaped value composed of JSON-compatible scalars and containers, with a staged attachment
85
+ allowed wherever the template expects a file.
86
+ _Avoid_: Arbitrary object, stored record module, Provider attachment reference
87
+
88
+ **Staged attachment**:
89
+ An upload prepared in a selected notebook for one later record import or update; uploading does not choose the target
90
+ record.
91
+ _Avoid_: Import attachment, record-scoped upload, stored attachment, attachment ref