ya-dialogs-api 1.0.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.
@@ -0,0 +1,55 @@
1
+ # Byte-compiled / optimized
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ *.egg
12
+ wheels/
13
+ share/python-wheels/
14
+ .eggs/
15
+ MANIFEST
16
+
17
+ # Virtual environments
18
+ .venv/
19
+ venv/
20
+ env/
21
+ ENV/
22
+
23
+ # Tooling caches
24
+ .mypy_cache/
25
+ .ruff_cache/
26
+ .pytest_cache/
27
+ .tox/
28
+ .nox/
29
+ .cache/
30
+ htmlcov/
31
+ .coverage
32
+ .coverage.*
33
+ coverage.xml
34
+ *.cover
35
+ .hypothesis/
36
+
37
+ # Secrets scan
38
+ .secrets.baseline
39
+
40
+ # Editors / OS
41
+ .vscode/
42
+ .idea/
43
+ *.swp
44
+ *.swo
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # Generated
49
+ _version.py
50
+ sbom.json
51
+ *.sigstore
52
+ *.intoto.jsonl
53
+
54
+ # Local test artifacts
55
+ manual_qr_output.txt
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. The format is based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.0] — 2026-05-06
10
+
11
+ ### Added
12
+
13
+ Initial public release. Async Yandex Dialogs Developer API client extracted
14
+ from `ma-provider-yandex-smarthome/provider/auto_skill.py` and made
15
+ framework-agnostic.
16
+
17
+ **Public API:**
18
+
19
+ - `auto_create_skill(...)` — full skill-creation pipeline (CSRF/cookie session
20
+ → POST `/apps` → upload logo → PATCH draft → POST OAuth app → attach OAuth
21
+ → request deploy). Handles both `skill_type="smart_home"` and
22
+ `skill_type="dialog"` channels. Resumable via `SkillCreationArtifacts`.
23
+ - `auto_rename_dialog_skill(...)` — patches a dialog skill draft name and
24
+ re-deploys.
25
+ - `DialogsSkillCreator` — low-level dev-console client (one method per
26
+ pipeline step).
27
+ - `SkillCreationArtifacts` / `SkillCreationState` — incremental state
28
+ machine; callers persist between calls so transient failures resume from
29
+ the last completed step.
30
+ - Payload builders: `build_smart_home_draft_payload`,
31
+ `build_dialog_draft_payload`, `build_oauth_app_payload`.
32
+ - `load_default_logo_bytes()` — bundled fallback skill logo.
33
+ - `SecretStr` re-exported from `ya-passport-auth` for token redaction.
34
+ - Typed errors: `DialogsApiError`, `DialogsCsrfError`,
35
+ `DialogsDuplicateSkillError`.
36
+
37
+ **Architecture:**
38
+
39
+ The library is **framework-agnostic**. Authentication is the caller's
40
+ responsibility — pass a no-arg async-context-manager factory (`AuthenticatorCM`)
41
+ that yields an authenticated `aiohttp.ClientSession`. Typically the caller
42
+ wraps `ya_passport_auth.PassportClient.login_device_code` and any UX surface
43
+ they want around the Device Flow user-code prompt (CLI, web page, Telegram,
44
+ Music Assistant config-flow, etc.).
45
+
46
+ All URLs are pre-computed by the caller (`backend_uri`, `oauth_authorize_url`,
47
+ `oauth_token_url`, `oauth_client_id`, `oauth_client_secret`) — the lib has
48
+ no opinion on connection-type or hosting.
49
+
50
+ Failures are values, not exceptions: pipeline errors land as
51
+ `artifacts.state=FAILED` with `last_error` set. Truly unexpected exceptions
52
+ still propagate.
53
+
54
+ **Testing:**
55
+
56
+ - 47 tests across `DialogsSkillCreator` methods, payload builders,
57
+ state-machine serialisation, orchestrator happy paths, resume from each
58
+ state, and failure recovery.
59
+ - `mypy --strict` clean.
60
+ - 86% coverage (state.py 100%, api_client.py 83%).
61
+
62
+ **Runtime dependencies:**
63
+
64
+ - `aiohttp >= 3.10, < 4`
65
+ - `ya-passport-auth >= 1.3.0`
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mikhail Nevskiy
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,29 @@
1
+ ya-dialogs-api
2
+ Copyright (c) 2026 Mikhail Nevskiy
3
+
4
+ This library implements a client for the Yandex Dialogs Developer API
5
+ (`dialogs.yandex.ru/developer-api/v2/`). The API is undocumented and
6
+ private — the request shapes, endpoint paths, CSRF extraction pattern,
7
+ and pipeline ordering were captured from Chrome DevTools HAR files
8
+ during interactive sessions with the Yandex developer console.
9
+
10
+ This product includes software originally developed as part of the
11
+ ma-provider-yandex-smarthome Music Assistant plugin:
12
+
13
+ ma-provider-yandex-smarthome
14
+ Copyright (c) 2025-2026 Mikhail Nevskiy
15
+ https://github.com/trudenboy/ma-provider-yandex-smarthome
16
+ Licensed under the MIT License
17
+
18
+ The skill auto-creation pipeline (Device Flow OAuth → CSRF/cookie session
19
+ → POST /apps → POST /skills/{id}/draft → publication polling) was
20
+ extracted from `provider/auto_skill.py` of that project and made
21
+ framework-agnostic for general use.
22
+
23
+ The default skill logo asset (`src/ya_dialogs_api/assets/default_logo.png`)
24
+ is also drawn from that upstream project.
25
+
26
+ This library uses ya-passport-auth (https://github.com/trudenboy/ya-passport-auth)
27
+ for the Yandex Passport authentication side of the flow. ya-passport-auth
28
+ in turn re-implements work originally derived from AlexxIT/YandexStation;
29
+ see ya-passport-auth's NOTICE for that upstream attribution.
@@ -0,0 +1,170 @@
1
+ Metadata-Version: 2.4
2
+ Name: ya-dialogs-api
3
+ Version: 1.0.0
4
+ Summary: Yandex Dialogs Developer API client — programmatic skill creation, draft management, OAuth Device Flow
5
+ Project-URL: Homepage, https://github.com/trudenboy/ya-dialogs-api
6
+ Project-URL: Repository, https://github.com/trudenboy/ya-dialogs-api
7
+ Project-URL: Issues, https://github.com/trudenboy/ya-dialogs-api/issues
8
+ Project-URL: Changelog, https://github.com/trudenboy/ya-dialogs-api/blob/main/CHANGELOG.md
9
+ Author: Mikhail Nevskiy
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Mikhail Nevskiy
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ License-File: NOTICE
33
+ Keywords: aiohttp,alice,api-client,async,dialogs,oauth,skill,yandex
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Framework :: AsyncIO
36
+ Classifier: Intended Audience :: Developers
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: OS Independent
39
+ Classifier: Programming Language :: Python :: 3 :: Only
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Programming Language :: Python :: 3.14
43
+ Classifier: Topic :: Internet :: WWW/HTTP
44
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
+ Classifier: Typing :: Typed
46
+ Requires-Python: >=3.12
47
+ Requires-Dist: aiohttp<4,>=3.10
48
+ Requires-Dist: ya-passport-auth>=1.3.0
49
+ Provides-Extra: dev
50
+ Requires-Dist: aioresponses>=0.7.6; extra == 'dev'
51
+ Requires-Dist: bandit[toml]>=1.7; extra == 'dev'
52
+ Requires-Dist: cyclonedx-bom>=4; extra == 'dev'
53
+ Requires-Dist: hypothesis>=6; extra == 'dev'
54
+ Requires-Dist: liccheck>=0.9; extra == 'dev'
55
+ Requires-Dist: mypy>=1.11; extra == 'dev'
56
+ Requires-Dist: pip-audit>=2.7; extra == 'dev'
57
+ Requires-Dist: pre-commit>=3.8; extra == 'dev'
58
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
59
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
60
+ Requires-Dist: pytest>=8; extra == 'dev'
61
+ Requires-Dist: ruff>=0.6; extra == 'dev'
62
+ Description-Content-Type: text/markdown
63
+
64
+ # ya-dialogs-api
65
+
66
+ > Async Yandex Dialogs Developer API client — programmatic skill creation, draft management, OAuth Device Flow.
67
+
68
+ [![CI](https://github.com/trudenboy/ya-dialogs-api/actions/workflows/ci.yml/badge.svg)](https://github.com/trudenboy/ya-dialogs-api/actions/workflows/ci.yml)
69
+ [![PyPI](https://img.shields.io/pypi/v/ya-dialogs-api)](https://pypi.org/project/ya-dialogs-api/)
70
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
71
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
72
+
73
+ ## What this is
74
+
75
+ A framework-agnostic Python library that drives the **Yandex Dialogs Developer
76
+ API** — the meta-API at `dialogs.yandex.ru/developer-api/v2/` used to
77
+ programmatically create and manage Alice skills (Smart Home and custom dialog
78
+ skills). Where every other Yandex Alice library on PyPI handles the *runtime*
79
+ side (incoming webhook requests from end users), this one handles the
80
+ *provisioning* side: sign in via Yandex Passport Device Flow, create a skill,
81
+ upload a logo, set the webhook backend URL, publish a draft, poll for
82
+ publication state.
83
+
84
+ It exists because Yandex doesn't publish a developer-API SDK and the only
85
+ known Python implementation lived inside the Music Assistant
86
+ `ma-provider-yandex-smarthome` plugin. This library is that code, extracted
87
+ and made generic.
88
+
89
+ ## Features
90
+
91
+ - **Full skill auto-creation pipeline** — Device Flow OAuth → CSRF/cookie
92
+ session → POST `/apps` → POST `/skills/{id}/draft` → publication polling →
93
+ callback URL extraction.
94
+ - **Two channel types** — `skill_type="smart_home"` for Yandex Smart Home
95
+ skills, `skill_type="dialog"` for Alice custom dialog (`aliceSkill`) skills.
96
+ - **Incremental state machine** — `SkillCreationArtifacts` snapshots progress
97
+ after every step. On transient failure, retry resumes from the last
98
+ completed step instead of restarting.
99
+ - **Framework-agnostic** — caller provides a `WebserverAdapter` Protocol
100
+ implementation for hosting the short-lived Device Code activation page.
101
+ Works with aiohttp, FastAPI, Starlette, or any ASGI/aiohttp-compatible
102
+ webserver.
103
+ - **Strictly typed** — `mypy --strict` clean, PEP 561 `py.typed` marker.
104
+ - **Security-aware** — `SecretStr` redacts tokens in repr/str/format/tracebacks
105
+ (re-exported from `ya-passport-auth`).
106
+
107
+ ## Installation
108
+
109
+ ```bash
110
+ pip install ya-dialogs-api
111
+ ```
112
+
113
+ ## Quick start
114
+
115
+ ```python
116
+ import asyncio
117
+ from ya_dialogs_api import (
118
+ SkillCreationArtifacts,
119
+ SkillCreationState,
120
+ WebserverAdapter,
121
+ auto_create_skill,
122
+ load_default_logo_bytes,
123
+ )
124
+
125
+ # 1. Implement WebserverAdapter against your HTTP framework.
126
+ # See docs for an aiohttp reference implementation.
127
+ my_webserver: WebserverAdapter = ...
128
+
129
+ # 2. Drive the pipeline. Persist artifacts between calls — the next
130
+ # invocation will resume from the last completed step.
131
+ async def main() -> None:
132
+ artifacts = SkillCreationArtifacts(state=SkillCreationState.PENDING)
133
+ result = await auto_create_skill(
134
+ webserver=my_webserver,
135
+ connection_type="direct",
136
+ skill_name="My Smart Home",
137
+ artifacts=artifacts,
138
+ cloud_instance_id="...",
139
+ direct_client_secret="...",
140
+ logo_bytes=load_default_logo_bytes(),
141
+ session_id="cfg-flow-1",
142
+ skill_type="smart_home",
143
+ )
144
+ if result.state == SkillCreationState.DONE:
145
+ print(f"Skill created: skill_id={result.skill_id}")
146
+ else:
147
+ print(f"Failed at step {result.state}: {result.last_error}")
148
+
149
+ asyncio.run(main())
150
+ ```
151
+
152
+ ## Status
153
+
154
+ **Beta.** The API is stable enough to depend on, but the underlying Yandex dev-
155
+ console endpoints are unofficial (reverse-engineered from DevTools traces) and
156
+ may break without notice. The library is actively maintained against the
157
+ current production endpoint behavior.
158
+
159
+ ## See also
160
+
161
+ - [`ya-passport-auth`](https://github.com/trudenboy/ya-passport-auth) — Yandex
162
+ Passport authentication library. Required runtime dependency for the OAuth
163
+ Device Flow used by this library.
164
+ - [`ma-provider-yandex-smarthome`](https://github.com/trudenboy/ma-provider-yandex-smarthome)
165
+ and [`ma-provider-yandex-alice`](https://github.com/trudenboy/ma-provider-yandex-alice)
166
+ — Music Assistant providers that consume this library.
167
+
168
+ ## License
169
+
170
+ [MIT](LICENSE)
@@ -0,0 +1,107 @@
1
+ # ya-dialogs-api
2
+
3
+ > Async Yandex Dialogs Developer API client — programmatic skill creation, draft management, OAuth Device Flow.
4
+
5
+ [![CI](https://github.com/trudenboy/ya-dialogs-api/actions/workflows/ci.yml/badge.svg)](https://github.com/trudenboy/ya-dialogs-api/actions/workflows/ci.yml)
6
+ [![PyPI](https://img.shields.io/pypi/v/ya-dialogs-api)](https://pypi.org/project/ya-dialogs-api/)
7
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
9
+
10
+ ## What this is
11
+
12
+ A framework-agnostic Python library that drives the **Yandex Dialogs Developer
13
+ API** — the meta-API at `dialogs.yandex.ru/developer-api/v2/` used to
14
+ programmatically create and manage Alice skills (Smart Home and custom dialog
15
+ skills). Where every other Yandex Alice library on PyPI handles the *runtime*
16
+ side (incoming webhook requests from end users), this one handles the
17
+ *provisioning* side: sign in via Yandex Passport Device Flow, create a skill,
18
+ upload a logo, set the webhook backend URL, publish a draft, poll for
19
+ publication state.
20
+
21
+ It exists because Yandex doesn't publish a developer-API SDK and the only
22
+ known Python implementation lived inside the Music Assistant
23
+ `ma-provider-yandex-smarthome` plugin. This library is that code, extracted
24
+ and made generic.
25
+
26
+ ## Features
27
+
28
+ - **Full skill auto-creation pipeline** — Device Flow OAuth → CSRF/cookie
29
+ session → POST `/apps` → POST `/skills/{id}/draft` → publication polling →
30
+ callback URL extraction.
31
+ - **Two channel types** — `skill_type="smart_home"` for Yandex Smart Home
32
+ skills, `skill_type="dialog"` for Alice custom dialog (`aliceSkill`) skills.
33
+ - **Incremental state machine** — `SkillCreationArtifacts` snapshots progress
34
+ after every step. On transient failure, retry resumes from the last
35
+ completed step instead of restarting.
36
+ - **Framework-agnostic** — caller provides a `WebserverAdapter` Protocol
37
+ implementation for hosting the short-lived Device Code activation page.
38
+ Works with aiohttp, FastAPI, Starlette, or any ASGI/aiohttp-compatible
39
+ webserver.
40
+ - **Strictly typed** — `mypy --strict` clean, PEP 561 `py.typed` marker.
41
+ - **Security-aware** — `SecretStr` redacts tokens in repr/str/format/tracebacks
42
+ (re-exported from `ya-passport-auth`).
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install ya-dialogs-api
48
+ ```
49
+
50
+ ## Quick start
51
+
52
+ ```python
53
+ import asyncio
54
+ from ya_dialogs_api import (
55
+ SkillCreationArtifacts,
56
+ SkillCreationState,
57
+ WebserverAdapter,
58
+ auto_create_skill,
59
+ load_default_logo_bytes,
60
+ )
61
+
62
+ # 1. Implement WebserverAdapter against your HTTP framework.
63
+ # See docs for an aiohttp reference implementation.
64
+ my_webserver: WebserverAdapter = ...
65
+
66
+ # 2. Drive the pipeline. Persist artifacts between calls — the next
67
+ # invocation will resume from the last completed step.
68
+ async def main() -> None:
69
+ artifacts = SkillCreationArtifacts(state=SkillCreationState.PENDING)
70
+ result = await auto_create_skill(
71
+ webserver=my_webserver,
72
+ connection_type="direct",
73
+ skill_name="My Smart Home",
74
+ artifacts=artifacts,
75
+ cloud_instance_id="...",
76
+ direct_client_secret="...",
77
+ logo_bytes=load_default_logo_bytes(),
78
+ session_id="cfg-flow-1",
79
+ skill_type="smart_home",
80
+ )
81
+ if result.state == SkillCreationState.DONE:
82
+ print(f"Skill created: skill_id={result.skill_id}")
83
+ else:
84
+ print(f"Failed at step {result.state}: {result.last_error}")
85
+
86
+ asyncio.run(main())
87
+ ```
88
+
89
+ ## Status
90
+
91
+ **Beta.** The API is stable enough to depend on, but the underlying Yandex dev-
92
+ console endpoints are unofficial (reverse-engineered from DevTools traces) and
93
+ may break without notice. The library is actively maintained against the
94
+ current production endpoint behavior.
95
+
96
+ ## See also
97
+
98
+ - [`ya-passport-auth`](https://github.com/trudenboy/ya-passport-auth) — Yandex
99
+ Passport authentication library. Required runtime dependency for the OAuth
100
+ Device Flow used by this library.
101
+ - [`ma-provider-yandex-smarthome`](https://github.com/trudenboy/ma-provider-yandex-smarthome)
102
+ and [`ma-provider-yandex-alice`](https://github.com/trudenboy/ma-provider-yandex-alice)
103
+ — Music Assistant providers that consume this library.
104
+
105
+ ## License
106
+
107
+ [MIT](LICENSE)
@@ -0,0 +1,50 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ If you discover a security issue, **please do not open a public issue.**
6
+
7
+ Instead, email the maintainer directly or use GitHub's private vulnerability
8
+ reporting feature at:
9
+ https://github.com/trudenboy/ya-dialogs-api/security/advisories/new
10
+
11
+ You will receive an acknowledgement within 72 hours and a resolution timeline
12
+ within 7 days.
13
+
14
+ ## Supported versions
15
+
16
+ | Version | Supported |
17
+ |---------|-----------|
18
+ | 1.0.x | Yes |
19
+
20
+ ## Threat model summary
21
+
22
+ This library is a relatively thin HTTP client over the Yandex Dialogs developer
23
+ API. The hot security perimeter (Yandex Passport credentials, OAuth tokens,
24
+ session cookies) is owned by `ya-passport-auth`, which has its own threat
25
+ model. The threats specific to this library are:
26
+
27
+ | # | Threat | Mitigation |
28
+ |---|--------|------------|
29
+ | D1 | Skill credentials leak via logs (skill_id is sensitive enough that an attacker who learns it can call dialogs.yandex.net/api/v1/skills/{id}/callback/state if they also have skill_token) | Library-side: never logs full credentials; only logs `step` + status code + first 200 chars of error body, which never contain skill_token |
30
+ | D2 | DoS via unbounded HTML response from dev-console | 2 MiB hard cap on developer page HTML (`_MAX_HTML_RESPONSE_BYTES`) |
31
+ | D3 | ReDoS on CSRF regex | Single explicit character class, non-greedy. The regex matches inside a 2 MiB cap |
32
+ | D4 | Spoofed dev-console responses (e.g. on a malicious proxy) | TLS verification is the caller's responsibility on the supplied `aiohttp.ClientSession` (this library does not own the session) |
33
+ | D5 | CSRF token reuse across attempts | `fetch_csrf` is called once per attempt; orchestrator does not cache the token across `auto_create_skill` calls |
34
+ | D6 | Pickled `SkillCreationArtifacts` carrying secrets | Artifacts dataclass is frozen but does not currently carry secrets — only IDs (skill_id, logo_id, oauth_app_id). The actual `skill_token` is owned by the caller and never enters the artifacts object |
35
+ | D7 | Supply-chain compromise via this library | Hash-pinned `uv.lock`, `pip-audit` in CI, Dependabot enabled, OpenSSF Scorecard published |
36
+ | D8 | Real Yandex tokens in test fixtures | All test data uses synthetic tokens (`csrf-token`, `test-secret`, `skill-id-123`); no production credentials in source tree |
37
+
38
+ For the security of the Passport authentication flow, OAuth Device Flow,
39
+ SecretStr handling, host allow-list, and TLS verification, see the threat model
40
+ of [`ya-passport-auth`](https://github.com/trudenboy/ya-passport-auth) — this
41
+ library uses it as a runtime dependency.
42
+
43
+ ## Out of scope
44
+
45
+ - Host compromise / memory scraping
46
+ - Side-channel timing attacks
47
+ - Encrypted at-rest storage of artifacts (caller responsibility)
48
+ - The undocumented Yandex API itself — if Yandex changes endpoint shapes or
49
+ auth requirements, this library's release cadence is the mitigation
50
+ - CAPTCHA / anti-bot bypass
@@ -0,0 +1 @@
1
+ 1.0.0