commitguardian 0.1.0__py3-none-any.whl
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.
- commitguard/__init__.py +26 -0
- commitguard/__main__.py +6 -0
- commitguard/api/__init__.py +18 -0
- commitguard/api/app.py +1376 -0
- commitguard/api/governance.py +1085 -0
- commitguard/api/hosting.py +196 -0
- commitguard/api/http.py +252 -0
- commitguard/api/settings.py +169 -0
- commitguard/audit/__init__.py +13 -0
- commitguard/audit/logger.py +34 -0
- commitguard/audit/models.py +222 -0
- commitguard/audit/storage.py +59 -0
- commitguard/ci/__init__.py +7 -0
- commitguard/ci/context.py +60 -0
- commitguard/cli/__init__.py +6 -0
- commitguard/cli/app.py +74 -0
- commitguard/cli/commands/__init__.py +1 -0
- commitguard/cli/commands/benchmark.py +441 -0
- commitguard/cli/commands/check.py +100 -0
- commitguard/cli/commands/ci.py +165 -0
- commitguard/cli/commands/dashboard.py +141 -0
- commitguard/cli/commands/doctor.py +533 -0
- commitguard/cli/commands/github.py +449 -0
- commitguard/cli/commands/hook.py +156 -0
- commitguard/cli/commands/init.py +137 -0
- commitguard/cli/commands/install.py +152 -0
- commitguard/cli/commands/policy.py +36 -0
- commitguard/cli/commands/report.py +39 -0
- commitguard/cli/commands/reproduce.py +123 -0
- commitguard/cli/commands/scan.py +47 -0
- commitguard/cli/common.py +44 -0
- commitguard/cli/output.py +89 -0
- commitguard/cli/render.py +367 -0
- commitguard/config/__init__.py +6 -0
- commitguard/config/defaults.py +53 -0
- commitguard/config/enforcement.py +53 -0
- commitguard/config/loader.py +174 -0
- commitguard/config/schema.py +105 -0
- commitguard/config/sources.py +183 -0
- commitguard/controlplane/__init__.py +24 -0
- commitguard/controlplane/access.py +231 -0
- commitguard/controlplane/commands.py +393 -0
- commitguard/controlplane/errors.py +88 -0
- commitguard/controlplane/identity.py +478 -0
- commitguard/controlplane/members.py +219 -0
- commitguard/controlplane/notifications.py +787 -0
- commitguard/controlplane/pagination.py +146 -0
- commitguard/controlplane/policies.py +1204 -0
- commitguard/controlplane/queries.py +1814 -0
- commitguard/controlplane/results.py +909 -0
- commitguard/controlplane/rules.py +184 -0
- commitguard/controlplane/views.py +799 -0
- commitguard/core/__init__.py +6 -0
- commitguard/core/context.py +31 -0
- commitguard/core/decision.py +58 -0
- commitguard/core/engine.py +82 -0
- commitguard/core/result.py +177 -0
- commitguard/detectors/__init__.py +6 -0
- commitguard/detectors/base.py +58 -0
- commitguard/detectors/bot.py +87 -0
- commitguard/detectors/coauthor.py +86 -0
- commitguard/detectors/identity.py +76 -0
- commitguard/detectors/registry.py +72 -0
- commitguard/detectors/trailer.py +211 -0
- commitguard/exceptions/__init__.py +33 -0
- commitguard/exceptions/base.py +9 -0
- commitguard/exceptions/configuration.py +22 -0
- commitguard/exceptions/detection.py +11 -0
- commitguard/exceptions/git.py +41 -0
- commitguard/exceptions/service.py +25 -0
- commitguard/git/__init__.py +12 -0
- commitguard/git/commands.py +101 -0
- commitguard/git/commit.py +97 -0
- commitguard/git/diff.py +36 -0
- commitguard/git/hooks.py +527 -0
- commitguard/git/push.py +93 -0
- commitguard/git/ranges.py +71 -0
- commitguard/git/repository.py +447 -0
- commitguard/github/__init__.py +34 -0
- commitguard/github/actions.py +163 -0
- commitguard/github/app.py +935 -0
- commitguard/github/auth.py +217 -0
- commitguard/github/check_runs.py +172 -0
- commitguard/github/checks.py +210 -0
- commitguard/github/client.py +844 -0
- commitguard/github/enforcement_status.py +209 -0
- commitguard/github/errors.py +129 -0
- commitguard/github/events.py +563 -0
- commitguard/github/identifiers.py +90 -0
- commitguard/github/installations.py +566 -0
- commitguard/github/markdown.py +19 -0
- commitguard/github/permissions.py +70 -0
- commitguard/github/pull_requests.py +53 -0
- commitguard/github/queue.py +47 -0
- commitguard/github/recovery.py +124 -0
- commitguard/github/repositories.py +305 -0
- commitguard/github/server.py +52 -0
- commitguard/github/settings.py +174 -0
- commitguard/github/storage.py +2315 -0
- commitguard/github/webhooks.py +129 -0
- commitguard/github/worker.py +628 -0
- commitguard/github/workflow.py +286 -0
- commitguard/governance/__init__.py +26 -0
- commitguard/governance/bulk.py +765 -0
- commitguard/governance/cache.py +88 -0
- commitguard/governance/common.py +216 -0
- commitguard/governance/exceptions.py +861 -0
- commitguard/governance/groups.py +448 -0
- commitguard/governance/inventory.py +386 -0
- commitguard/governance/posture.py +1272 -0
- commitguard/governance/resolver.py +632 -0
- commitguard/governance/rollouts.py +760 -0
- commitguard/governance/rules.py +371 -0
- commitguard/governance/schedules.py +663 -0
- commitguard/governance/service.py +120 -0
- commitguard/governance/settings.py +365 -0
- commitguard/governance/simulation.py +618 -0
- commitguard/governance/workflow.py +734 -0
- commitguard/notifications/__init__.py +2 -0
- commitguard/notifications/channels/__init__.py +1 -0
- commitguard/notifications/channels/base.py +22 -0
- commitguard/notifications/channels/email.py +110 -0
- commitguard/notifications/channels/in_app.py +74 -0
- commitguard/notifications/channels/sink.py +58 -0
- commitguard/notifications/channels/webhook.py +233 -0
- commitguard/notifications/deduplication.py +57 -0
- commitguard/notifications/dispatcher.py +201 -0
- commitguard/notifications/models.py +439 -0
- commitguard/notifications/outbox.py +106 -0
- commitguard/notifications/preferences.py +224 -0
- commitguard/notifications/retry.py +282 -0
- commitguard/notifications/service.py +128 -0
- commitguard/notifications/settings.py +167 -0
- commitguard/notifications/templates.py +108 -0
- commitguard/observability/__init__.py +5 -0
- commitguard/observability/logging.py +161 -0
- commitguard/observability/metrics.py +105 -0
- commitguard/policies/__init__.py +6 -0
- commitguard/policies/defaults.py +48 -0
- commitguard/policies/evaluator.py +66 -0
- commitguard/policies/governance.py +498 -0
- commitguard/policies/loader.py +23 -0
- commitguard/policies/mandatory.py +52 -0
- commitguard/policies/model.py +46 -0
- commitguard/provenance/__init__.py +9 -0
- commitguard/provenance/author.py +146 -0
- commitguard/provenance/committer.py +16 -0
- commitguard/provenance/normalization.py +158 -0
- commitguard/provenance/signatures.py +34 -0
- commitguard/provenance/trailers.py +256 -0
- commitguard/research/__init__.py +26 -0
- commitguard/research/compare.py +231 -0
- commitguard/research/datasets.py +1484 -0
- commitguard/research/detection.py +183 -0
- commitguard/research/environment.py +185 -0
- commitguard/research/gitenv.py +108 -0
- commitguard/research/hooks.py +247 -0
- commitguard/research/metrics.py +85 -0
- commitguard/research/performance.py +194 -0
- commitguard/research/platform.py +288 -0
- commitguard/research/report.py +372 -0
- commitguard/research/repository.py +111 -0
- commitguard/research/reproduction.py +297 -0
- commitguard/research/results.py +94 -0
- commitguard/rules/__init__.py +11 -0
- commitguard/rules/data/ai-domains.yaml +51 -0
- commitguard/rules/data/ai-identities.yaml +131 -0
- commitguard/rules/data/bot-identities.yaml +53 -0
- commitguard/rules/data/patterns.yaml +52 -0
- commitguard/rules/loader.py +102 -0
- commitguard/rules/matcher.py +212 -0
- commitguard/rules/models.py +269 -0
- commitguard/security/__init__.py +5 -0
- commitguard/security/hashing.py +30 -0
- commitguard/security/rate_limit.py +33 -0
- commitguard/security/safe_yaml.py +69 -0
- commitguard/security/sanitization.py +85 -0
- commitguard/security/secrets.py +169 -0
- commitguard/security/validation.py +89 -0
- commitguard/services/__init__.py +15 -0
- commitguard/services/analysis.py +119 -0
- commitguard/services/audit.py +95 -0
- commitguard/services/ci.py +383 -0
- commitguard/services/enforcement.py +102 -0
- commitguard/services/hooks.py +254 -0
- commitguard/services/remediation.py +99 -0
- commitguard/services/reports.py +146 -0
- commitguard/services/scan.py +172 -0
- commitguard/utils/__init__.py +1 -0
- commitguard/utils/filesystem.py +72 -0
- commitguard/utils/platform.py +35 -0
- commitguard/utils/subprocess.py +84 -0
- commitguardian-0.1.0.dist-info/METADATA +694 -0
- commitguardian-0.1.0.dist-info/RECORD +197 -0
- commitguardian-0.1.0.dist-info/WHEEL +4 -0
- commitguardian-0.1.0.dist-info/entry_points.txt +2 -0
- commitguardian-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
"""The dashboard API's resource models (the ``data`` of API responses).
|
|
2
|
+
|
|
3
|
+
These are the public contract of ``/api/v1``. They are built from database
|
|
4
|
+
rows by the query services and deliberately differ from them: internal columns
|
|
5
|
+
(leases, job keys, delivery IDs, session hashes) never appear here, and every
|
|
6
|
+
status is one value of a closed vocabulary decided by the server. The
|
|
7
|
+
dashboard renders these values; it never derives a security decision itself.
|
|
8
|
+
|
|
9
|
+
Status vocabulary
|
|
10
|
+
=================
|
|
11
|
+
|
|
12
|
+
===================== ================================================================
|
|
13
|
+
Field Values
|
|
14
|
+
===================== ================================================================
|
|
15
|
+
scan ``result`` ``queued`` ``running`` ``pass`` ``warning`` ``blocked``
|
|
16
|
+
``error`` ``cancelled`` ``stale``
|
|
17
|
+
scan ``trigger`` ``push`` ``pull_request`` ``merge_group`` ``manual`` ``rerun``
|
|
18
|
+
``retry``
|
|
19
|
+
violation ``status`` ``open`` ``acknowledged`` ``resolved``
|
|
20
|
+
``protection`` ``protected`` ``at_risk`` ``unprotected`` ``configuration_error``
|
|
21
|
+
``unknown``
|
|
22
|
+
merge queue ``enabled`` ``not_enabled`` ``unknown``
|
|
23
|
+
notification ``state`` ``unread`` ``read`` ``archived``
|
|
24
|
+
GitHub App ``connected`` ``suspended`` ``disconnected``
|
|
25
|
+
GitHub Actions ``detected`` ``not_detected`` ``unknown``
|
|
26
|
+
required check ``required`` ``not_required`` ``unknown``
|
|
27
|
+
local hooks ``not_verifiable``
|
|
28
|
+
integration ``connected`` ``action_required`` ``disconnected``
|
|
29
|
+
severity ``info`` ``low`` ``medium`` ``high`` ``critical`` (core model)
|
|
30
|
+
policy action ``allow`` ``warn`` ``block`` (core model)
|
|
31
|
+
===================== ================================================================
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from datetime import datetime
|
|
35
|
+
from enum import StrEnum
|
|
36
|
+
from typing import Literal
|
|
37
|
+
|
|
38
|
+
from pydantic import BaseModel, ConfigDict
|
|
39
|
+
|
|
40
|
+
from commitguard.core.decision import Action
|
|
41
|
+
from commitguard.core.result import Severity
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class _View(BaseModel):
|
|
45
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# --------------------------------------------------------------------------- #
|
|
49
|
+
# Vocabulary
|
|
50
|
+
# --------------------------------------------------------------------------- #
|
|
51
|
+
class ScanResultStatus(StrEnum):
|
|
52
|
+
QUEUED = "queued"
|
|
53
|
+
RUNNING = "running"
|
|
54
|
+
PASS = "pass" # noqa: S105 - status name, not a password
|
|
55
|
+
WARNING = "warning"
|
|
56
|
+
BLOCKED = "blocked"
|
|
57
|
+
ERROR = "error"
|
|
58
|
+
CANCELLED = "cancelled"
|
|
59
|
+
STALE = "stale" # superseded before it could publish: a newer execution owns the check
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ViolationStatus(StrEnum):
|
|
63
|
+
OPEN = "open"
|
|
64
|
+
ACKNOWLEDGED = "acknowledged"
|
|
65
|
+
RESOLVED = "resolved"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ProtectionStatus(StrEnum):
|
|
69
|
+
PROTECTED = "protected"
|
|
70
|
+
AT_RISK = "at_risk" # the GitHub App lost access: enforcement may no longer run
|
|
71
|
+
UNPROTECTED = "unprotected"
|
|
72
|
+
CONFIGURATION_ERROR = "configuration_error"
|
|
73
|
+
UNKNOWN = "unknown"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class AppConnection(StrEnum):
|
|
77
|
+
CONNECTED = "connected"
|
|
78
|
+
SUSPENDED = "suspended"
|
|
79
|
+
DISCONNECTED = "disconnected"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ActionsStatus(StrEnum):
|
|
83
|
+
DETECTED = "detected"
|
|
84
|
+
NOT_DETECTED = "not_detected"
|
|
85
|
+
UNKNOWN = "unknown"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class RequiredCheckStatus(StrEnum):
|
|
89
|
+
REQUIRED = "required"
|
|
90
|
+
NOT_REQUIRED = "not_required"
|
|
91
|
+
UNKNOWN = "unknown"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class MergeQueueStatus(StrEnum):
|
|
95
|
+
ENABLED = "enabled"
|
|
96
|
+
NOT_ENABLED = "not_enabled"
|
|
97
|
+
UNKNOWN = "unknown"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class IntegrationStatus(StrEnum):
|
|
101
|
+
CONNECTED = "connected"
|
|
102
|
+
ACTION_REQUIRED = "action_required"
|
|
103
|
+
DISCONNECTED = "disconnected"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class HealthCheckStatus(StrEnum):
|
|
107
|
+
OK = "ok"
|
|
108
|
+
ATTENTION = "attention"
|
|
109
|
+
UNKNOWN = "unknown"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# --------------------------------------------------------------------------- #
|
|
113
|
+
# Shared fragments
|
|
114
|
+
# --------------------------------------------------------------------------- #
|
|
115
|
+
class OrganizationRef(_View):
|
|
116
|
+
id: int
|
|
117
|
+
login: str
|
|
118
|
+
type: str
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class RepositoryLink(_View):
|
|
122
|
+
id: int
|
|
123
|
+
installation_id: int
|
|
124
|
+
full_name: str
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class ActorView(_View):
|
|
128
|
+
type: Literal["system", "github", "user"]
|
|
129
|
+
id: int | None = None
|
|
130
|
+
login: str | None = None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class PolicyEntry(_View):
|
|
134
|
+
id: str
|
|
135
|
+
enabled: bool
|
|
136
|
+
action: Action
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# --------------------------------------------------------------------------- #
|
|
140
|
+
# Scans and findings
|
|
141
|
+
# --------------------------------------------------------------------------- #
|
|
142
|
+
class ScanSummary(_View):
|
|
143
|
+
id: str
|
|
144
|
+
scan_id: str | None
|
|
145
|
+
repository: RepositoryLink
|
|
146
|
+
organization_id: int | None
|
|
147
|
+
event: str
|
|
148
|
+
pull_request_number: int | None
|
|
149
|
+
ref: str | None
|
|
150
|
+
base_sha: str | None
|
|
151
|
+
head_sha: str
|
|
152
|
+
check_name: str
|
|
153
|
+
result: ScanResultStatus
|
|
154
|
+
commits_scanned: int | None
|
|
155
|
+
violations: int | None
|
|
156
|
+
warnings: int | None
|
|
157
|
+
findings: int | None
|
|
158
|
+
created_at: datetime
|
|
159
|
+
started_at: datetime | None
|
|
160
|
+
completed_at: datetime | None
|
|
161
|
+
duration_ms: int | None
|
|
162
|
+
requested_by: str | None
|
|
163
|
+
trigger: str
|
|
164
|
+
execution: int
|
|
165
|
+
failure_source: Literal["pull_request", "push", "merge_queue"]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class MatchView(_View):
|
|
169
|
+
kind: str
|
|
170
|
+
value: str
|
|
171
|
+
rule: str
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class EvidenceView(_View):
|
|
175
|
+
source: str
|
|
176
|
+
source_label: str
|
|
177
|
+
value: str
|
|
178
|
+
line_number: int | None
|
|
179
|
+
matched: tuple[MatchView, ...]
|
|
180
|
+
notes: tuple[str, ...]
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class FindingView(_View):
|
|
184
|
+
id: int
|
|
185
|
+
violation_id: str | None
|
|
186
|
+
rule_id: str
|
|
187
|
+
detector: str
|
|
188
|
+
title: str
|
|
189
|
+
message: str
|
|
190
|
+
severity: Severity
|
|
191
|
+
confidence: str
|
|
192
|
+
action: Action
|
|
193
|
+
reason: str
|
|
194
|
+
commit_sha: str | None
|
|
195
|
+
author: str | None
|
|
196
|
+
committer: str | None
|
|
197
|
+
evidence: tuple[EvidenceView, ...]
|
|
198
|
+
remediation: str
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class ScanFailure(_View):
|
|
202
|
+
kind: str | None
|
|
203
|
+
message: str
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class ScanDetail(_View):
|
|
207
|
+
scan: ScanSummary
|
|
208
|
+
conclusion: str | None
|
|
209
|
+
tool_version: str | None
|
|
210
|
+
rules_version: str | None
|
|
211
|
+
policy_version: str | None
|
|
212
|
+
policy_source: str | None
|
|
213
|
+
organization_policy_version: int | None
|
|
214
|
+
effective_policies: tuple[PolicyEntry, ...]
|
|
215
|
+
detector_failures: int | None
|
|
216
|
+
notices: tuple[str, ...]
|
|
217
|
+
failure: ScanFailure | None
|
|
218
|
+
findings: tuple[FindingView, ...]
|
|
219
|
+
can_rescan: bool
|
|
220
|
+
rescan_blocked_reason: str | None
|
|
221
|
+
executions: int
|
|
222
|
+
latest_execution: str
|
|
223
|
+
merge_group: "MergeGroupView | None" = None
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class ExecutionView(_View):
|
|
227
|
+
"""One execution of a logical scan (same repository, commits and check)."""
|
|
228
|
+
|
|
229
|
+
id: str
|
|
230
|
+
execution: int
|
|
231
|
+
trigger: str
|
|
232
|
+
current: bool # the newest execution: it determines the current status
|
|
233
|
+
result: ScanResultStatus
|
|
234
|
+
head_sha: str
|
|
235
|
+
base_sha: str | None
|
|
236
|
+
organization_policy_version: int | None
|
|
237
|
+
policy_version: str | None
|
|
238
|
+
rules_version: str | None
|
|
239
|
+
tool_version: str | None
|
|
240
|
+
conclusion: str | None
|
|
241
|
+
requested_by: str | None
|
|
242
|
+
failure: ScanFailure | None
|
|
243
|
+
created_at: datetime
|
|
244
|
+
started_at: datetime | None
|
|
245
|
+
completed_at: datetime | None
|
|
246
|
+
duration_ms: int | None
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class ExecutionHistory(_View):
|
|
250
|
+
scan_id: str
|
|
251
|
+
items: tuple[ExecutionView, ...]
|
|
252
|
+
policy_changed: bool # executions were evaluated under different policy versions
|
|
253
|
+
rules_changed: bool
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class ScanComparison(_View):
|
|
257
|
+
scan_id: str
|
|
258
|
+
previous_scan_id: str | None
|
|
259
|
+
new: tuple[str, ...] # finding fingerprints
|
|
260
|
+
resolved: tuple[str, ...]
|
|
261
|
+
unchanged: tuple[str, ...]
|
|
262
|
+
new_findings: tuple[FindingView, ...]
|
|
263
|
+
resolved_findings: tuple[FindingView, ...]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# --------------------------------------------------------------------------- #
|
|
267
|
+
# Violations
|
|
268
|
+
# --------------------------------------------------------------------------- #
|
|
269
|
+
class ViolationSummary(_View):
|
|
270
|
+
id: str
|
|
271
|
+
rule_id: str
|
|
272
|
+
title: str
|
|
273
|
+
severity: Severity
|
|
274
|
+
action: Action
|
|
275
|
+
repository: RepositoryLink
|
|
276
|
+
organization_id: int | None
|
|
277
|
+
commit_sha: str | None
|
|
278
|
+
author: str | None
|
|
279
|
+
status: ViolationStatus
|
|
280
|
+
first_detected_at: datetime
|
|
281
|
+
last_detected_at: datetime
|
|
282
|
+
detections: int
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class ExposureView(_View):
|
|
286
|
+
kind: Literal["pull_request", "branch", "merge_group"]
|
|
287
|
+
label: str
|
|
288
|
+
active: bool
|
|
289
|
+
opened_at: datetime
|
|
290
|
+
closed_at: datetime | None
|
|
291
|
+
closed_reason: str | None
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class AcknowledgementView(_View):
|
|
295
|
+
by: str | None
|
|
296
|
+
at: datetime
|
|
297
|
+
note: str | None
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class DetectionView(_View):
|
|
301
|
+
scan: str
|
|
302
|
+
result: ScanResultStatus
|
|
303
|
+
detected_at: datetime
|
|
304
|
+
action: Action
|
|
305
|
+
head_sha: str
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class ViolationDetail(_View):
|
|
309
|
+
violation: ViolationSummary
|
|
310
|
+
detector: str
|
|
311
|
+
message: str
|
|
312
|
+
committer: str | None
|
|
313
|
+
policy_reason: str
|
|
314
|
+
evidence: tuple[EvidenceView, ...]
|
|
315
|
+
remediation: str
|
|
316
|
+
recommended_steps: tuple[str, ...]
|
|
317
|
+
resolved_at: datetime | None
|
|
318
|
+
resolution: str | None
|
|
319
|
+
acknowledgement: AcknowledgementView | None
|
|
320
|
+
exposures: tuple[ExposureView, ...]
|
|
321
|
+
detections: tuple[DetectionView, ...]
|
|
322
|
+
first_scan_id: str
|
|
323
|
+
last_scan_id: str
|
|
324
|
+
can_manage: bool
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# --------------------------------------------------------------------------- #
|
|
328
|
+
# Repositories
|
|
329
|
+
# --------------------------------------------------------------------------- #
|
|
330
|
+
class EnforcementSignal(_View):
|
|
331
|
+
status: str
|
|
332
|
+
detail: str
|
|
333
|
+
checked_at: datetime | None = None
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class RequiredCheckSignal(_View):
|
|
337
|
+
status: RequiredCheckStatus
|
|
338
|
+
branch: str | None
|
|
339
|
+
required_checks: tuple[str, ...]
|
|
340
|
+
detail: str
|
|
341
|
+
checked_at: datetime | None
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class LatestCheckSignal(_View):
|
|
345
|
+
result: ScanResultStatus | None
|
|
346
|
+
scan: str | None
|
|
347
|
+
head_sha: str | None
|
|
348
|
+
completed_at: datetime | None
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
class EnforcementView(_View):
|
|
352
|
+
github_app: EnforcementSignal
|
|
353
|
+
github_actions: EnforcementSignal
|
|
354
|
+
required_check: RequiredCheckSignal
|
|
355
|
+
latest_check: LatestCheckSignal
|
|
356
|
+
local_hooks: EnforcementSignal
|
|
357
|
+
merge_queue: EnforcementSignal
|
|
358
|
+
monitoring_enabled: bool
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class RepositorySummary(_View):
|
|
362
|
+
id: int
|
|
363
|
+
installation_id: int
|
|
364
|
+
organization: OrganizationRef | None
|
|
365
|
+
owner: str
|
|
366
|
+
name: str
|
|
367
|
+
full_name: str
|
|
368
|
+
github_url: str
|
|
369
|
+
default_branch: str | None
|
|
370
|
+
protection: ProtectionStatus
|
|
371
|
+
protection_reason: str
|
|
372
|
+
app_connection: AppConnection
|
|
373
|
+
monitoring_enabled: bool
|
|
374
|
+
last_scan: ScanSummary | None
|
|
375
|
+
open_violations: int
|
|
376
|
+
open_warnings: int
|
|
377
|
+
critical_open: int
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class RepositoryPermissions(_View):
|
|
381
|
+
manage: bool
|
|
382
|
+
trigger_scans: bool
|
|
383
|
+
read_audit: bool
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
class RepositoryDetail(_View):
|
|
387
|
+
repository: RepositorySummary
|
|
388
|
+
enforcement: EnforcementView
|
|
389
|
+
organization_policy_version: int | None
|
|
390
|
+
effective_policies: tuple[PolicyEntry, ...]
|
|
391
|
+
effective_policy_scan: str | None
|
|
392
|
+
recent_scans: tuple[ScanSummary, ...]
|
|
393
|
+
open_violations: tuple[ViolationSummary, ...]
|
|
394
|
+
audit: tuple["AuditEventView", ...]
|
|
395
|
+
permissions: RepositoryPermissions
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class MergeGroupView(_View):
|
|
399
|
+
head_sha: str
|
|
400
|
+
base_sha: str
|
|
401
|
+
base_ref: str
|
|
402
|
+
pull_requests: tuple[int, ...]
|
|
403
|
+
state: Literal["checks_requested", "destroyed"]
|
|
404
|
+
destroyed_reason: str | None
|
|
405
|
+
result: ScanResultStatus | None
|
|
406
|
+
scan: str | None
|
|
407
|
+
created_at: datetime
|
|
408
|
+
updated_at: datetime
|
|
409
|
+
validated_at: datetime | None
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class MergeQueueView(_View):
|
|
413
|
+
repository_id: int
|
|
414
|
+
status: MergeQueueStatus
|
|
415
|
+
detail: str
|
|
416
|
+
checked_at: datetime | None
|
|
417
|
+
permission: Literal["granted", "missing"]
|
|
418
|
+
current: MergeGroupView | None
|
|
419
|
+
recent: tuple[MergeGroupView, ...]
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
# --------------------------------------------------------------------------- #
|
|
423
|
+
# Policies and rules
|
|
424
|
+
# --------------------------------------------------------------------------- #
|
|
425
|
+
class PolicyRuleView(_View):
|
|
426
|
+
policy_id: str
|
|
427
|
+
name: str
|
|
428
|
+
description: str
|
|
429
|
+
default_action: Action
|
|
430
|
+
service_floor: Action | None # operator's mandatory policy file
|
|
431
|
+
organization_floor: Action | None
|
|
432
|
+
minimum_action: Action | None # strongest floor; None = repository decides
|
|
433
|
+
repository_override: Literal["any", "stricter_only"]
|
|
434
|
+
source: Literal[
|
|
435
|
+
"built_in_default", "service_policy", "organization_policy", "organization_default"
|
|
436
|
+
]
|
|
437
|
+
#: A default-strength organization entry: the baseline repositories may change.
|
|
438
|
+
organization_default: Action | None = None
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class PolicyAuthor(_View):
|
|
442
|
+
id: int | None
|
|
443
|
+
login: str | None
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class OrganizationPolicyView(_View):
|
|
447
|
+
organization: OrganizationRef
|
|
448
|
+
version: int
|
|
449
|
+
fingerprint: str | None
|
|
450
|
+
updated_at: datetime | None
|
|
451
|
+
updated_by: PolicyAuthor | None
|
|
452
|
+
reason: str | None
|
|
453
|
+
service_policy: str | None
|
|
454
|
+
rules: tuple[PolicyRuleView, ...]
|
|
455
|
+
can_write: bool
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class PolicyChange(_View):
|
|
459
|
+
policy_id: str
|
|
460
|
+
old: Action | None
|
|
461
|
+
new: Action | None
|
|
462
|
+
weakening: bool
|
|
463
|
+
enforcement: Literal["mandatory", "default"] = "mandatory"
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class PolicyVersionView(_View):
|
|
467
|
+
version: int
|
|
468
|
+
fingerprint: str
|
|
469
|
+
floors: dict[str, Action]
|
|
470
|
+
created_at: datetime
|
|
471
|
+
created_by: PolicyAuthor
|
|
472
|
+
reason: str | None
|
|
473
|
+
status: Literal["active", "archived"]
|
|
474
|
+
kind: Literal["change", "rollback"]
|
|
475
|
+
rollback_of: int | None # rollback: the version that was active before
|
|
476
|
+
restored_version: int | None # rollback: the version whose document was restored
|
|
477
|
+
changes: tuple[PolicyChange, ...] # compared with the previous version
|
|
478
|
+
summary: str
|
|
479
|
+
defaults: dict[str, Action] = {} # default-strength entries (Phase 8)
|
|
480
|
+
draft_id: str | None = None # the reviewed draft this version was published from
|
|
481
|
+
emergency: bool = False # published without the approval workflow
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
class PolicyDiffEntry(_View):
|
|
485
|
+
policy_id: str
|
|
486
|
+
old: Action | None = None
|
|
487
|
+
new: Action | None = None
|
|
488
|
+
weakening: bool = False
|
|
489
|
+
enforcement: Literal["mandatory", "default"] = "mandatory"
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class PolicyDiffView(_View):
|
|
493
|
+
from_version: int
|
|
494
|
+
to_version: int
|
|
495
|
+
added: tuple[PolicyDiffEntry, ...]
|
|
496
|
+
changed: tuple[PolicyDiffEntry, ...]
|
|
497
|
+
removed: tuple[PolicyDiffEntry, ...]
|
|
498
|
+
weakening: bool
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class PolicyTargetView(_View):
|
|
502
|
+
type: Literal["organization", "group", "repository"]
|
|
503
|
+
id: str # "" for the organization, a group ID or a repository ID
|
|
504
|
+
label: str
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class ScopedRuleView(_View):
|
|
508
|
+
policy_id: str
|
|
509
|
+
name: str
|
|
510
|
+
mandatory: Action | None
|
|
511
|
+
default: Action | None
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class ScopedPolicyView(_View):
|
|
515
|
+
"""A repository group's or repository's published policy."""
|
|
516
|
+
|
|
517
|
+
organization: OrganizationRef
|
|
518
|
+
target: PolicyTargetView
|
|
519
|
+
version: int # 0: nothing published yet
|
|
520
|
+
fingerprint: str | None
|
|
521
|
+
updated_at: datetime | None
|
|
522
|
+
updated_by: PolicyAuthor | None
|
|
523
|
+
reason: str | None
|
|
524
|
+
rules: tuple[ScopedRuleView, ...]
|
|
525
|
+
can_write: bool
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
class RuleView(_View):
|
|
529
|
+
id: str
|
|
530
|
+
name: str
|
|
531
|
+
description: str
|
|
532
|
+
detector: str
|
|
533
|
+
severity: Severity
|
|
534
|
+
default_action: Action
|
|
535
|
+
source: Literal["bundled"]
|
|
536
|
+
trusted: bool
|
|
537
|
+
status: Literal["active"]
|
|
538
|
+
rules_version: str
|
|
539
|
+
tool_version: str
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
class RuleDataFile(_View):
|
|
543
|
+
name: str
|
|
544
|
+
entries: int
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
class RuleDetail(_View):
|
|
548
|
+
rule: RuleView
|
|
549
|
+
remediation: tuple[str, ...]
|
|
550
|
+
evidence_sources: tuple[str, ...]
|
|
551
|
+
data_files: tuple[RuleDataFile, ...]
|
|
552
|
+
editable: bool
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
# --------------------------------------------------------------------------- #
|
|
556
|
+
# Audit
|
|
557
|
+
# --------------------------------------------------------------------------- #
|
|
558
|
+
class AuditEventView(_View):
|
|
559
|
+
id: str
|
|
560
|
+
type: str
|
|
561
|
+
occurred_at: datetime
|
|
562
|
+
actor: ActorView
|
|
563
|
+
organization_id: int | None
|
|
564
|
+
installation_id: int | None
|
|
565
|
+
repository: RepositoryLink | None
|
|
566
|
+
head_sha: str | None
|
|
567
|
+
action: Action | None
|
|
568
|
+
summary: str
|
|
569
|
+
data: dict[str, str | int | bool | None]
|
|
570
|
+
scan: str | None
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
# --------------------------------------------------------------------------- #
|
|
574
|
+
# GitHub
|
|
575
|
+
# --------------------------------------------------------------------------- #
|
|
576
|
+
class InstallationView(_View):
|
|
577
|
+
id: int
|
|
578
|
+
account: OrganizationRef
|
|
579
|
+
status: AppConnection
|
|
580
|
+
repository_selection: str
|
|
581
|
+
repositories: int
|
|
582
|
+
permissions: dict[str, str]
|
|
583
|
+
missing_permissions: tuple[str, ...]
|
|
584
|
+
excessive_permissions: tuple[str, ...]
|
|
585
|
+
installed_at: datetime
|
|
586
|
+
updated_at: datetime
|
|
587
|
+
last_event_at: datetime | None
|
|
588
|
+
github_settings_url: str
|
|
589
|
+
can_manage: bool
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
class InstallationRepositoryView(_View):
|
|
593
|
+
id: int
|
|
594
|
+
full_name: str
|
|
595
|
+
connected: bool
|
|
596
|
+
monitoring_enabled: bool
|
|
597
|
+
added_at: datetime | None
|
|
598
|
+
removed_at: datetime | None
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class InstallationDetail(_View):
|
|
602
|
+
installation: InstallationView
|
|
603
|
+
recent_events: tuple[AuditEventView, ...]
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
class SyncResult(_View):
|
|
607
|
+
installation_id: int
|
|
608
|
+
repositories: int
|
|
609
|
+
added: tuple[str, ...]
|
|
610
|
+
removed: tuple[str, ...]
|
|
611
|
+
synced_at: datetime
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
# --------------------------------------------------------------------------- #
|
|
615
|
+
# Overview
|
|
616
|
+
# --------------------------------------------------------------------------- #
|
|
617
|
+
class OverviewPeriod(_View):
|
|
618
|
+
key: Literal["24h", "7d", "30d"]
|
|
619
|
+
start: datetime
|
|
620
|
+
end: datetime
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
class OverviewSummary(_View):
|
|
624
|
+
repositories_monitored: int
|
|
625
|
+
repositories_protected: int
|
|
626
|
+
repositories_at_risk: int
|
|
627
|
+
repositories_unprotected: int
|
|
628
|
+
repositories_unknown: int
|
|
629
|
+
repositories_configuration_error: int
|
|
630
|
+
scans: int
|
|
631
|
+
scans_passed: int
|
|
632
|
+
scans_blocked: int
|
|
633
|
+
scans_error: int
|
|
634
|
+
open_violations: int
|
|
635
|
+
open_warnings: int
|
|
636
|
+
critical_open: int
|
|
637
|
+
high_open: int
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
class IntegrationView(_View):
|
|
641
|
+
status: IntegrationStatus
|
|
642
|
+
installations_connected: int
|
|
643
|
+
installations_suspended: int
|
|
644
|
+
installations_disconnected: int
|
|
645
|
+
detail: str
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
class HealthCheck(_View):
|
|
649
|
+
id: str
|
|
650
|
+
label: str
|
|
651
|
+
status: HealthCheckStatus
|
|
652
|
+
detail: str
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
class OverviewView(_View):
|
|
656
|
+
period: OverviewPeriod
|
|
657
|
+
summary: OverviewSummary
|
|
658
|
+
integration: IntegrationView
|
|
659
|
+
health: tuple[HealthCheck, ...]
|
|
660
|
+
recent_scans: tuple[ScanSummary, ...]
|
|
661
|
+
recent_violations: tuple[ViolationSummary, ...]
|
|
662
|
+
repository_health: tuple[RepositorySummary, ...]
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
# --------------------------------------------------------------------------- #
|
|
666
|
+
# Notifications
|
|
667
|
+
# --------------------------------------------------------------------------- #
|
|
668
|
+
class NotificationView(_View):
|
|
669
|
+
id: str
|
|
670
|
+
type: str
|
|
671
|
+
category: str
|
|
672
|
+
severity: Severity
|
|
673
|
+
state: Literal["unread", "read", "archived"]
|
|
674
|
+
title: str
|
|
675
|
+
body: str
|
|
676
|
+
organization_id: int
|
|
677
|
+
repository: RepositoryLink | None
|
|
678
|
+
resource_type: str
|
|
679
|
+
resource_id: str
|
|
680
|
+
link: str | None
|
|
681
|
+
occurrences: int
|
|
682
|
+
created_at: datetime
|
|
683
|
+
last_occurred_at: datetime
|
|
684
|
+
read_at: datetime | None
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class NotificationCounts(_View):
|
|
688
|
+
unread: int # at most 1000
|
|
689
|
+
unread_critical: int
|
|
690
|
+
capped: bool # more unread notifications than counted
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
class ChannelPreferenceView(_View):
|
|
694
|
+
in_app: bool
|
|
695
|
+
email: bool
|
|
696
|
+
webhook: bool
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
class TypePreferenceView(_View):
|
|
700
|
+
type: str
|
|
701
|
+
label: str
|
|
702
|
+
description: str
|
|
703
|
+
category: str
|
|
704
|
+
mandatory_in_app: bool
|
|
705
|
+
organization: ChannelPreferenceView
|
|
706
|
+
personal_in_app: bool # the member's own inbox (always true when mandatory)
|
|
707
|
+
receives_in_app: bool # the member's role receives this type at all
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
class NotificationChannelsView(_View):
|
|
711
|
+
in_app: bool
|
|
712
|
+
email: bool
|
|
713
|
+
webhook: bool
|
|
714
|
+
mode: Literal["off", "deliver", "test"]
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
class WebhookEndpointView(_View):
|
|
718
|
+
id: str
|
|
719
|
+
url: str
|
|
720
|
+
created_at: datetime
|
|
721
|
+
created_by: str | None
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
class NotificationDeliveryView(_View):
|
|
725
|
+
id: str
|
|
726
|
+
notification_type: str
|
|
727
|
+
title: str
|
|
728
|
+
channel: str
|
|
729
|
+
destination: str
|
|
730
|
+
status: Literal["pending", "sent", "failed", "cancelled"]
|
|
731
|
+
attempts: int
|
|
732
|
+
failure_code: str | None
|
|
733
|
+
last_attempt_at: datetime | None
|
|
734
|
+
next_retry_at: datetime | None
|
|
735
|
+
created_at: datetime
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
class OrganizationNotificationSettingsView(_View):
|
|
739
|
+
organization: OrganizationRef
|
|
740
|
+
version: int
|
|
741
|
+
updated_at: datetime | None
|
|
742
|
+
updated_by: str | None
|
|
743
|
+
channels: NotificationChannelsView
|
|
744
|
+
types: tuple[TypePreferenceView, ...]
|
|
745
|
+
email_recipients: tuple[str, ...] # only for notifications:manage
|
|
746
|
+
webhooks: tuple[WebhookEndpointView, ...] # only for notifications:manage
|
|
747
|
+
can_manage: bool
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
class CreatedWebhookView(_View):
|
|
751
|
+
endpoint: WebhookEndpointView
|
|
752
|
+
signing_secret: str # shown once; CommitGuard does not store it
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
# --------------------------------------------------------------------------- #
|
|
756
|
+
# Accounts, members and sessions
|
|
757
|
+
# --------------------------------------------------------------------------- #
|
|
758
|
+
class OrganizationView(_View):
|
|
759
|
+
organization: OrganizationRef
|
|
760
|
+
role: str
|
|
761
|
+
implicit_role: bool
|
|
762
|
+
permissions: tuple[str, ...]
|
|
763
|
+
installation_ids: tuple[int, ...]
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
class MemberView(_View):
|
|
767
|
+
user_id: int
|
|
768
|
+
login: str | None
|
|
769
|
+
role: str
|
|
770
|
+
granted_by: str
|
|
771
|
+
created_at: datetime
|
|
772
|
+
updated_at: datetime
|
|
773
|
+
implicit: bool
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
class SessionView(_View):
|
|
777
|
+
id: str
|
|
778
|
+
created_at: datetime
|
|
779
|
+
last_seen_at: datetime
|
|
780
|
+
expires_at: datetime
|
|
781
|
+
user_agent: str
|
|
782
|
+
current: bool
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
class UserView(_View):
|
|
786
|
+
id: int
|
|
787
|
+
login: str
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
class SessionInfo(_View):
|
|
791
|
+
user: UserView
|
|
792
|
+
session: SessionView
|
|
793
|
+
csrf_token: str
|
|
794
|
+
organizations: tuple[OrganizationView, ...]
|
|
795
|
+
reauthentication_required_after: datetime
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
RepositoryDetail.model_rebuild()
|
|
799
|
+
ScanDetail.model_rebuild()
|