sentry-jaga 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.
Files changed (32) hide show
  1. sentry_jaga-1.0.0/.gitignore +363 -0
  2. sentry_jaga-1.0.0/.pre-commit-config.yaml +15 -0
  3. sentry_jaga-1.0.0/CHANGELOG.md +100 -0
  4. sentry_jaga-1.0.0/CODE_OF_CONDUCT.md +130 -0
  5. sentry_jaga-1.0.0/CONTRIBUTING.md +242 -0
  6. sentry_jaga-1.0.0/LICENSE +21 -0
  7. sentry_jaga-1.0.0/PKG-INFO +328 -0
  8. sentry_jaga-1.0.0/README.md +302 -0
  9. sentry_jaga-1.0.0/SECURITY.md +68 -0
  10. sentry_jaga-1.0.0/pyproject.toml +145 -0
  11. sentry_jaga-1.0.0/src/sentry_jaga/__init__.py +8 -0
  12. sentry_jaga-1.0.0/src/sentry_jaga/apps.py +38 -0
  13. sentry_jaga-1.0.0/src/sentry_jaga/client/__init__.py +1 -0
  14. sentry_jaga-1.0.0/src/sentry_jaga/client/api.py +511 -0
  15. sentry_jaga-1.0.0/src/sentry_jaga/client/auth.py +91 -0
  16. sentry_jaga-1.0.0/src/sentry_jaga/client/exceptions.py +89 -0
  17. sentry_jaga-1.0.0/src/sentry_jaga/client/models.py +172 -0
  18. sentry_jaga-1.0.0/src/sentry_jaga/descriptions.py +49 -0
  19. sentry_jaga-1.0.0/src/sentry_jaga/fields.py +292 -0
  20. sentry_jaga-1.0.0/src/sentry_jaga/integration.py +98 -0
  21. sentry_jaga-1.0.0/src/sentry_jaga/issue_config.py +684 -0
  22. sentry_jaga-1.0.0/src/sentry_jaga/issues.py +307 -0
  23. sentry_jaga-1.0.0/src/sentry_jaga/metadata.py +43 -0
  24. sentry_jaga-1.0.0/src/sentry_jaga/notify_action.py +39 -0
  25. sentry_jaga-1.0.0/src/sentry_jaga/pipeline.py +103 -0
  26. sentry_jaga-1.0.0/src/sentry_jaga/py.typed +0 -0
  27. sentry_jaga-1.0.0/src/sentry_jaga/search.py +104 -0
  28. sentry_jaga-1.0.0/src/sentry_jaga/sync.py +297 -0
  29. sentry_jaga-1.0.0/src/sentry_jaga/templates/sentry_jaga/config.html +61 -0
  30. sentry_jaga-1.0.0/src/sentry_jaga/urlconf.py +21 -0
  31. sentry_jaga-1.0.0/src/sentry_jaga/urls.py +23 -0
  32. sentry_jaga-1.0.0/uv.lock +643 -0
@@ -0,0 +1,363 @@
1
+ ### JetBrains template
2
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
3
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
4
+
5
+ # User-specific stuff
6
+ .idea/**/workspace.xml
7
+ .idea/**/tasks.xml
8
+ .idea/**/usage.statistics.xml
9
+ .idea/**/dictionaries
10
+ .idea/**/shelf
11
+
12
+ # AWS User-specific
13
+ .idea/**/aws.xml
14
+
15
+ # Generated files
16
+ .idea/**/contentModel.xml
17
+
18
+ # Sensitive or high-churn files
19
+ .idea/**/dataSources/
20
+ .idea/**/dataSources.ids
21
+ .idea/**/dataSources.local.xml
22
+ .idea/**/sqlDataSources.xml
23
+ .idea/**/dynamic.xml
24
+ .idea/**/uiDesigner.xml
25
+ .idea/**/dbnavigator.xml
26
+
27
+ # Gradle
28
+ .idea/**/gradle.xml
29
+ .idea/**/libraries
30
+
31
+ # Gradle and Maven with auto-import
32
+ # When using Gradle or Maven with auto-import, you should exclude module files,
33
+ # since they will be recreated, and may cause churn. Uncomment if using
34
+ # auto-import.
35
+ # .idea/artifacts
36
+ # .idea/compiler.xml
37
+ # .idea/jarRepositories.xml
38
+ # .idea/modules.xml
39
+ # .idea/*.iml
40
+ # .idea/modules
41
+ # *.iml
42
+ # *.ipr
43
+
44
+ # CMake
45
+ cmake-build-*/
46
+
47
+ # Mongo Explorer plugin
48
+ .idea/**/mongoSettings.xml
49
+
50
+ # File-based project format
51
+ *.iws
52
+
53
+ # IntelliJ
54
+ out/
55
+
56
+ # mpeltonen/sbt-idea plugin
57
+ .idea_modules/
58
+
59
+ # JIRA plugin
60
+ atlassian-ide-plugin.xml
61
+
62
+ # Cursive Clojure plugin
63
+ .idea/replstate.xml
64
+
65
+ # SonarLint plugin
66
+ .idea/sonarlint/
67
+
68
+ # Crashlytics plugin (for Android Studio and IntelliJ)
69
+ com_crashlytics_export_strings.xml
70
+ crashlytics.properties
71
+ crashlytics-build.properties
72
+ fabric.properties
73
+
74
+ # Editor-based Rest Client
75
+ .idea/httpRequests
76
+
77
+ # Android studio 3.1+ serialized cache file
78
+ .idea/caches/build_file_checksums.ser
79
+
80
+ ### VirtualEnv template
81
+ # Virtualenv
82
+ # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
83
+ .Python
84
+ [Bb]in
85
+ [Ii]nclude
86
+ [Ll]ib
87
+ [Ll]ib64
88
+ [Ll]ocal
89
+ [Ss]cripts
90
+ # ...but not our own scripts/ directory (the pattern above targets Windows venvs).
91
+ !/scripts/
92
+
93
+ # Planning artefacts, not documentation: they describe what was intended, not what was built.
94
+ /docs/superpowers/
95
+
96
+ # The release runbook is the maintainer's own note, not part of the published project.
97
+ /docs/release.md
98
+
99
+ # Editor and rebase leftovers. The wheel target ships everything under `src/sentry_jaga`, so a
100
+ # `.bak` next to a module would be published to PyPI inside it.
101
+ *.bak
102
+ *.mbak
103
+ *.orig
104
+ *.rej
105
+
106
+ # Throwaway probe scripts: they talk to a real Jaga instance with real credentials. What they found
107
+ # lives in the docstrings of the code they justify (`JagaClient.transition_task`, `attach_file`,
108
+ # `get_or_create_label`, `fields.injected_attributes`). Keep yours locally.
109
+ /scripts/probe_*.py
110
+ pyvenv.cfg
111
+ .venv
112
+ pip-selfcheck.json
113
+
114
+ ### Linux template
115
+ *~
116
+
117
+ # temporary files which can be created if a process still has a handle open of a deleted file
118
+ .fuse_hidden*
119
+
120
+ # KDE directory preferences
121
+ .directory
122
+
123
+ # Linux trash folder which might appear on any partition or disk
124
+ .Trash-*
125
+
126
+ # .nfs files are created when an open file is removed but is still being accessed
127
+ .nfs*
128
+
129
+ ### Windows template
130
+ # Windows thumbnail cache files
131
+ Thumbs.db
132
+ Thumbs.db:encryptable
133
+ ehthumbs.db
134
+ ehthumbs_vista.db
135
+
136
+ # Dump file
137
+ *.stackdump
138
+
139
+ # Folder config file
140
+ [Dd]esktop.ini
141
+
142
+ # Recycle Bin used on file shares
143
+ $RECYCLE.BIN/
144
+
145
+ # Windows Installer files
146
+ *.cab
147
+ *.msi
148
+ *.msix
149
+ *.msm
150
+ *.msp
151
+
152
+ # Windows shortcuts
153
+ *.lnk
154
+
155
+ ### macOS template
156
+ # General
157
+ .DS_Store
158
+ .AppleDouble
159
+ .LSOverride
160
+
161
+ # Icon must end with two \r
162
+ Icon
163
+
164
+ # Thumbnails
165
+ ._*
166
+
167
+ # Files that might appear in the root of a volume
168
+ .DocumentRevisions-V100
169
+ .fseventsd
170
+ .Spotlight-V100
171
+ .TemporaryItems
172
+ .Trashes
173
+ .VolumeIcon.icns
174
+ .com.apple.timemachine.donotpresent
175
+
176
+ # Directories potentially created on remote AFP share
177
+ .AppleDB
178
+ .AppleDesktop
179
+ Network Trash Folder
180
+ Temporary Items
181
+ .apdisk
182
+
183
+ ### Python template
184
+ # Byte-compiled / optimized / DLL files
185
+ __pycache__/
186
+ *.py[cod]
187
+ *$py.class
188
+
189
+ # C extensions
190
+ *.so
191
+
192
+ # Distribution / packaging
193
+ build/
194
+ develop-eggs/
195
+ dist/
196
+ downloads/
197
+ eggs/
198
+ .eggs/
199
+ lib/
200
+ lib64/
201
+ parts/
202
+ sdist/
203
+ var/
204
+ wheels/
205
+ share/python-wheels/
206
+ *.egg-info/
207
+ .installed.cfg
208
+ *.egg
209
+ MANIFEST
210
+
211
+ # PyInstaller
212
+ # Usually these files are written by a python script from a template
213
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
214
+ *.manifest
215
+ *.spec
216
+
217
+ # Installer logs
218
+ pip-log.txt
219
+ pip-delete-this-directory.txt
220
+
221
+ # Unit test / coverage reports
222
+ htmlcov/
223
+ .tox/
224
+ .nox/
225
+ .coverage
226
+ .coverage.*
227
+ .cache
228
+ nosetests.xml
229
+ coverage.xml
230
+ *.cover
231
+ *.py,cover
232
+ .hypothesis/
233
+ .pytest_cache/
234
+ cover/
235
+
236
+ # Translations
237
+ *.mo
238
+ *.pot
239
+
240
+ # Django stuff:
241
+ *.log
242
+ local_settings.py
243
+ db.sqlite3
244
+ db.sqlite3-journal
245
+
246
+ # Flask stuff:
247
+ instance/
248
+ .webassets-cache
249
+
250
+ # Scrapy stuff:
251
+ .scrapy
252
+
253
+ # Sphinx documentation
254
+ docs/_build/
255
+
256
+ # PyBuilder
257
+ .pybuilder/
258
+ target/
259
+
260
+ # Jupyter Notebook
261
+ .ipynb_checkpoints
262
+
263
+ # IPython
264
+ profile_default/
265
+ ipython_config.py
266
+
267
+ # pyenv
268
+ # For a library or package, you might want to ignore these files since the code is
269
+ # intended to run in multiple environments; otherwise, check them in:
270
+ # .python-version
271
+
272
+ # pipenv
273
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
274
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
275
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
276
+ # install all needed dependencies.
277
+ #Pipfile.lock
278
+
279
+ # poetry
280
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
281
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
282
+ # commonly ignored for libraries.
283
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
284
+ #poetry.lock
285
+
286
+ # pdm
287
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
288
+ #pdm.lock
289
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
290
+ # in version control.
291
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
292
+ .pdm.toml
293
+ .pdm-python
294
+ .pdm-build/
295
+
296
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
297
+ __pypackages__/
298
+
299
+ # Celery stuff
300
+ celerybeat-schedule
301
+ celerybeat.pid
302
+
303
+ # SageMath parsed files
304
+ *.sage.py
305
+
306
+ # Environments
307
+ .env
308
+ env/
309
+ venv/
310
+ ENV/
311
+ env.bak/
312
+ venv.bak/
313
+
314
+ # Spyder project settings
315
+ .spyderproject
316
+ .spyproject
317
+
318
+ # Rope project settings
319
+ .ropeproject
320
+
321
+ # mkdocs documentation
322
+ /site
323
+
324
+ # mypy
325
+ .mypy_cache/
326
+ .dmypy.json
327
+ dmypy.json
328
+
329
+ # Pyre type checker
330
+ .pyre/
331
+
332
+ # pytype static type analyzer
333
+ .pytype/
334
+
335
+ # Cython debug symbols
336
+ cython_debug/
337
+
338
+ # PyCharm
339
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
340
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
341
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
342
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
343
+ #.idea/
344
+
345
+ # ruff
346
+ .ruff_cache/
347
+
348
+
349
+ ### Project
350
+ # IDE clutter (the template above only covers it partially — cover it entirely)
351
+ .idea/
352
+
353
+ # The internal Jaga API spec (Rostelecom): it goes neither into the OSS repo nor a release
354
+ jaga-openapi.json
355
+
356
+ # Scratch space of the SDD agents
357
+ .superpowers/
358
+
359
+ # Sentry sources used for type checking (cloned locally / in CI)
360
+ .sentry-src/
361
+
362
+ # Scratch worktrees of subagents
363
+ .claude/
@@ -0,0 +1,15 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: https://github.com/pre-commit/pre-commit-hooks
9
+ rev: v4.6.0
10
+ hooks:
11
+ - id: end-of-file-fixer
12
+ - id: trailing-whitespace
13
+ - id: check-toml
14
+ - id: check-yaml
15
+ - id: check-merge-conflict
@@ -0,0 +1,100 @@
1
+ # Changelog
2
+
3
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
+ and this project adheres to [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [1.0.0] - 2026-07-14
9
+
10
+ The first public release. Everything below was verified against a live Jaga instance and a real
11
+ self-hosted Sentry 26.3.1, not against the API spec, which turned out to be wrong about six separate
12
+ things.
13
+
14
+ ### Fixed
15
+
16
+ - **The "Assignees" select was always empty, and said nothing about it.** It was filled from the
17
+ endpoint the spec documents for exactly this — `GET /v1/project/getUserProfileDtos/{projectId}` —
18
+ which on a live instance answers `200 []` for *every* space, including one the asking account
19
+ owns. It does not fail; it silently reports that nobody is there.
20
+
21
+ The members now come from the space's user-role matrix
22
+ (`GET /v1/team/userRoles/applications/JAGA/projects/{projectId}`). `applicationMnemo` is a required
23
+ path segment the spec never gives a value for; `JAGA` is the one a live instance accepts. The old
24
+ endpoint is kept only as a fallback for when the matrix itself errors — an *empty* matrix is taken
25
+ at face value, since a space really can have no members.
26
+
27
+ ### Added
28
+
29
+ - **Assignee sync (`Sync assignment to Jaga`, off by default).** Assigning a Sentry issue puts the
30
+ person on the linked Jaga task; unassigning takes them off. Matched by email — the user's primary
31
+ address first, then their verified ones. A Sentry user Jaga has never heard of leaves the task
32
+ exactly as it was, and is never turned into an unassignment. Assigning an issue to a Sentry
33
+ **team** does nothing in Jaga. Off by default because it names a real person in another system.
34
+
35
+ The assignee turned out **not** to be the "task role" the spec advertises: the documented
36
+ `PUT /v1/taskRole/task/{taskId}/executor` does not exist on a live instance (404, `No static
37
+ resource ...`). It is an ordinary EAV attribute, written with `PATCH /v1/task/{taskId}`, and
38
+ writing it fills the task's `executors` — the attribute *is* what Jaga's UI calls the executor.
39
+ - **Linking searches every space at once** (`POST /v1/globalSearch/findTaskList`). Jaga's per-space
40
+ search demands a `projectId`, which is why the link form used to make you pick a space first.
41
+ - **The Sentry event can be attached to the task** as a JSON file (`Attach the Sentry event to the
42
+ task`, **off by default**). It is the event as `Event.as_dict()` serves it, so it carries personal
43
+ data — the user's email, request headers and body — which is why an admin has to turn it on
44
+ deliberately. A failed upload is logged and swallowed: the task is already created by then.
45
+
46
+ The attachment is run through **Sentry's own data scrubber**
47
+ (`sentry.relay.datascrubbing.scrub_data`) before it is uploaded, so it honours every privacy
48
+ setting of the project and the organization: IP scrubbing, additional sensitive fields, the default
49
+ rules, and the advanced PII rules. Because the rules are applied to the *stored* event rather than
50
+ on ingest, this is stricter than Sentry's own "JSON" view. A scrub that fails means no attachment
51
+ at all — never an unscrubbed one.
52
+
53
+ It does **not** apply to tasks filed by an alert rule: the rule modal renders the create form with
54
+ no issue behind it and saves the result into the rule, so the hidden field that carries the issue
55
+ is not emitted there — otherwise one frozen group id would attach the event of a single long-dead
56
+ issue to every task the rule ever filed.
57
+ - **Every task created from Sentry is labelled** (`sentry` by default, configurable per
58
+ organization; an empty setting turns it off). The label is created on first use
59
+ (`POST /v1/labels/list` is a get-or-create) and is *added* to the labels picked in the create form
60
+ rather than replacing them. A task type without a label attribute is filed without a label.
61
+ - The status sync now **moves the linked Jaga task**, instead of only commenting on it. The target is
62
+ configured per organization as a status *category* (Done / In progress / To do), and the concrete
63
+ status is resolved per task from the ones its own workflow can reach — Jaga keeps a separate copy
64
+ of every status per workflow (~90k of them on a real instance), so a status id cannot be mapped
65
+ directly.
66
+ - Organization settings for the sync: the categories to move the task to when an issue is resolved
67
+ and when it regresses, and whether to comment in addition to moving.
68
+ - **The create form remembers the space and task type** last filed into, per Sentry project. A
69
+ remembered space that Jaga no longer offers the service account falls back to the first available
70
+ one instead of breaking the form.
71
+ - **Sentry notes can be synced to Jaga as comments** (`Sync Sentry comments to Jaga`, **off by
72
+ default**). A note is posted as `<Author> wrote:` followed by its quoted text, and editing the note
73
+ rewrites the comment it created rather than adding a second one. Off by default because a Sentry
74
+ note is internal discussion and the Jaga task may have a wider audience.
75
+ - **Linking an existing task now comments on it**, with a link back to the Sentry issue. The text is
76
+ pre-filled in the link form and is editable: clearing the box posts nothing, which is why this
77
+ needs no organization-wide setting.
78
+
79
+ ### Changed
80
+
81
+ - **The link form no longer asks for a space** (the search is global now), and its suggestions read
82
+ `code — title`: the global search returns a found task's space as `null`, and fetching it per
83
+ suggestion, per keystroke, is not worth the round trips. The search endpoint
84
+ (`/extensions/jaga/search/…`) no longer takes a `project` parameter.
85
+ - The project is now fully in English: documentation, code comments and user-facing strings.
86
+ - The tests of the Sentry layer now run against a real Sentry 26.3.1, in Sentry's own environment
87
+ (see CONTRIBUTING.md). The `sentry` dependency group is gone: it could never have worked, as Sentry
88
+ is not installable as a package.
89
+
90
+ ### The rest of what 1.0.0 contains
91
+
92
+ - Creating Jaga tasks from a Sentry issue, with the attributes of the chosen task type rendered
93
+ dynamically (Jaga's EAV model).
94
+ - Linking an existing Jaga task to a Sentry issue.
95
+ - Installation through a form: the Jaga URL plus a service account, with the credentials checked
96
+ before the integration is created.
97
+ - Ticket Rules: an alert rule can file a Jaga task by itself.
98
+
99
+ [Unreleased]: https://github.com/happykust/sentry-jaga/compare/v1.0.0...HEAD
100
+ [1.0.0]: https://github.com/happykust/sentry-jaga/releases/tag/v1.0.0
@@ -0,0 +1,130 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ - Demonstrating empathy and kindness toward other people.
21
+ - Being respectful of differing opinions, viewpoints, and experiences.
22
+ - Giving and gracefully accepting constructive feedback.
23
+ - Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience.
25
+ - Focusing on what is best not just for us as individuals, but for the overall
26
+ community.
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ - The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind.
32
+ - Trolling, insulting or derogatory comments, and personal or political attacks.
33
+ - Public or private harassment.
34
+ - Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission.
36
+ - Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting.
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official email address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ **me@happykust.dev**.
64
+
65
+ All complaints will be reviewed and investigated promptly and fairly.
66
+
67
+ All community leaders are obligated to respect the privacy and security of the
68
+ reporter of any incident.
69
+
70
+ ## Enforcement Guidelines
71
+
72
+ Community leaders will follow these Community Impact Guidelines in determining
73
+ the consequences for any action they deem in violation of this Code of Conduct:
74
+
75
+ ### 1. Correction
76
+
77
+ **Community Impact**: Use of inappropriate language or other behavior deemed
78
+ unprofessional or unwelcome in the community.
79
+
80
+ **Consequence**: A private, written warning from community leaders, providing
81
+ clarity around the nature of the violation and an explanation of why the
82
+ behavior was inappropriate. A public apology may be requested.
83
+
84
+ ### 2. Warning
85
+
86
+ **Community Impact**: A violation through a single incident or series of
87
+ actions.
88
+
89
+ **Consequence**: A warning with consequences for continued behavior. No
90
+ interaction with the people involved, including unsolicited interaction with
91
+ those enforcing the Code of Conduct, for a specified period of time. This
92
+ includes avoiding interactions in community spaces as well as external channels
93
+ like social media. Violating these terms may lead to a temporary or permanent
94
+ ban.
95
+
96
+ ### 3. Temporary Ban
97
+
98
+ **Community Impact**: A serious violation of community standards, including
99
+ sustained inappropriate behavior.
100
+
101
+ **Consequence**: A temporary ban from any sort of interaction or public
102
+ communication with the community for a specified period of time. No public or
103
+ private interaction with the people involved, including unsolicited interaction
104
+ with those enforcing the Code of Conduct, is allowed during this period.
105
+ Violating these terms may lead to a permanent ban.
106
+
107
+ ### 4. Permanent Ban
108
+
109
+ **Community Impact**: Demonstrating a pattern of violation of community
110
+ standards, including sustained inappropriate behavior, harassment of an
111
+ individual, or aggression toward or disparagement of classes of individuals.
112
+
113
+ **Consequence**: A permanent ban from any sort of public interaction within the
114
+ community.
115
+
116
+ ## Attribution
117
+
118
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119
+ version 2.1, available at
120
+ https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
121
+
122
+ Community Impact Guidelines were inspired by
123
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124
+
125
+ [homepage]: https://www.contributor-covenant.org
126
+ [Mozilla CoC]: https://github.com/mozilla/diversity
127
+
128
+ For answers to common questions about this code of conduct, see the FAQ at
129
+ https://www.contributor-covenant.org/faq. Translations are available at
130
+ https://www.contributor-covenant.org/translations.