spanguard 0.1.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 (62) hide show
  1. spanguard-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +87 -0
  2. spanguard-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. spanguard-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +59 -0
  4. spanguard-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  5. spanguard-0.1.0/.github/workflows/ci.yml +22 -0
  6. spanguard-0.1.0/.github/workflows/docs.yml +32 -0
  7. spanguard-0.1.0/.github/workflows/publish.yml +16 -0
  8. spanguard-0.1.0/.gitignore +52 -0
  9. spanguard-0.1.0/.gitleaks.toml +13 -0
  10. spanguard-0.1.0/CHANGELOG.md +90 -0
  11. spanguard-0.1.0/CITATION.cff +22 -0
  12. spanguard-0.1.0/CODE_OF_CONDUCT.md +142 -0
  13. spanguard-0.1.0/CONTRIBUTING.md +163 -0
  14. spanguard-0.1.0/LICENSE +21 -0
  15. spanguard-0.1.0/PKG-INFO +235 -0
  16. spanguard-0.1.0/README.md +206 -0
  17. spanguard-0.1.0/SECURITY.md +115 -0
  18. spanguard-0.1.0/benchmarks/throughput.py +129 -0
  19. spanguard-0.1.0/docs/PUBLISH-CHECKLIST.md +96 -0
  20. spanguard-0.1.0/docs/api.md +78 -0
  21. spanguard-0.1.0/docs/assets/logo.svg +12 -0
  22. spanguard-0.1.0/docs/cli.md +112 -0
  23. spanguard-0.1.0/docs/css/extra.css +56 -0
  24. spanguard-0.1.0/docs/index.md +135 -0
  25. spanguard-0.1.0/docs/known-limitations.md +122 -0
  26. spanguard-0.1.0/docs/quickstart.md +110 -0
  27. spanguard-0.1.0/docs/recognizers.md +89 -0
  28. spanguard-0.1.0/docs/streaming.md +105 -0
  29. spanguard-0.1.0/mkdocs.yml +111 -0
  30. spanguard-0.1.0/pyproject.toml +67 -0
  31. spanguard-0.1.0/src/spanguard/__init__.py +21 -0
  32. spanguard-0.1.0/src/spanguard/_keys.py +29 -0
  33. spanguard-0.1.0/src/spanguard/_overlap.py +53 -0
  34. spanguard-0.1.0/src/spanguard/_transform.py +54 -0
  35. spanguard-0.1.0/src/spanguard/cli.py +145 -0
  36. spanguard-0.1.0/src/spanguard/policy.py +35 -0
  37. spanguard-0.1.0/src/spanguard/py.typed +0 -0
  38. spanguard-0.1.0/src/spanguard/recognizers/__init__.py +8 -0
  39. spanguard-0.1.0/src/spanguard/recognizers/base.py +28 -0
  40. spanguard-0.1.0/src/spanguard/recognizers/luhn.py +19 -0
  41. spanguard-0.1.0/src/spanguard/recognizers/ner.py +57 -0
  42. spanguard-0.1.0/src/spanguard/recognizers/regex_recognizers.py +156 -0
  43. spanguard-0.1.0/src/spanguard/redactor.py +94 -0
  44. spanguard-0.1.0/src/spanguard/result.py +49 -0
  45. spanguard-0.1.0/src/spanguard/streaming.py +149 -0
  46. spanguard-0.1.0/src/spanguard/tokenize.py +71 -0
  47. spanguard-0.1.0/tests/__init__.py +0 -0
  48. spanguard-0.1.0/tests/test_audit_safety.py +55 -0
  49. spanguard-0.1.0/tests/test_benchmark_smoke.py +42 -0
  50. spanguard-0.1.0/tests/test_cli.py +186 -0
  51. spanguard-0.1.0/tests/test_docs_examples.py +47 -0
  52. spanguard-0.1.0/tests/test_modes.py +99 -0
  53. spanguard-0.1.0/tests/test_ner.py +101 -0
  54. spanguard-0.1.0/tests/test_overlap.py +75 -0
  55. spanguard-0.1.0/tests/test_policy.py +35 -0
  56. spanguard-0.1.0/tests/test_recognizers.py +225 -0
  57. spanguard-0.1.0/tests/test_redactor.py +104 -0
  58. spanguard-0.1.0/tests/test_result.py +50 -0
  59. spanguard-0.1.0/tests/test_smoke.py +6 -0
  60. spanguard-0.1.0/tests/test_streaming.py +263 -0
  61. spanguard-0.1.0/tests/test_tokenize.py +124 -0
  62. spanguard-0.1.0/uv.lock +1347 -0
@@ -0,0 +1,87 @@
1
+ name: Bug report
2
+ description: Report a problem with spanguard (detector miss, incorrect redaction, streaming/CLI bug, etc.)
3
+ title: "bug: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time to report a bug.
10
+
11
+ **IMPORTANT — do not paste real PII/PHI or other sensitive data into this
12
+ issue.** GitHub issues are public. Please reproduce the problem using
13
+ synthetic/fake data only, e.g. `jane@example.com`, `555-123-4567`,
14
+ `123-45-6789`. If the bug is a security-sensitive redaction bypass or a
15
+ way sensitive data can leak (rather than a general correctness bug),
16
+ please use [private vulnerability reporting](https://github.com/Clufy/spanguard/security/advisories/new)
17
+ instead of a public issue — see [SECURITY.md](https://github.com/Clufy/spanguard/blob/master/SECURITY.md).
18
+
19
+ - type: checkboxes
20
+ id: no-real-pii
21
+ attributes:
22
+ label: Confirmation
23
+ options:
24
+ - label: I have NOT included any real PII/PHI or other sensitive data in this report — all examples below use synthetic/fake data.
25
+ required: true
26
+ - label: This is a general bug, not a security-sensitive leak or detector bypass (if it is, I will use private vulnerability reporting instead).
27
+ required: true
28
+
29
+ - type: input
30
+ id: spanguard-version
31
+ attributes:
32
+ label: spanguard version
33
+ description: Output of `pip show spanguard` (or `uv pip show spanguard`), or the git commit if installed from source.
34
+ placeholder: "0.1.0"
35
+ validations:
36
+ required: true
37
+
38
+ - type: input
39
+ id: python-version
40
+ attributes:
41
+ label: Python version
42
+ description: Output of `python --version`.
43
+ placeholder: "3.12.4"
44
+ validations:
45
+ required: true
46
+
47
+ - type: textarea
48
+ id: repro
49
+ attributes:
50
+ label: Minimal reproduction
51
+ description: >
52
+ A minimal, self-contained code snippet that reproduces the issue, using
53
+ synthetic data only. Include the `Policy`/`Redactor` configuration you
54
+ used.
55
+ render: python
56
+ placeholder: |
57
+ from spanguard import Redactor, Policy
58
+
59
+ policy = Policy(mode="placeholder", entities=("EMAIL",))
60
+ result = Redactor(policy).redact("Contact: jane@example.com")
61
+ print(result.text)
62
+ validations:
63
+ required: true
64
+
65
+ - type: textarea
66
+ id: expected
67
+ attributes:
68
+ label: Expected behavior
69
+ description: What did you expect to happen?
70
+ validations:
71
+ required: true
72
+
73
+ - type: textarea
74
+ id: actual
75
+ attributes:
76
+ label: Actual behavior
77
+ description: What actually happened? Include the full output/traceback if relevant (with any sensitive data replaced by synthetic placeholders).
78
+ validations:
79
+ required: true
80
+
81
+ - type: textarea
82
+ id: context
83
+ attributes:
84
+ label: Additional context
85
+ description: Anything else relevant — e.g. whether the `[ner]` extra is installed, whether this happens in streaming mode, OS, etc.
86
+ validations:
87
+ required: false
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Documentation
4
+ url: https://clufy.github.io/spanguard
5
+ about: Check the docs (quickstart, recognizers, streaming, CLI, known limitations) before filing an issue — your question may already be answered there.
6
+ - name: Report a security vulnerability
7
+ url: https://github.com/Clufy/spanguard/security/advisories/new
8
+ about: For redaction bypasses, audit-record leaks, or other security-sensitive issues, please use private vulnerability reporting instead of a public issue.
@@ -0,0 +1,59 @@
1
+ name: Feature request
2
+ description: Suggest a new detector, redaction mode, or other enhancement for spanguard
3
+ title: "feat: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for suggesting an improvement to spanguard.
10
+
11
+ As with bug reports: please describe your use case using synthetic
12
+ examples only — do not paste real PII/PHI into this issue.
13
+
14
+ - type: textarea
15
+ id: problem
16
+ attributes:
17
+ label: Problem / use case
18
+ description: >
19
+ What problem are you trying to solve? What's missing today? If this is
20
+ about a new entity type or detector, describe the format(s) you need
21
+ to detect (with synthetic examples).
22
+ placeholder: |
23
+ I need to detect [entity type] in my data, e.g. text like
24
+ "example-synthetic-value-123" — spanguard currently has no recognizer
25
+ for this format.
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: proposed-solution
31
+ attributes:
32
+ label: Proposed solution
33
+ description: >
34
+ How would you like this to work? If you're proposing a new detector,
35
+ note whether it could be a regex `Recognizer`, whether it needs
36
+ context-anchoring (like `MRN`), or whether it needs NER/model-based
37
+ detection.
38
+ validations:
39
+ required: true
40
+
41
+ - type: textarea
42
+ id: alternatives
43
+ attributes:
44
+ label: Alternatives considered
45
+ description: >
46
+ Have you considered writing a custom `Recognizer` for this yourself
47
+ (see the docs on Recognizers)? If so, why doesn't that work for your
48
+ case — e.g. does it need to be a built-in default, or shared across
49
+ projects?
50
+ validations:
51
+ required: false
52
+
53
+ - type: textarea
54
+ id: context
55
+ attributes:
56
+ label: Additional context
57
+ description: Anything else — links, related issues, references to similar detectors in other tools, etc.
58
+ validations:
59
+ required: false
@@ -0,0 +1,19 @@
1
+ ## Summary
2
+
3
+ <!-- What does this change do, and why? Link any related issue. -->
4
+
5
+ ## Checklist
6
+
7
+ - [ ] PR title follows [Conventional Commits](https://www.conventionalcommits.org/) (`feat: ...`, `fix: ...`, `docs: ...`, `refactor: ...`, `chore: ...`, `ci: ...`, `test: ...`).
8
+ - [ ] Tests added/updated for the change, including **both positive and negative cases** if this touches a `Recognizer` (see `CONTRIBUTING.md`).
9
+ - [ ] `uv run ruff check .` passes clean.
10
+ - [ ] `uv run mypy` passes clean (`strict = true` — no new untyped defs or `Any` leaks).
11
+ - [ ] `uv run pytest --cov=spanguard --cov-report=term-missing --cov-fail-under=90` passes and coverage is maintained (currently 96.92%; gate is 90%).
12
+ - [ ] Docs updated under `docs/` if this changes or adds user-facing behavior (new detector, new CLI flag, new redaction mode, etc.), including `docs/known-limitations.md` if this introduces a deliberate precision/recall trade-off.
13
+ - [ ] `CHANGELOG.md` updated under `[Unreleased]` if this is a user-visible change.
14
+ - [ ] **No real PII/PHI in tests, examples, fixtures, or this PR description** — synthetic data only (e.g. `jane@example.com`, `555-123-4567`, `123-45-6789`).
15
+ - [ ] If this touches redaction, audit records, or streaming: confirmed no raw matched value can reach `RedactionResult.audit`, redacted output (when it shouldn't), or CLI `scan` output.
16
+
17
+ ## Additional context
18
+
19
+ <!-- Anything a reviewer needs to know: design trade-offs, alternatives considered, follow-up work, etc. -->
@@ -0,0 +1,22 @@
1
+ name: CI
2
+ on:
3
+ push: { branches: [master, main] }
4
+ pull_request:
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v4
10
+ - uses: astral-sh/setup-uv@v5
11
+ - run: uv venv --python 3.12
12
+ - run: uv pip install -e ".[ner]" pytest pytest-cov ruff mypy
13
+ - run: uv run ruff check .
14
+ - run: uv run mypy
15
+ - run: uv run pytest --cov=spanguard --cov-report=term-missing --cov-fail-under=90
16
+
17
+ secrets:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with: { fetch-depth: 0 } # full history so gitleaks scans every commit
22
+ - uses: gitleaks/gitleaks-action@v2
@@ -0,0 +1,32 @@
1
+ name: Docs
2
+ on:
3
+ push: { branches: [master, main] }
4
+ workflow_dispatch:
5
+ permissions:
6
+ contents: read
7
+ pages: write
8
+ id-token: write
9
+ concurrency:
10
+ group: pages
11
+ cancel-in-progress: true # newer docs push supersedes an in-flight deploy; avoids Pages collisions
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v5
18
+ - run: uv venv --python 3.12
19
+ - run: uv pip install -e ".[docs]"
20
+ - run: uv run mkdocs build --strict
21
+ - uses: actions/upload-pages-artifact@v3
22
+ with:
23
+ path: site
24
+ deploy:
25
+ needs: build
26
+ runs-on: ubuntu-latest
27
+ environment:
28
+ name: github-pages
29
+ url: ${{ steps.deployment.outputs.page_url }}
30
+ steps:
31
+ - id: deployment
32
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,16 @@
1
+ name: Publish
2
+ on:
3
+ push:
4
+ tags: ["v*"]
5
+ permissions:
6
+ id-token: write # OIDC; NO PyPI token stored
7
+ contents: read
8
+ jobs:
9
+ build-and-publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ - run: uv build
16
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,52 @@
1
+ # Python bytecode / caches
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ .pytest_cache/
8
+ .hypothesis/
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+ env/
14
+ ENV/
15
+
16
+ # Packaging / build artifacts
17
+ *.egg-info/
18
+ *.egg
19
+ dist/
20
+ build/
21
+ wheels/
22
+ pip-wheel-metadata/
23
+
24
+ # Test / coverage output
25
+ .coverage
26
+ .coverage.*
27
+ htmlcov/
28
+ coverage.xml
29
+ .tox/
30
+ .nox/
31
+
32
+ # Docs build output
33
+ site/
34
+
35
+ # Secrets / environment
36
+ .env
37
+ .env.*
38
+ !.env.example
39
+
40
+ # Superpowers workflow scratch (task briefs, reports, review diffs, ledger)
41
+ .superpowers/
42
+
43
+ # OS / editor cruft
44
+ .DS_Store
45
+ Thumbs.db
46
+ .idea/
47
+ .vscode/
48
+ *.swp
49
+ *~
50
+
51
+ # Internal design/plan/spec docs (not part of the public site or repo)
52
+ docs/superpowers/
@@ -0,0 +1,13 @@
1
+ # Extend gitleaks' default rules; only add an allowlist for known-safe fixtures.
2
+ [extend]
3
+ useDefault = true
4
+
5
+ # ponytail: allowlist the synthetic secrets in the recognizer test suite.
6
+ # These are non-credentials — AWS's own docs placeholder and a fabricated sk- string —
7
+ # used to verify detection. Add real exceptions here (by regex) only when equally certain.
8
+ [allowlist]
9
+ description = "Synthetic test fixtures, not real credentials"
10
+ regexes = [
11
+ '''AKIAIOSFODNN7EXAMPLE''',
12
+ '''sk-abcDEF0123456789abcDEF0123''',
13
+ ]
@@ -0,0 +1,90 @@
1
+ # Changelog
2
+
3
+ All notable changes to spanguard will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-11-12
11
+
12
+ Initial release.
13
+
14
+ ### Added
15
+
16
+ - **Entity detection** for `EMAIL` (Unicode-aware local part and domain),
17
+ `PHONE` (NANP-style, multiple separator conventions), `SSN`, `MRN`
18
+ (context-anchored on an `MRN` prefix), `DOB` (`mm/dd/yyyy` and ISO
19
+ `yyyy-mm-dd`), `CREDIT_CARD` (regex plus Luhn checksum validation across
20
+ standard printed groupings), and `API_KEY` (known-prefix formats such as
21
+ `sk-`, `AKIA`, `ghp_`, plus a high-entropy generic fallback).
22
+ - **Four redaction modes** on every `Policy`: `mask` (fixed-character
23
+ replacement, length-preserving), `placeholder` (`[TYPE]` tags), `hash`
24
+ (deterministic HMAC digest, reproducible with a shared key), and
25
+ `tokenize` (reversible placeholder tokens).
26
+ - **Reversible tokenization and reveal** — `Redactor.reveal()` restores the
27
+ original text from `tokenize`-mode output via an in-memory `Keyring`,
28
+ scoped to a single process/key.
29
+ - **`StreamRedactor`** for chunked/streaming input (e.g. live call
30
+ transcripts or log tails), with a documented split-equals-one-shot
31
+ guarantee: concatenating every `feed()` call's output plus a final
32
+ `flush()` equals exactly what a one-shot `redact()` on the full text would
33
+ produce, even when an entity straddles a chunk boundary. Enforces a
34
+ minimum `tail` buffer of 64 characters to prevent sub-threshold entity
35
+ leakage.
36
+ - **Optional NER extra** (`pip install spanguard[ner]`) adding a
37
+ spaCy-backed `SpacyRecognizer` for `PERSON` and `LOCATION` detection,
38
+ imported lazily so the core install stays dependency-light and fast to
39
+ import.
40
+ - **`spanguard` CLI** with `scan` (report entity-type counts only, never raw
41
+ values) and `redact` (write redacted text to stdout or a file, with an
42
+ optional `--audit-json` audit record on stderr) subcommands.
43
+ `-` reads stdin as UTF-8. An unknown `--entities` name, an unreadable,
44
+ undecodable or missing input (including closed stdin), or an unwritable
45
+ `--out` path exits with code 2 and a one-line `error:` message that names
46
+ only the path or label, never input content.
47
+ - **Unknown-entity warning**: `Redactor` warns (`UserWarning`, entity labels
48
+ only) when `Policy.entities` names a type with no recognizer, such as
49
+ `PERSON` without `SpacyRecognizer` or a typo like `EMIAL`, instead of
50
+ silently detecting nothing for it.
51
+ - **`StreamRedactor(max_buffer=N)`** and `StreamBufferFullError`: an opt-in
52
+ cap on held-back text for streams that never offer a safe split point.
53
+ Uncapped by default.
54
+ - **Leak-free audit records** — every `RedactionResult.audit` contains only
55
+ entity-type counts, a policy hash, and a timestamp, never a raw matched
56
+ value or span text; this guarantee is enforced directly by the test suite
57
+ (`tests/test_audit_safety.py`), not just documented.
58
+ - **Pluggable `Recognizer` protocol** for adding custom, domain-specific
59
+ detectors without forking the library.
60
+ - Full documentation site (mkdocs-material) covering quickstart, streaming,
61
+ the CLI, recognizers, and an honest known-limitations page, published to
62
+ [clufy.github.io/spanguard](https://clufy.github.io/spanguard).
63
+ - CI pipeline (ruff, mypy `--strict`, pytest with a 90% coverage gate) on
64
+ every push and pull request; 128 tests at 97.92% coverage as of this
65
+ release. Published to PyPI from GitHub Actions via OIDC Trusted
66
+ Publishing on `v*` tags; no PyPI token is stored anywhere.
67
+
68
+ ### Performance
69
+
70
+ Measured against the July 2026 pre-release build. Redaction output is
71
+ byte-identical; each change is pinned by a differential test against the
72
+ earlier algorithm.
73
+
74
+ | Path | Pre-release | 0.1.0 |
75
+ |---|---|---|
76
+ | `Redactor.redact`, 40k spans | 84.6 s | 0.84 s |
77
+ | `EmailRecognizer`, 8k-char token with no spaces | 844 ms (quadratic) | 0.6 ms (linear) |
78
+ | `Keyring.reveal`, 30k issued tokens | 11.2 s | 44 ms |
79
+ | `StreamRedactor`, 200 KB in 4 KB chunks | 304 ms | 194 ms |
80
+ | `StreamRedactor`, 1 MB with no whitespace | quadratic | linear |
81
+ | `StreamRedactor`, 200 KB whose only whitespace is inside a phone number | 8.49 s | 0.08 s |
82
+ | `benchmarks/throughput.py` (1 MB corpus) | 1.54 MB/s | 2.15 MB/s |
83
+
84
+ Overlap resolution is O(n log n), email detection cannot backtrack
85
+ quadratically on long whitespace-free runs (a denial-of-service vector),
86
+ `Keyring.reveal` is linear in the text, and `StreamRedactor` never re-detects
87
+ text it has already verified or split points it has already tried.
88
+
89
+ [unreleased]: https://github.com/Clufy/spanguard/compare/v0.1.0...HEAD
90
+ [0.1.0]: https://github.com/Clufy/spanguard/releases/tag/v0.1.0
@@ -0,0 +1,22 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use spanguard in your work, please cite it using the metadata below."
3
+ type: software
4
+ title: spanguard
5
+ abstract: >-
6
+ Detect and redact PII/PHI in text and streaming transcripts, with leak-free
7
+ audit records, reversible tokenization, an optional NER extra, and a CLI.
8
+ authors:
9
+ - name: "spanguard authors"
10
+ alias: "Clufy"
11
+ repository-code: "https://github.com/Clufy/spanguard"
12
+ url: "https://clufy.github.io/spanguard"
13
+ license: MIT
14
+ version: 0.1.0
15
+ date-released: "2026-07-06"
16
+ keywords:
17
+ - pii
18
+ - phi
19
+ - redaction
20
+ - privacy
21
+ - compliance
22
+ - nlp
@@ -0,0 +1,142 @@
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
9
+ status, nationality, personal appearance, race, caste, color, religion, or
10
+ sexual 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
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances
31
+ of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political
33
+ attacks
34
+ * Public or private harassment
35
+ * Publishing others' private information, such as a physical or email
36
+ address, without their explicit permission
37
+ * Other conduct which could reasonably be considered inappropriate in a
38
+ professional setting
39
+
40
+ ## Enforcement Responsibilities
41
+
42
+ Community leaders are responsible for clarifying and enforcing our standards
43
+ of acceptable behavior and will take appropriate and fair corrective action
44
+ in response to any behavior that they deem inappropriate, threatening,
45
+ offensive, or harmful.
46
+
47
+ Community leaders have the right and responsibility to remove, edit, or
48
+ reject comments, commits, code, wiki edits, issues, and other contributions
49
+ that are not aligned to this Code of Conduct, and will communicate reasons
50
+ for moderation decisions when appropriate.
51
+
52
+ ## Scope
53
+
54
+ This Code of Conduct applies within all community spaces, and also applies
55
+ when an individual is officially representing the community in public
56
+ spaces. Examples of representing our community include using an official
57
+ e-mail address, posting via an official social media account, or acting as
58
+ an appointed representative at an online or offline event.
59
+
60
+ ## Enforcement
61
+
62
+ spanguard does not currently publish a dedicated enforcement email address.
63
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
64
+ reported by:
65
+
66
+ * Opening a private [Security Advisory](https://github.com/Clufy/spanguard/security/advisories/new)
67
+ on the repository (via the **Security** tab → **Report a vulnerability**),
68
+ which is visible only to the maintainer and is not public — this mechanism
69
+ works for conduct reports as well as security reports; or
70
+ * Contacting the maintainer directly via their GitHub account,
71
+ [@Clufy](https://github.com/Clufy).
72
+
73
+ All complaints will be reviewed and investigated promptly and fairly.
74
+
75
+ All community leaders are obligated to respect the privacy and security of
76
+ the reporter of any incident.
77
+
78
+ ## Enforcement Guidelines
79
+
80
+ Community leaders will follow these Community Impact Guidelines in
81
+ determining the consequences for any action they deem in violation of this
82
+ Code of Conduct:
83
+
84
+ ### 1. Correction
85
+
86
+ **Community Impact**: Use of inappropriate language or other behavior deemed
87
+ unprofessional or unwelcome in the community.
88
+
89
+ **Consequence**: A private, written warning from community leaders,
90
+ providing clarity around the nature of the violation and an explanation of
91
+ why the behavior was inappropriate. A public apology may be requested.
92
+
93
+ ### 2. Warning
94
+
95
+ **Community Impact**: A violation through a single incident or series of
96
+ actions.
97
+
98
+ **Consequence**: A warning with consequences for continued behavior. No
99
+ interaction with the people involved, including unsolicited interaction with
100
+ those enforcing the Code of Conduct, for a specified period of time. This
101
+ includes avoiding interactions in community spaces as well as external
102
+ channels like social media. Violating these terms may lead to a temporary or
103
+ permanent ban.
104
+
105
+ ### 3. Temporary Ban
106
+
107
+ **Community Impact**: A serious violation of community standards, including
108
+ sustained inappropriate behavior.
109
+
110
+ **Consequence**: A temporary ban from any sort of interaction or public
111
+ communication with the community for a specified period of time. No public
112
+ or private interaction with the people involved, including unsolicited
113
+ interaction with those enforcing the Code of Conduct, is allowed during this
114
+ period. Violating these terms may lead to a permanent ban.
115
+
116
+ ### 4. Permanent Ban
117
+
118
+ **Community Impact**: Demonstrating a pattern of violation of community
119
+ standards, including sustained inappropriate behavior, harassment of an
120
+ individual, or aggression toward or disparagement of classes of individuals.
121
+
122
+ **Consequence**: A permanent ban from any sort of public interaction within
123
+ the community.
124
+
125
+ ## Attribution
126
+
127
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
128
+ version 2.1, available at
129
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
130
+
131
+ Community Impact Guidelines were inspired by
132
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
133
+
134
+ For answers to common questions about this code of conduct, see the FAQ at
135
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
136
+ at [https://www.contributor-covenant.org/translations][translations].
137
+
138
+ [homepage]: https://www.contributor-covenant.org
139
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
140
+ [Mozilla CoC]: https://github.com/mozilla/diversity
141
+ [FAQ]: https://www.contributor-covenant.org/faq
142
+ [translations]: https://www.contributor-covenant.org/translations