trackerkit 0.3.0__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 (44) hide show
  1. trackerkit-0.3.0/LICENSE +21 -0
  2. trackerkit-0.3.0/PKG-INFO +300 -0
  3. trackerkit-0.3.0/README.md +273 -0
  4. trackerkit-0.3.0/pyproject.toml +73 -0
  5. trackerkit-0.3.0/src/trackerkit/__init__.py +81 -0
  6. trackerkit-0.3.0/src/trackerkit/contracts/__init__.py +35 -0
  7. trackerkit-0.3.0/src/trackerkit/contracts/auth.py +91 -0
  8. trackerkit-0.3.0/src/trackerkit/contracts/comments.py +14 -0
  9. trackerkit-0.3.0/src/trackerkit/contracts/connection.py +14 -0
  10. trackerkit-0.3.0/src/trackerkit/contracts/projects.py +43 -0
  11. trackerkit-0.3.0/src/trackerkit/contracts/relations.py +30 -0
  12. trackerkit-0.3.0/src/trackerkit/contracts/task_tracker_client.py +25 -0
  13. trackerkit-0.3.0/src/trackerkit/contracts/tasks.py +28 -0
  14. trackerkit-0.3.0/src/trackerkit/contracts/users.py +10 -0
  15. trackerkit-0.3.0/src/trackerkit/domain/__init__.py +70 -0
  16. trackerkit-0.3.0/src/trackerkit/domain/enums.py +28 -0
  17. trackerkit-0.3.0/src/trackerkit/domain/errors.py +37 -0
  18. trackerkit-0.3.0/src/trackerkit/domain/models.py +131 -0
  19. trackerkit-0.3.0/src/trackerkit/domain/relation_mapping.py +215 -0
  20. trackerkit-0.3.0/src/trackerkit/factory/__init__.py +4 -0
  21. trackerkit-0.3.0/src/trackerkit/factory/client_factory.py +105 -0
  22. trackerkit-0.3.0/src/trackerkit/providers/__init__.py +6 -0
  23. trackerkit-0.3.0/src/trackerkit/providers/asana/__init__.py +4 -0
  24. trackerkit-0.3.0/src/trackerkit/providers/asana/client.py +189 -0
  25. trackerkit-0.3.0/src/trackerkit/providers/asana/errors.py +12 -0
  26. trackerkit-0.3.0/src/trackerkit/providers/asana/mappers.py +84 -0
  27. trackerkit-0.3.0/src/trackerkit/providers/asana/queries.py +58 -0
  28. trackerkit-0.3.0/src/trackerkit/providers/asana/transport.py +193 -0
  29. trackerkit-0.3.0/src/trackerkit/providers/base.py +47 -0
  30. trackerkit-0.3.0/src/trackerkit/providers/jira/__init__.py +4 -0
  31. trackerkit-0.3.0/src/trackerkit/providers/jira/client.py +203 -0
  32. trackerkit-0.3.0/src/trackerkit/providers/jira/errors.py +29 -0
  33. trackerkit-0.3.0/src/trackerkit/providers/jira/mappers.py +126 -0
  34. trackerkit-0.3.0/src/trackerkit/providers/jira/queries.py +39 -0
  35. trackerkit-0.3.0/src/trackerkit/providers/jira/relations.py +198 -0
  36. trackerkit-0.3.0/src/trackerkit/providers/jira/transport.py +176 -0
  37. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/__init__.py +4 -0
  38. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/client.py +283 -0
  39. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/errors.py +17 -0
  40. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/mappers.py +95 -0
  41. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/queries.py +62 -0
  42. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/relations.py +165 -0
  43. trackerkit-0.3.0/src/trackerkit/providers/yandex_tracker/transport.py +127 -0
  44. trackerkit-0.3.0/src/trackerkit/tracker_client.py +232 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mikhail Stasyshin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,300 @@
1
+ Metadata-Version: 2.4
2
+ Name: trackerkit
3
+ Version: 0.3.0
4
+ Summary: Unified async client library for Jira, Yandex Tracker, and Asana integrations.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: jira,yandex-tracker,asana,task-tracker,async,integration
8
+ Author: Mikhail Stasyshin
9
+ Author-email: m.stasyshin@gmail.com
10
+ Requires-Python: >=3.12,<4.0
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Dist: asana (>=5.2.4,<6.0.0)
19
+ Requires-Dist: jira (>=3.10.5,<4.0.0)
20
+ Requires-Dist: pydantic (>=2.12.5,<3.0.0)
21
+ Requires-Dist: yandex-tracker-client (>=2.10,<3.0)
22
+ Project-URL: Documentation, https://github.com/depensee-dev/trackerkit#readme
23
+ Project-URL: Homepage, https://github.com/depensee-dev/trackerkit
24
+ Project-URL: Repository, https://github.com/depensee-dev/trackerkit
25
+ Description-Content-Type: text/markdown
26
+
27
+ # trackerkit
28
+
29
+ Unified async client library for Jira, Yandex Tracker, and Asana integrations.
30
+
31
+ ## Status
32
+ - early-stage internal library;
33
+ - API and provider coverage may still evolve;
34
+ - currently focused on a shared contract for Jira, Yandex Tracker, and Asana.
35
+
36
+ ## Installation
37
+
38
+ Install from PyPI:
39
+
40
+ ```bash
41
+ pip install trackerkit
42
+ ```
43
+
44
+ Install from a Git tag:
45
+
46
+ ```bash
47
+ pip install "git+https://github.com/depensee-dev/trackerkit.git@v0.3.0"
48
+ ```
49
+
50
+ Install from the `main` branch:
51
+
52
+ ```bash
53
+ pip install "git+https://github.com/depensee-dev/trackerkit.git@main"
54
+ ```
55
+
56
+ ## Local development
57
+
58
+ ```bash
59
+ poetry install
60
+ ```
61
+
62
+ Install from the current project directory:
63
+
64
+ ```bash
65
+ pip install .
66
+ ```
67
+
68
+ ## Goals
69
+ - provide one common contract for supported task trackers;
70
+ - hide provider-specific SDK details from the main backend;
71
+ - expose only shared entities and operations;
72
+ - keep the design extensible and testable.
73
+
74
+ ## Supported providers
75
+ - Jira
76
+ - Yandex Tracker
77
+ - Asana
78
+
79
+ ## Current scope
80
+ - one facade client per one selected task tracker;
81
+ - common async client contract;
82
+ - shared models for tasks, projects, users, comments, relations, and statuses;
83
+ - provider auth configs;
84
+ - real provider adapters for `workspaces`, `projects`, and `tasks`;
85
+ - relation CRUD for `Jira` and `Yandex Tracker`;
86
+ - users and comments are modeled in the shared contract, but provider adapters currently report them as unsupported capabilities;
87
+ - client factory.
88
+
89
+ ## Internal architecture
90
+ - capability-based contracts instead of one monolithic provider interface;
91
+ - `TrackerClient` facade with centralized connection guard;
92
+ - provider adapters split into `transport`, `queries`, `mappers`, and `errors`;
93
+ - domain models and auth configs remain typed with `Pydantic`;
94
+ - the public API stays async even when a provider transport uses a sync SDK under the hood.
95
+
96
+ ## Package layout
97
+ ```text
98
+ docs/
99
+ examples/
100
+ src/
101
+ └── trackerkit/
102
+ ├── contracts/
103
+ ├── domain/
104
+ ├── factory/
105
+ ├── providers/
106
+ ├── tracker_client.py
107
+ └── __init__.py
108
+ ```
109
+
110
+ ## Usage
111
+ ```python
112
+ from trackerkit import TrackerClient
113
+
114
+ client = TrackerClient(
115
+ provider="jira",
116
+ auth_data={
117
+ "base_url": "https://your-domain.atlassian.net",
118
+ "access_token": "secret",
119
+ },
120
+ connection_timeout=3,
121
+ max_retries=0,
122
+ )
123
+ ```
124
+
125
+ ## Development
126
+ - Python `3.12+` (required — the codebase uses `from datetime import UTC` and
127
+ modern `X | Y` generics that need 3.10+ at minimum, and `UTC` since 3.11;
128
+ 3.12 is the chosen lower bound to match `pydantic 2.12` and `ruff` defaults)
129
+ - package manager: `poetry`
130
+ - import root: `src`
131
+
132
+ ### Local checks
133
+ Build the package locally:
134
+
135
+ ```bash
136
+ python -m pip wheel . --no-deps
137
+ ```
138
+
139
+ Lint and tests (after `poetry install`):
140
+
141
+ ```bash
142
+ poetry run ruff check
143
+ poetry run ruff format --check
144
+ poetry run pytest
145
+ ```
146
+
147
+ ## Service integration
148
+ This library is designed to be embedded into a backend service.
149
+
150
+ - the primary configuration path is explicit `TrackerClient` initialization;
151
+ - the service loads configuration and passes typed `auth_data` into `TrackerClient`;
152
+ - optional helpers such as `RelationMappingConfig.from_env()` read environment variables only when the host service or an example calls them explicitly;
153
+ - connection behavior is configured via explicit `TrackerClient` arguments instead of `auth_data`;
154
+ - only `examples/` load local env files for manual development checks.
155
+
156
+ ### Pydantic settings example
157
+ ```python
158
+ from pydantic_settings import BaseSettings, SettingsConfigDict
159
+
160
+ from trackerkit import TrackerClient
161
+
162
+
163
+ class JiraSettings(BaseSettings):
164
+ model_config = SettingsConfigDict(
165
+ env_file=".env",
166
+ env_file_encoding="utf-8",
167
+ )
168
+
169
+ base_url: str
170
+ token: str
171
+
172
+
173
+ settings = JiraSettings()
174
+
175
+ client = TrackerClient(
176
+ provider="jira",
177
+ auth_data={
178
+ "base_url": settings.base_url,
179
+ "access_token": settings.token,
180
+ },
181
+ connection_timeout=3,
182
+ max_retries=0,
183
+ )
184
+ ```
185
+
186
+ ## Documentation
187
+ - `docs/auth.md` - authorization and client initialization.
188
+ - `docs/projects.md` - workspaces and project methods.
189
+ - `docs/tasks.md` - task methods and task models.
190
+ - `docs/relations.md` - relation semantics, mapping config, and CRUD behavior.
191
+ - `ROADMAP.md` - status, ChainForge-driven priorities, release targets 0.3–0.5.
192
+ - `TECH_ROADMAP.md` - engineering debt, tests, and execution order.
193
+ - `THIRD_PARTY_LICENSES.md` - direct runtime dependency license summary.
194
+
195
+ ## Examples
196
+ - `examples/jira_example.py` - Jira auth, projects flow, task flow, and relation flow.
197
+ - `examples/yandex_example.py` - Yandex Tracker auth, projects flow, task flow, and relation flow.
198
+ - `examples/asana_example.py` - Asana auth and readonly inspection flow.
199
+
200
+ ## Notes
201
+ `src` is configured as the import root for the repository.
202
+
203
+ `Jira`, `Yandex Tracker`, and `Asana` already implement the shared `workspaces`, `projects`, and `tasks` contract. `Jira` and `Yandex Tracker` also implement relation CRUD for the core product relation types. `Asana` relations remain follow-up work.
204
+
205
+ ## Entity Mapping
206
+ `trackerkit` exposes a canonical task-tracker model.
207
+ This model is grounded in provider documentation first, then normalized into a shared contract for the backend.
208
+ Shared entities do not have to match provider-native names one to one.
209
+ They are mapped by functional role in the workflow, and some shared entities are integration-level abstractions rather than native provider objects.
210
+
211
+ ### Provider source model
212
+ | Shared entity | Jira source model | Yandex Tracker source model | Asana source model |
213
+ | --- | --- | --- | --- |
214
+ | `Workspace` | integration-level container for one Jira site / instance | organization context selected by `X-Org-ID` or `X-Cloud-Org-ID` | native Asana workspace |
215
+ | `Project` | native Jira project | queue for operational task work; Yandex also has a separate native `project` entity above queues | native Asana project |
216
+ | `Task` | native Jira issue / work item | native Yandex issue in a queue | native Asana task |
217
+ | `Status` | native issue status | native issue status in queue workflow | task completion state and related task state fields |
218
+ | `User` | native Jira user | native Tracker user | native Asana user |
219
+ | `Relation` | native Jira issue link or hierarchy relation depending on config | native issue link with explicit relationship type and direction | task dependency / dependent edge rather than a general-purpose typed link |
220
+
221
+ ### Canonical mapping decision in `trackerkit`
222
+ - `Jira`: shared `Project` maps to Jira project, and shared `Task` maps to issue.
223
+ - `Yandex Tracker`: shared `Project` maps to queue, and shared `Task` maps to issue inside that queue.
224
+ - `Yandex Tracker`: native Yandex `project` is documented as a separate higher-level entity and is not part of the current shared contract.
225
+ - `Yandex Tracker`: direct issue deletion is not supported by the provider in the same way as in some other trackers, so task deletion should be modeled as unsupported or as a separate close/archive workflow.
226
+ - `Asana`: shared `Project` maps to Asana project, and shared `Task` maps to task.
227
+ - `Jira`: shared `Relation` maps to issue links for `relates` and `blocks`, and to hierarchy for default `contains`.
228
+ - `Yandex Tracker`: shared `Relation` maps to native issue links; provider-native link types cover both dependency-style and hierarchy-style relations.
229
+ - `Asana`: relation mapping is conceptually clear for dependencies and subtasks, but relation CRUD is not implemented in the adapter yet.
230
+
231
+ ### Product-first core relation semantics
232
+ For the product concept, the most important relation taxonomy is the one that supports canvas visualization and planning semantics.
233
+ The core visual set is smaller than the full set of provider-native link types.
234
+
235
+ | Core relation | Meaning in the product | Default visual style | Jira source model | Yandex Tracker source model | Asana source model |
236
+ | --- | --- | --- | --- | --- | --- |
237
+ | `relates` | weak semantic connection without strict dependency | dashed line | symmetric relates-style issue link when configured | native `relates` | no direct native equivalent |
238
+ | `blocks` | one task blocks or unlocks another | directed arrow | Blocks-style issue link direction | `depends on` / `is dependent by` | dependencies / dependents |
239
+ | `contains` | one task structurally includes, decomposes, or parents another | solid line | work item hierarchy such as parent-child or subtask hierarchy | `is parent task for` / `is subtask for`, plus epic-style hierarchy when relevant | subtasks |
240
+
241
+ ### Non-core provider relations
242
+ Provider-specific relation variants such as duplicates, clones, epics, or custom hierarchy
243
+ levels are not part of the public `RelationType` enum. They can be handled later as
244
+ provider metadata or normalized into one of the three core relation types when that
245
+ preserves the product meaning.
246
+
247
+ ### Integration note
248
+ - The product-facing taxonomy above is the active shared model for relation work in the library.
249
+ - Jira allows custom issue link types, so label-based normalization stays explicit and source-aware.
250
+ - `RelationMappingConfig` provides a default `Mode A` structural hierarchy for Jira `contains` and leaves room for `Mode B` custom link mapping.
251
+ - Asana covers dependency and subtask hierarchy well, but does not provide a general-purpose typed link system equivalent to Jira or Yandex Tracker.
252
+
253
+ ### Source notes
254
+ - Jira describes a project/space as a configurable container for work items.
255
+ - Yandex Tracker documents that every issue belongs to a queue, and also documents a separate native `project` entity that can include queues.
256
+ - Asana documents a project as a prioritized list of tasks or a board, and a task as the main work item inside workspaces and projects.
257
+ - Jira documents issue links as bidirectional links with configurable link types, each having inward and outward descriptions.
258
+ - Yandex Tracker documents links between issues with explicit relationship values such as `relates`, `depends on`, `is dependent by`, `duplicates`, and hierarchy-specific variants.
259
+ - Asana documents task dependencies and dependents, which model blocking order rather than a general relation taxonomy.
260
+ - Jira and Asana also document hierarchy-style task structures such as work item hierarchy and subtasks.
261
+ - Yandex Tracker documents hierarchy-oriented issue links such as parent-task and subtask relations.
262
+
263
+ ### Sources
264
+ - Jira: [Projects / spaces overview](https://www.atlassian.com/software/jira/guides/projects/overview)
265
+ - Jira: [Issue linking model](https://developer.atlassian.com/cloud/jira/platform/issue-linking-model/)
266
+ - Yandex Tracker: [Queue introduction](https://yandex.ru/support/tracker/en/queue-intro)
267
+ - Yandex Tracker: [Get project parameters](https://yandex.ru/support/tracker/en/api-ref/projects/get-project)
268
+ - Yandex Tracker: [Linking issues](https://yandex.ru/support/tracker/en/api-ref/issues/link-issue)
269
+ - Asana: [Projects reference](https://developers.asana.com/reference/projects)
270
+ - Asana: [Tasks reference](https://developers.asana.com/reference/tasks)
271
+ - Asana: [Set dependencies for a task](https://developers.asana.com/reference/adddependenciesfortask)
272
+ - Asana: [Get dependents from a task](https://developers.asana.com/reference/getdependentsfortask)
273
+
274
+ Examples use environment variables instead of hardcoded credentials.
275
+ Host services should prefer explicit settings objects and pass `auth_data` / `relation_mapping`
276
+ into `TrackerClient` during initialization:
277
+ - `JIRA_BASE_URL`
278
+ - `JIRA_TOKEN`
279
+ - `JIRA_RELATES_LINK_TYPES` - optional Jira relation mapping, `Type` or `Type|outward|inward`
280
+ - `JIRA_BLOCKS_LINK_TYPES` - optional Jira relation mapping, `Type` or `Type|outward|inward`
281
+ - `JIRA_CONTAINS_LINK_TYPES` - optional Jira relation mapping for custom `contains`
282
+ - `JIRA_CONTAINS_MODE` - optional Jira contains mode override
283
+ - `YANDEX_TOKEN`
284
+ - `YANDEX_CLOUD_ORG_ID` - use one of `YANDEX_CLOUD_ORG_ID` or `YANDEX_ORG_ID`
285
+ - `YANDEX_ORG_ID` - use one of `YANDEX_CLOUD_ORG_ID` or `YANDEX_ORG_ID`
286
+ - `ASANA_TOKEN`
287
+ - `ASANA_PROJECT_ID` - optional, enables Asana task listing
288
+
289
+ Local development files:
290
+ - `.env.example` - fallback template for local example runs
291
+ - `.env` - local override for real local credentials
292
+
293
+ Examples load variables with this priority:
294
+ 1. process environment
295
+ 2. `.env`
296
+ 3. `.env.example`
297
+
298
+ ## Roadmap
299
+ See `ROADMAP.md` for release plan (0.3 sync, 0.4 PERT data, 0.5 scale/auth) and `TECH_ROADMAP.md` for engineering tasks.
300
+
@@ -0,0 +1,273 @@
1
+ # trackerkit
2
+
3
+ Unified async client library for Jira, Yandex Tracker, and Asana integrations.
4
+
5
+ ## Status
6
+ - early-stage internal library;
7
+ - API and provider coverage may still evolve;
8
+ - currently focused on a shared contract for Jira, Yandex Tracker, and Asana.
9
+
10
+ ## Installation
11
+
12
+ Install from PyPI:
13
+
14
+ ```bash
15
+ pip install trackerkit
16
+ ```
17
+
18
+ Install from a Git tag:
19
+
20
+ ```bash
21
+ pip install "git+https://github.com/depensee-dev/trackerkit.git@v0.3.0"
22
+ ```
23
+
24
+ Install from the `main` branch:
25
+
26
+ ```bash
27
+ pip install "git+https://github.com/depensee-dev/trackerkit.git@main"
28
+ ```
29
+
30
+ ## Local development
31
+
32
+ ```bash
33
+ poetry install
34
+ ```
35
+
36
+ Install from the current project directory:
37
+
38
+ ```bash
39
+ pip install .
40
+ ```
41
+
42
+ ## Goals
43
+ - provide one common contract for supported task trackers;
44
+ - hide provider-specific SDK details from the main backend;
45
+ - expose only shared entities and operations;
46
+ - keep the design extensible and testable.
47
+
48
+ ## Supported providers
49
+ - Jira
50
+ - Yandex Tracker
51
+ - Asana
52
+
53
+ ## Current scope
54
+ - one facade client per one selected task tracker;
55
+ - common async client contract;
56
+ - shared models for tasks, projects, users, comments, relations, and statuses;
57
+ - provider auth configs;
58
+ - real provider adapters for `workspaces`, `projects`, and `tasks`;
59
+ - relation CRUD for `Jira` and `Yandex Tracker`;
60
+ - users and comments are modeled in the shared contract, but provider adapters currently report them as unsupported capabilities;
61
+ - client factory.
62
+
63
+ ## Internal architecture
64
+ - capability-based contracts instead of one monolithic provider interface;
65
+ - `TrackerClient` facade with centralized connection guard;
66
+ - provider adapters split into `transport`, `queries`, `mappers`, and `errors`;
67
+ - domain models and auth configs remain typed with `Pydantic`;
68
+ - the public API stays async even when a provider transport uses a sync SDK under the hood.
69
+
70
+ ## Package layout
71
+ ```text
72
+ docs/
73
+ examples/
74
+ src/
75
+ └── trackerkit/
76
+ ├── contracts/
77
+ ├── domain/
78
+ ├── factory/
79
+ ├── providers/
80
+ ├── tracker_client.py
81
+ └── __init__.py
82
+ ```
83
+
84
+ ## Usage
85
+ ```python
86
+ from trackerkit import TrackerClient
87
+
88
+ client = TrackerClient(
89
+ provider="jira",
90
+ auth_data={
91
+ "base_url": "https://your-domain.atlassian.net",
92
+ "access_token": "secret",
93
+ },
94
+ connection_timeout=3,
95
+ max_retries=0,
96
+ )
97
+ ```
98
+
99
+ ## Development
100
+ - Python `3.12+` (required — the codebase uses `from datetime import UTC` and
101
+ modern `X | Y` generics that need 3.10+ at minimum, and `UTC` since 3.11;
102
+ 3.12 is the chosen lower bound to match `pydantic 2.12` and `ruff` defaults)
103
+ - package manager: `poetry`
104
+ - import root: `src`
105
+
106
+ ### Local checks
107
+ Build the package locally:
108
+
109
+ ```bash
110
+ python -m pip wheel . --no-deps
111
+ ```
112
+
113
+ Lint and tests (after `poetry install`):
114
+
115
+ ```bash
116
+ poetry run ruff check
117
+ poetry run ruff format --check
118
+ poetry run pytest
119
+ ```
120
+
121
+ ## Service integration
122
+ This library is designed to be embedded into a backend service.
123
+
124
+ - the primary configuration path is explicit `TrackerClient` initialization;
125
+ - the service loads configuration and passes typed `auth_data` into `TrackerClient`;
126
+ - optional helpers such as `RelationMappingConfig.from_env()` read environment variables only when the host service or an example calls them explicitly;
127
+ - connection behavior is configured via explicit `TrackerClient` arguments instead of `auth_data`;
128
+ - only `examples/` load local env files for manual development checks.
129
+
130
+ ### Pydantic settings example
131
+ ```python
132
+ from pydantic_settings import BaseSettings, SettingsConfigDict
133
+
134
+ from trackerkit import TrackerClient
135
+
136
+
137
+ class JiraSettings(BaseSettings):
138
+ model_config = SettingsConfigDict(
139
+ env_file=".env",
140
+ env_file_encoding="utf-8",
141
+ )
142
+
143
+ base_url: str
144
+ token: str
145
+
146
+
147
+ settings = JiraSettings()
148
+
149
+ client = TrackerClient(
150
+ provider="jira",
151
+ auth_data={
152
+ "base_url": settings.base_url,
153
+ "access_token": settings.token,
154
+ },
155
+ connection_timeout=3,
156
+ max_retries=0,
157
+ )
158
+ ```
159
+
160
+ ## Documentation
161
+ - `docs/auth.md` - authorization and client initialization.
162
+ - `docs/projects.md` - workspaces and project methods.
163
+ - `docs/tasks.md` - task methods and task models.
164
+ - `docs/relations.md` - relation semantics, mapping config, and CRUD behavior.
165
+ - `ROADMAP.md` - status, ChainForge-driven priorities, release targets 0.3–0.5.
166
+ - `TECH_ROADMAP.md` - engineering debt, tests, and execution order.
167
+ - `THIRD_PARTY_LICENSES.md` - direct runtime dependency license summary.
168
+
169
+ ## Examples
170
+ - `examples/jira_example.py` - Jira auth, projects flow, task flow, and relation flow.
171
+ - `examples/yandex_example.py` - Yandex Tracker auth, projects flow, task flow, and relation flow.
172
+ - `examples/asana_example.py` - Asana auth and readonly inspection flow.
173
+
174
+ ## Notes
175
+ `src` is configured as the import root for the repository.
176
+
177
+ `Jira`, `Yandex Tracker`, and `Asana` already implement the shared `workspaces`, `projects`, and `tasks` contract. `Jira` and `Yandex Tracker` also implement relation CRUD for the core product relation types. `Asana` relations remain follow-up work.
178
+
179
+ ## Entity Mapping
180
+ `trackerkit` exposes a canonical task-tracker model.
181
+ This model is grounded in provider documentation first, then normalized into a shared contract for the backend.
182
+ Shared entities do not have to match provider-native names one to one.
183
+ They are mapped by functional role in the workflow, and some shared entities are integration-level abstractions rather than native provider objects.
184
+
185
+ ### Provider source model
186
+ | Shared entity | Jira source model | Yandex Tracker source model | Asana source model |
187
+ | --- | --- | --- | --- |
188
+ | `Workspace` | integration-level container for one Jira site / instance | organization context selected by `X-Org-ID` or `X-Cloud-Org-ID` | native Asana workspace |
189
+ | `Project` | native Jira project | queue for operational task work; Yandex also has a separate native `project` entity above queues | native Asana project |
190
+ | `Task` | native Jira issue / work item | native Yandex issue in a queue | native Asana task |
191
+ | `Status` | native issue status | native issue status in queue workflow | task completion state and related task state fields |
192
+ | `User` | native Jira user | native Tracker user | native Asana user |
193
+ | `Relation` | native Jira issue link or hierarchy relation depending on config | native issue link with explicit relationship type and direction | task dependency / dependent edge rather than a general-purpose typed link |
194
+
195
+ ### Canonical mapping decision in `trackerkit`
196
+ - `Jira`: shared `Project` maps to Jira project, and shared `Task` maps to issue.
197
+ - `Yandex Tracker`: shared `Project` maps to queue, and shared `Task` maps to issue inside that queue.
198
+ - `Yandex Tracker`: native Yandex `project` is documented as a separate higher-level entity and is not part of the current shared contract.
199
+ - `Yandex Tracker`: direct issue deletion is not supported by the provider in the same way as in some other trackers, so task deletion should be modeled as unsupported or as a separate close/archive workflow.
200
+ - `Asana`: shared `Project` maps to Asana project, and shared `Task` maps to task.
201
+ - `Jira`: shared `Relation` maps to issue links for `relates` and `blocks`, and to hierarchy for default `contains`.
202
+ - `Yandex Tracker`: shared `Relation` maps to native issue links; provider-native link types cover both dependency-style and hierarchy-style relations.
203
+ - `Asana`: relation mapping is conceptually clear for dependencies and subtasks, but relation CRUD is not implemented in the adapter yet.
204
+
205
+ ### Product-first core relation semantics
206
+ For the product concept, the most important relation taxonomy is the one that supports canvas visualization and planning semantics.
207
+ The core visual set is smaller than the full set of provider-native link types.
208
+
209
+ | Core relation | Meaning in the product | Default visual style | Jira source model | Yandex Tracker source model | Asana source model |
210
+ | --- | --- | --- | --- | --- | --- |
211
+ | `relates` | weak semantic connection without strict dependency | dashed line | symmetric relates-style issue link when configured | native `relates` | no direct native equivalent |
212
+ | `blocks` | one task blocks or unlocks another | directed arrow | Blocks-style issue link direction | `depends on` / `is dependent by` | dependencies / dependents |
213
+ | `contains` | one task structurally includes, decomposes, or parents another | solid line | work item hierarchy such as parent-child or subtask hierarchy | `is parent task for` / `is subtask for`, plus epic-style hierarchy when relevant | subtasks |
214
+
215
+ ### Non-core provider relations
216
+ Provider-specific relation variants such as duplicates, clones, epics, or custom hierarchy
217
+ levels are not part of the public `RelationType` enum. They can be handled later as
218
+ provider metadata or normalized into one of the three core relation types when that
219
+ preserves the product meaning.
220
+
221
+ ### Integration note
222
+ - The product-facing taxonomy above is the active shared model for relation work in the library.
223
+ - Jira allows custom issue link types, so label-based normalization stays explicit and source-aware.
224
+ - `RelationMappingConfig` provides a default `Mode A` structural hierarchy for Jira `contains` and leaves room for `Mode B` custom link mapping.
225
+ - Asana covers dependency and subtask hierarchy well, but does not provide a general-purpose typed link system equivalent to Jira or Yandex Tracker.
226
+
227
+ ### Source notes
228
+ - Jira describes a project/space as a configurable container for work items.
229
+ - Yandex Tracker documents that every issue belongs to a queue, and also documents a separate native `project` entity that can include queues.
230
+ - Asana documents a project as a prioritized list of tasks or a board, and a task as the main work item inside workspaces and projects.
231
+ - Jira documents issue links as bidirectional links with configurable link types, each having inward and outward descriptions.
232
+ - Yandex Tracker documents links between issues with explicit relationship values such as `relates`, `depends on`, `is dependent by`, `duplicates`, and hierarchy-specific variants.
233
+ - Asana documents task dependencies and dependents, which model blocking order rather than a general relation taxonomy.
234
+ - Jira and Asana also document hierarchy-style task structures such as work item hierarchy and subtasks.
235
+ - Yandex Tracker documents hierarchy-oriented issue links such as parent-task and subtask relations.
236
+
237
+ ### Sources
238
+ - Jira: [Projects / spaces overview](https://www.atlassian.com/software/jira/guides/projects/overview)
239
+ - Jira: [Issue linking model](https://developer.atlassian.com/cloud/jira/platform/issue-linking-model/)
240
+ - Yandex Tracker: [Queue introduction](https://yandex.ru/support/tracker/en/queue-intro)
241
+ - Yandex Tracker: [Get project parameters](https://yandex.ru/support/tracker/en/api-ref/projects/get-project)
242
+ - Yandex Tracker: [Linking issues](https://yandex.ru/support/tracker/en/api-ref/issues/link-issue)
243
+ - Asana: [Projects reference](https://developers.asana.com/reference/projects)
244
+ - Asana: [Tasks reference](https://developers.asana.com/reference/tasks)
245
+ - Asana: [Set dependencies for a task](https://developers.asana.com/reference/adddependenciesfortask)
246
+ - Asana: [Get dependents from a task](https://developers.asana.com/reference/getdependentsfortask)
247
+
248
+ Examples use environment variables instead of hardcoded credentials.
249
+ Host services should prefer explicit settings objects and pass `auth_data` / `relation_mapping`
250
+ into `TrackerClient` during initialization:
251
+ - `JIRA_BASE_URL`
252
+ - `JIRA_TOKEN`
253
+ - `JIRA_RELATES_LINK_TYPES` - optional Jira relation mapping, `Type` or `Type|outward|inward`
254
+ - `JIRA_BLOCKS_LINK_TYPES` - optional Jira relation mapping, `Type` or `Type|outward|inward`
255
+ - `JIRA_CONTAINS_LINK_TYPES` - optional Jira relation mapping for custom `contains`
256
+ - `JIRA_CONTAINS_MODE` - optional Jira contains mode override
257
+ - `YANDEX_TOKEN`
258
+ - `YANDEX_CLOUD_ORG_ID` - use one of `YANDEX_CLOUD_ORG_ID` or `YANDEX_ORG_ID`
259
+ - `YANDEX_ORG_ID` - use one of `YANDEX_CLOUD_ORG_ID` or `YANDEX_ORG_ID`
260
+ - `ASANA_TOKEN`
261
+ - `ASANA_PROJECT_ID` - optional, enables Asana task listing
262
+
263
+ Local development files:
264
+ - `.env.example` - fallback template for local example runs
265
+ - `.env` - local override for real local credentials
266
+
267
+ Examples load variables with this priority:
268
+ 1. process environment
269
+ 2. `.env`
270
+ 3. `.env.example`
271
+
272
+ ## Roadmap
273
+ See `ROADMAP.md` for release plan (0.3 sync, 0.4 PERT data, 0.5 scale/auth) and `TECH_ROADMAP.md` for engineering tasks.
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "trackerkit"
3
+ version = "0.3.0"
4
+ description = "Unified async client library for Jira, Yandex Tracker, and Asana integrations."
5
+ readme = "README.md"
6
+ requires-python = ">=3.12,<4.0"
7
+ license = "MIT"
8
+ authors = [
9
+ { name = "Mikhail Stasyshin", email = "m.stasyshin@gmail.com" },
10
+ ]
11
+ keywords = ["jira", "yandex-tracker", "asana", "task-tracker", "async", "integration"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Topic :: Software Development :: Libraries :: Python Modules",
20
+ ]
21
+ dependencies = [
22
+ "pydantic>=2.12.5,<3.0.0",
23
+ "jira>=3.10.5,<4.0.0",
24
+ "yandex-tracker-client>=2.10,<3.0",
25
+ "asana>=5.2.4,<6.0.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/depensee-dev/trackerkit"
30
+ Repository = "https://github.com/depensee-dev/trackerkit"
31
+ Documentation = "https://github.com/depensee-dev/trackerkit#readme"
32
+
33
+ [tool.poetry]
34
+ packages = [{ include = "trackerkit", from = "src" }]
35
+
36
+ [tool.poetry.group.dev.dependencies]
37
+ pytest = "*"
38
+ pytest-asyncio = "*"
39
+ ruff = "*"
40
+
41
+ [build-system]
42
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
43
+ build-backend = "poetry.core.masonry.api"
44
+
45
+ [tool.ruff]
46
+ target-version = "py312"
47
+ line-length = 100
48
+ src = ["src", "tests"]
49
+
50
+ [tool.ruff.lint]
51
+ select = [
52
+ "E", # pycodestyle errors
53
+ "F", # pyflakes
54
+ "I", # isort
55
+ "UP", # pyupgrade
56
+ "B", # bugbear
57
+ "SIM", # simplify
58
+ "RUF", # ruff-specific
59
+ ]
60
+ ignore = [
61
+ "E501", # long lines: prefer formatter over hard wraps
62
+ "UP042", # `(str, Enum)` is intentional; StrEnum changes repr/hash semantics
63
+ ]
64
+
65
+ [tool.ruff.lint.per-file-ignores]
66
+ "tests/**/*.py" = ["B011"]
67
+
68
+ [tool.pytest.ini_options]
69
+ minversion = "7.0"
70
+ asyncio_mode = "auto"
71
+ testpaths = ["tests"]
72
+ addopts = "-q"
73
+