kd-cli 2.9.0__tar.gz → 2.9.1__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 (86) hide show
  1. {kd_cli-2.9.0/kd_cli.egg-info → kd_cli-2.9.1}/PKG-INFO +1 -1
  2. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/CHANGELOG.md +16 -0
  3. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/error-messages.yaml +61 -0
  4. {kd_cli-2.9.0 → kd_cli-2.9.1/kd_cli.egg-info}/PKG-INFO +1 -1
  5. {kd_cli-2.9.0 → kd_cli-2.9.1}/pyproject.toml +1 -1
  6. {kd_cli-2.9.0 → kd_cli-2.9.1}/LICENSE +0 -0
  7. {kd_cli-2.9.0 → kd_cli-2.9.1}/MANIFEST.in +0 -0
  8. {kd_cli-2.9.0 → kd_cli-2.9.1}/README.md +0 -0
  9. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/__init__.py +0 -0
  10. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/__init__.py +0 -0
  11. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/articles.py +0 -0
  12. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/http.py +0 -0
  13. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/hub.py +0 -0
  14. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/saved_queries.py +0 -0
  15. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/tags.py +0 -0
  16. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/api/youtrack.py +0 -0
  17. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/article_marker.py +0 -0
  18. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/auth.py +0 -0
  19. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cache.py +0 -0
  20. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/__init__.py +0 -0
  21. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/__init__.py +0 -0
  22. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/command_base.py +0 -0
  23. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/command_parser.py +0 -0
  24. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/confirm.py +0 -0
  25. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/namespaces.py +0 -0
  26. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/core/option_registry.py +0 -0
  27. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/input.py +0 -0
  28. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/main.py +0 -0
  29. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/__init__.py +0 -0
  30. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/alias/__init__.py +0 -0
  31. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/article/__init__.py +0 -0
  32. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/cache/__init__.py +0 -0
  33. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/init.py +0 -0
  34. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/issue/__init__.py +0 -0
  35. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/primer/__init__.py +0 -0
  36. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/project/__init__.py +0 -0
  37. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/query/__init__.py +0 -0
  38. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/release_notes.py +0 -0
  39. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/search/__init__.py +0 -0
  40. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/system/__init__.py +0 -0
  41. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/tag/__init__.py +0 -0
  42. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/time/__init__.py +0 -0
  43. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/namespaces/user/__init__.py +0 -0
  44. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/output.py +0 -0
  45. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/cli/tree.py +0 -0
  46. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/client.py +0 -0
  47. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/config.py +0 -0
  48. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/config_read.py +0 -0
  49. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/config_schema.py +0 -0
  50. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/connection.py +0 -0
  51. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/debug.py +0 -0
  52. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/exceptions.py +0 -0
  53. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/history.py +0 -0
  54. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/locking.py +0 -0
  55. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/__init__.py +0 -0
  56. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/article.py +0 -0
  57. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/assist.py +0 -0
  58. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/attachment.py +0 -0
  59. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/comment.py +0 -0
  60. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/common.py +0 -0
  61. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/issue.py +0 -0
  62. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/project.py +0 -0
  63. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/saved_query.py +0 -0
  64. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/search.py +0 -0
  65. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/tag.py +0 -0
  66. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/tag_entities.py +0 -0
  67. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/user.py +0 -0
  68. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/models/work_item.py +0 -0
  69. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/operating_guide.py +0 -0
  70. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/primer.py +0 -0
  71. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/query_parser.py +0 -0
  72. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/release_notes.py +0 -0
  73. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/__init__.py +0 -0
  74. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/command-synonyms.yaml +0 -0
  75. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/config-template.yaml +0 -0
  76. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/operating-guide.md +0 -0
  77. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/primers/__init__.py +0 -0
  78. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/primers/hitl.yaml +0 -0
  79. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/resources/sdlc-doctrine.md +0 -0
  80. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd/sdlc.py +0 -0
  81. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd_cli.egg-info/SOURCES.txt +0 -0
  82. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd_cli.egg-info/dependency_links.txt +0 -0
  83. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd_cli.egg-info/entry_points.txt +0 -0
  84. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd_cli.egg-info/requires.txt +0 -0
  85. {kd_cli-2.9.0 → kd_cli-2.9.1}/kd_cli.egg-info/top_level.txt +0 -0
  86. {kd_cli-2.9.0 → kd_cli-2.9.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kd-cli
3
- Version: 2.9.0
3
+ Version: 2.9.1
4
4
  Summary: Knowledge Dispatcher for issue trackers and knowledge bases
5
5
  Author: Sergiy Gladkyy
6
6
  License-Expression: MIT
@@ -4,6 +4,22 @@ All notable changes to kd-cli are recorded here. The project follows [Semantic V
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.9.1] — 2026-05-12
8
+
9
+ ### Fixed
10
+ - `/tag add` and `/tag remove` no longer report "Article <id> not found"
11
+ when the upstream denies tag mutation. A 403 on
12
+ `DELETE /<articles|issues>/{id}/tags/{tag_id}` now surfaces as
13
+ "Tag remove denied for <article|issue> {id} (tag {tag_id})" with a
14
+ hint about tag ownership / `updateableBy` sharing; the 403 on
15
+ `POST /<articles|issues>/{id}/tags` surfaces as "Tag attach denied
16
+ for <article|issue> {id}". A 404 on the DELETE path now names the
17
+ tag attachment ("Tag {tag_id} was not found on <article|issue>
18
+ {id}") instead of falling through to the catch-all article/issue
19
+ 404 rule. The resolver pre-flight (KDCLI-198) already covers
20
+ parent-missing and not-attached cases at the SDK boundary; this
21
+ closes the residual HTTP-status surface (KDCLI-197).
22
+
7
23
  ## [2.9.0] — 2026-05-12
8
24
 
9
25
  ### Changed
@@ -29,6 +29,57 @@
29
29
  Time tracking may not be enabled for this project.
30
30
  Enable it in YouTrack: project Settings → Time Tracking.
31
31
 
32
+ # --- Tag mutation 403 (articles, issues) ---
33
+ # DELETE carries a tag_id segment; POST does not (tag id is in the body).
34
+ # YouTrack's stock body for the tag-mutation permission check is
35
+ # "Can't tag issue" on both article and issue endpoints. The body
36
+ # pattern is load-bearing: a 403 on these paths can also come from
37
+ # parent-entity permission denial (token can't read the article/issue
38
+ # at all), and that has nothing to do with tag ownership. Without the
39
+ # pattern guard, those unrelated 403s would be misdescribed as an
40
+ # updateableBy gap. The rules below only fire when the body actually
41
+ # carries the tag-mutation denial.
42
+
43
+ - status: 403
44
+ path: '/articles/(?P<id>[^/]+)/tags/(?P<tag_id>[^/]+)$'
45
+ pattern: "(?i)can.t tag issue"
46
+ message: 'Tag remove denied for article {id} (tag {tag_id})'
47
+ suggestion: >-
48
+ YouTrack denied removing this tag. The tag's owner has not shared
49
+ mutation rights with you (its `updateableBy` group does not include
50
+ the caller). Either ask the tag owner to widen `updateableBy`, or
51
+ reassign the tag's `owner` to a shared account.
52
+
53
+ - status: 403
54
+ path: '/issues/(?P<id>[^/]+)/tags/(?P<tag_id>[^/]+)$'
55
+ pattern: "(?i)can.t tag issue"
56
+ message: 'Tag remove denied for issue {id} (tag {tag_id})'
57
+ suggestion: >-
58
+ YouTrack denied removing this tag. The tag's owner has not shared
59
+ mutation rights with you (its `updateableBy` group does not include
60
+ the caller). Either ask the tag owner to widen `updateableBy`, or
61
+ reassign the tag's `owner` to a shared account.
62
+
63
+ - status: 403
64
+ path: '/articles/(?P<id>[^/]+)/tags$'
65
+ pattern: "(?i)can.t tag issue"
66
+ message: 'Tag attach denied for article {id}'
67
+ suggestion: >-
68
+ YouTrack denied attaching this tag. The tag's owner has not shared
69
+ mutation rights with you (its `updateableBy` group does not include
70
+ the caller). Either ask the tag owner to widen `updateableBy`, or
71
+ reassign the tag's `owner` to a shared account.
72
+
73
+ - status: 403
74
+ path: '/issues/(?P<id>[^/]+)/tags$'
75
+ pattern: "(?i)can.t tag issue"
76
+ message: 'Tag attach denied for issue {id}'
77
+ suggestion: >-
78
+ YouTrack denied attaching this tag. The tag's owner has not shared
79
+ mutation rights with you (its `updateableBy` group does not include
80
+ the caller). Either ask the tag owner to widen `updateableBy`, or
81
+ reassign the tag's `owner` to a shared account.
82
+
32
83
  # --- Sub-resource 404s (issues) ---
33
84
 
34
85
  - status: 404
@@ -46,6 +97,11 @@
46
97
  message: 'Comment {id} not found'
47
98
  suggestion: 'Show the parent issue to list its comments.'
48
99
 
100
+ - status: 404
101
+ path: '/issues/(?P<id>[^/]+)/tags/(?P<tag_id>[^/]+)$'
102
+ message: 'Tag {tag_id} was not found on issue {id}'
103
+ suggestion: 'List currently attached tags with: kd /issue show <ISSUE> -o yaml.'
104
+
49
105
  # --- Sub-resource 404s (articles) ---
50
106
 
51
107
  - status: 404
@@ -58,6 +114,11 @@
58
114
  message: 'Comment {id} not found'
59
115
  suggestion: 'List comments with: kd /article comment list <ARTICLE>.'
60
116
 
117
+ - status: 404
118
+ path: '/articles/(?P<id>[^/]+)/tags/(?P<tag_id>[^/]+)$'
119
+ message: 'Tag {tag_id} was not found on article {id}'
120
+ suggestion: 'List currently attached tags with: kd /article show <ARTICLE> -o yaml.'
121
+
61
122
  # --- Top-level 404s ---
62
123
 
63
124
  - status: 404
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kd-cli
3
- Version: 2.9.0
3
+ Version: 2.9.1
4
4
  Summary: Knowledge Dispatcher for issue trackers and knowledge bases
5
5
  Author: Sergiy Gladkyy
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kd-cli"
7
- version = "2.9.0"
7
+ version = "2.9.1"
8
8
  description = "Knowledge Dispatcher for issue trackers and knowledge bases"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes