@vivswan/github-settings-as-code 0.0.0 → 2.0.1-main.658.20260922.gdcb742f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4128 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "#/definitions/SettingsFile",
4
+ "$id": "https://raw.githubusercontent.com/Vivswan/github-settings-as-code/HEAD/lib/settings.schema.json",
5
+ "definitions": {
6
+ "ActionsConfig": {
7
+ "description": "GitHub Actions settings, routed to the right endpoint by key.",
8
+ "type": "object",
9
+ "properties": {
10
+ "enabled": {
11
+ "description": "PUT /repos/{r}/actions/permissions: whether Actions runs at all.",
12
+ "type": "boolean"
13
+ },
14
+ "allowed_actions": {
15
+ "description": "Which actions may run; \"selected\" pairs with selected_actions below.",
16
+ "type": "string",
17
+ "enum": [
18
+ "all",
19
+ "local_only",
20
+ "selected"
21
+ ]
22
+ },
23
+ "sha_pinning_required": {
24
+ "description": "Whether actions must be pinned to a full-length commit SHA.",
25
+ "type": "boolean"
26
+ },
27
+ "selected_actions": {
28
+ "description": "PUT /repos/{r}/actions/permissions/selected-actions (allowed_actions: selected): the allowlist, e.g. { github_owned_allowed: true, patterns_allowed: [octocat/*] }. Only the three documented keys are accepted, so a misspelled one is refused instead of re-sent on every run.",
29
+ "type": "object",
30
+ "properties": {
31
+ "github_owned_allowed": {
32
+ "description": "Whether actions in GitHub's own organizations (such as actions/*) may run.",
33
+ "type": "boolean"
34
+ },
35
+ "verified_allowed": {
36
+ "description": "Whether actions by GitHub Marketplace verified creators may run.",
37
+ "type": "boolean"
38
+ },
39
+ "patterns_allowed": {
40
+ "description": "Patterns naming the actions and reusable workflows allowed to run, e.g. octocat/hello-world@v2 or octocat/*; GitHub applies them to public repositories only.",
41
+ "type": "array",
42
+ "items": {
43
+ "type": "string"
44
+ }
45
+ }
46
+ },
47
+ "additionalProperties": false
48
+ },
49
+ "default_workflow_permissions": {
50
+ "description": "PUT /repos/{r}/actions/permissions/workflow: the default GITHUB_TOKEN grant.",
51
+ "type": "string",
52
+ "enum": [
53
+ "read",
54
+ "write"
55
+ ]
56
+ },
57
+ "can_approve_pull_request_reviews": {
58
+ "description": "Whether workflows may approve pull request reviews.",
59
+ "type": "boolean"
60
+ },
61
+ "access_level": {
62
+ "description": "PUT /repos/{r}/actions/permissions/access (private repositories only)",
63
+ "type": "string",
64
+ "enum": [
65
+ "none",
66
+ "user",
67
+ "organization"
68
+ ]
69
+ },
70
+ "artifact_and_log_retention": {
71
+ "description": "PUT /repos/{r}/actions/permissions/artifact-and-log-retention: how many days artifacts and workflow logs are kept, e.g. { days: 90 }. The body passes through verbatim, so future fields GitHub adds work unchanged, and a key the GET never echoes is noted at check time as never converging; maximum_allowed_days, which the GET reports and the PUT does not take, is refused.",
72
+ "type": "object",
73
+ "properties": {
74
+ "days": {
75
+ "description": "How many days artifacts and workflow logs are kept; a whole number of days within the plan's maximum.",
76
+ "type": "integer",
77
+ "exclusiveMinimum": 0
78
+ }
79
+ },
80
+ "required": [
81
+ "days"
82
+ ]
83
+ },
84
+ "cache": {
85
+ "description": "Actions cache limits, each key routed to its own endpoint: max_cache_retention_days -> PUT /repos/{r}/actions/cache/retention-limit, max_cache_size_gb -> PUT /repos/{r}/actions/cache/storage-limit. Keys other than these two are rejected (each limit has its own single-field endpoint, so an extra key could only be a typo).",
86
+ "type": "object",
87
+ "properties": {
88
+ "max_cache_retention_days": {
89
+ "description": "How many days an unused cache entry is kept before GitHub evicts it.",
90
+ "type": "integer",
91
+ "exclusiveMinimum": 0
92
+ },
93
+ "max_cache_size_gb": {
94
+ "description": "The total cache storage the repository may use, in GB.",
95
+ "type": "integer",
96
+ "exclusiveMinimum": 0
97
+ }
98
+ },
99
+ "additionalProperties": false
100
+ },
101
+ "oidc_customization_sub": {
102
+ "description": "PUT /repos/{r}/actions/oidc/customization/sub: the OIDC subject claim template for this repository's workflow tokens, e.g. { use_default: false, include_claim_keys: [repo, context] }, an endpoint pair that needs the \"Actions\" PAT permission rather than Administration. A list under use_default: true is refused, since GitHub ignores it; so is sub_claim_prefix, which only the GET reports. Other keys pass through verbatim, and one the GET never echoes is noted at check time as never converging.",
103
+ "oneOf": [
104
+ {
105
+ "type": "object",
106
+ "properties": {
107
+ "use_default": {
108
+ "description": "true: GitHub's default subject claim format; this variant carries no claim-key list.",
109
+ "type": "boolean",
110
+ "const": true
111
+ },
112
+ "use_immutable_subject": {
113
+ "description": "Switch the whole subject to the stable repository-ID-based format; omitted, the organization setting or the repository's creation date decides, and only a declared value is compared.",
114
+ "type": "boolean"
115
+ }
116
+ },
117
+ "required": [
118
+ "use_default"
119
+ ]
120
+ },
121
+ {
122
+ "type": "object",
123
+ "properties": {
124
+ "use_default": {
125
+ "description": "false: a custom template, joined from include_claim_keys.",
126
+ "type": "boolean",
127
+ "const": false
128
+ },
129
+ "include_claim_keys": {
130
+ "description": "The claim keys the custom subject joins, in order (e.g. repo, context); each is unique and holds only letters, digits, and underscores. Claim-key ORDER defines the subject format, so check mode compares a declared list positionally; an omitted list opts into the organization template and is not compared.",
131
+ "type": "array",
132
+ "items": {
133
+ "type": "string",
134
+ "pattern": "^[A-Za-z0-9_]+$"
135
+ }
136
+ },
137
+ "use_immutable_subject": {
138
+ "description": "Switch the whole subject to the stable repository-ID-based format; omitted, the organization setting or the repository's creation date decides, and only a declared value is compared.",
139
+ "type": "boolean"
140
+ }
141
+ },
142
+ "required": [
143
+ "use_default"
144
+ ]
145
+ }
146
+ ]
147
+ },
148
+ "fork_pr_contributor_approval": {
149
+ "description": "PUT /repos/{r}/actions/permissions/fork-pr-contributor-approval: when workflows triggered by fork pull requests need a maintainer's approval before they run, e.g. { approval_policy: first_time_contributors }. The policies GitHub accepts are first_time_contributors_new_to_github, first_time_contributors, and all_external_contributors; any other value is refused when the file is parsed. The body passes through verbatim, so future fields GitHub adds work unchanged, and a key the GET never echoes is noted at check time as never converging.",
150
+ "type": "object",
151
+ "properties": {
152
+ "approval_policy": {
153
+ "description": "Which fork contributors need a maintainer's approval before their workflows run: first_time_contributors_new_to_github, first_time_contributors, or all_external_contributors.",
154
+ "type": "string",
155
+ "enum": [
156
+ "first_time_contributors_new_to_github",
157
+ "first_time_contributors",
158
+ "all_external_contributors"
159
+ ]
160
+ }
161
+ },
162
+ "required": [
163
+ "approval_policy"
164
+ ]
165
+ },
166
+ "fork_pr_workflows_private_repos": {
167
+ "description": "PUT /repos/{r}/actions/permissions/fork-pr-workflows-private-repos: whether pull requests from forks may run workflows on this private repository, and what those workflows receive. Only run_workflows_from_fork_pull_requests is required; GitHub does not document whether the PUT preserves an omitted toggle, so declare all four. Other keys pass through verbatim, and one the GET never echoes is noted at check time as never converging.",
168
+ "type": "object",
169
+ "properties": {
170
+ "run_workflows_from_fork_pull_requests": {
171
+ "description": "Whether pull requests from forks may run workflows at all.",
172
+ "type": "boolean"
173
+ },
174
+ "send_write_tokens_to_workflows": {
175
+ "description": "Whether those workflows receive a GITHUB_TOKEN with write permissions.",
176
+ "type": "boolean"
177
+ },
178
+ "send_secrets_and_variables": {
179
+ "description": "Whether those workflows receive the repository's secrets and variables.",
180
+ "type": "boolean"
181
+ },
182
+ "require_approval_for_fork_pr_workflows": {
183
+ "description": "Whether a repository administrator must approve each fork workflow run before it starts.",
184
+ "type": "boolean"
185
+ }
186
+ },
187
+ "required": [
188
+ "run_workflows_from_fork_pull_requests"
189
+ ]
190
+ }
191
+ }
192
+ },
193
+ "ActionsSecretConfig": {
194
+ "description": "One repository Actions secret, matched by case-insensitive name (GitHub stores secret names uppercase). Keys other than name and value are rejected: the API body is built from the sealed value alone, so an extra key would silently do nothing.",
195
+ "type": "object",
196
+ "properties": {
197
+ "name": {
198
+ "description": "The secret name, the natural key; compared case-insensitively and written uppercase. GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case (`github_token` is the reserved `GITHUB_TOKEN` once uppercased).",
199
+ "type": "string",
200
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
201
+ },
202
+ "value": {
203
+ "description": "A whole-value `$NAME` reference to an environment variable holding the secret - never a literal (settings files are committed plaintext). Resolved from the action step's env at run time and sealed client-side into the sealed box GitHub's secrets API expects (libsodium's crypto_box_seal format) before upload; GitHub cannot return the value, so check mode verifies existence only and apply re-seals it on every run.",
204
+ "type": "string"
205
+ }
206
+ },
207
+ "required": [
208
+ "name",
209
+ "value"
210
+ ]
211
+ },
212
+ "ActionsVariableConfig": {
213
+ "description": "One GitHub Actions repository variable, matched by case-insensitive name; workflows read it through the `vars` context.",
214
+ "type": "object",
215
+ "properties": {
216
+ "name": {
217
+ "description": "The variable name, the natural key; case-insensitive (stored uppercased by GitHub). GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case.",
218
+ "type": "string",
219
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
220
+ },
221
+ "value": {
222
+ "description": "The plain-text value. GitHub caps one variable at 48 KB; a value over 49152 bytes of UTF-8 is refused when the file is parsed, before any API call.",
223
+ "type": "string",
224
+ "maxLength": 49152
225
+ }
226
+ },
227
+ "required": [
228
+ "name",
229
+ "value"
230
+ ]
231
+ },
232
+ "AgentsSecretConfig": {
233
+ "description": "One repository Copilot agents secret, matched by case-insensitive name (GitHub stores secret names uppercase). Keys other than name and value are rejected: the API body is built from the sealed value alone, so an extra key would silently do nothing.",
234
+ "type": "object",
235
+ "properties": {
236
+ "name": {
237
+ "description": "The secret name, the natural key; compared case-insensitively and written uppercase. GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case (`github_token` is the reserved `GITHUB_TOKEN` once uppercased).",
238
+ "type": "string",
239
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
240
+ },
241
+ "value": {
242
+ "description": "A whole-value `$NAME` reference to an environment variable holding the secret - never a literal (settings files are committed plaintext). Resolved from the action step's env at run time and sealed client-side into the sealed box GitHub's secrets API expects (libsodium's crypto_box_seal format) before upload; GitHub cannot return the value, so check mode verifies existence only and apply re-seals it on every run.",
243
+ "type": "string"
244
+ }
245
+ },
246
+ "required": [
247
+ "name",
248
+ "value"
249
+ ]
250
+ },
251
+ "AgentsVariableConfig": {
252
+ "description": "One Copilot agents repository variable, matched by case-insensitive name.",
253
+ "type": "object",
254
+ "properties": {
255
+ "name": {
256
+ "description": "The variable name, the natural key; case-insensitive (stored uppercased by GitHub). GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case.",
257
+ "type": "string",
258
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
259
+ },
260
+ "value": {
261
+ "description": "The plain-text value. GitHub caps one variable at 48 KB; a value over 49152 bytes of UTF-8 is refused when the file is parsed, before any API call.",
262
+ "type": "string",
263
+ "maxLength": 49152
264
+ }
265
+ },
266
+ "required": [
267
+ "name",
268
+ "value"
269
+ ]
270
+ },
271
+ "AutoTriggerCheckConfig": {
272
+ "description": "One per-app auto-trigger toggle. Extra fields pass through verbatim.",
273
+ "type": "object",
274
+ "properties": {
275
+ "app_id": {
276
+ "description": "The id of the GitHub App the preference applies to: a positive integer (the App's settings page shows it), declared once. 0, fractions, and a repeated app_id fail at parse time; GitHub has no app 0, rejects fractions, and would keep whichever duplicate it reads last with nothing to read it back.",
277
+ "type": "integer",
278
+ "exclusiveMinimum": 0
279
+ },
280
+ "setting": {
281
+ "description": "Whether pushes automatically create check suites for this app; GitHub defaults each app to true.",
282
+ "type": "boolean"
283
+ }
284
+ },
285
+ "required": [
286
+ "app_id",
287
+ "setting"
288
+ ]
289
+ },
290
+ "AutolinkConfig": {
291
+ "description": "One autolink reference, matched by key prefix.",
292
+ "type": "object",
293
+ "properties": {
294
+ "key_prefix": {
295
+ "description": "Text prefix that triggers the link (e.g. \"TICKET-\"), the natural key; letters, digits, and \". - _ + = : / #\" only, and no declared prefix may begin another.",
296
+ "type": "string",
297
+ "pattern": "^[A-Za-z0-9.\\-_+=:/#]+$"
298
+ },
299
+ "url_template": {
300
+ "description": "Target URL template containing \"<num>\".",
301
+ "type": "string",
302
+ "pattern": "<num>"
303
+ },
304
+ "is_alphanumeric": {
305
+ "description": "Whether <num> also matches letters; upstream default is true on a create, and a recreate re-sends the live value when undeclared.",
306
+ "type": "boolean"
307
+ }
308
+ },
309
+ "required": [
310
+ "key_prefix",
311
+ "url_template"
312
+ ]
313
+ },
314
+ "BranchConfig": {
315
+ "description": "Classic protection for one branch name or wildcard pattern.",
316
+ "type": "object",
317
+ "properties": {
318
+ "name": {
319
+ "description": "The branch name, or a wildcard pattern (any name containing `*`, `?`, or `[`, e.g. \"release/*\"). A literal name applies through the REST protection endpoints; a wildcard rule is REST-invisible, so it applies entirely through the GraphQL branch-protection-rule mutations and its protection accepts only the keys this action can round-trip through that surface (the validator names them; prefer rulesets for new pattern-based configuration).",
320
+ "type": "string"
321
+ },
322
+ "protection": {
323
+ "description": "PUT .../protection payload; null removes protection (Probot parity).",
324
+ "anyOf": [
325
+ {
326
+ "$ref": "#/definitions/BranchProtectionConfig"
327
+ },
328
+ {
329
+ "type": "null"
330
+ }
331
+ ]
332
+ }
333
+ },
334
+ "required": [
335
+ "name",
336
+ "protection"
337
+ ]
338
+ },
339
+ "BranchProtectionConfig": {
340
+ "description": "The protection PUT payload, passed through verbatim except its routed keys; a key the GET never echoes is noted at check time as never converging. What the file alone shows wrong is refused upfront, naming the fix: the GET-only keys a copied GET response carries (`name`, `enabled`, `enforcement_level`, `url` and `*_url`, at any depth), a status-check requirement without `strict` or a check list, and a review count outside 0-6.",
341
+ "type": "object",
342
+ "properties": {
343
+ "required_status_checks": {
344
+ "description": "Require status checks to pass before merging; `null` turns the requirement off. A mapping carries `strict` and one of `contexts` or `checks`, since GitHub's protection PUT rejects the requirement without either.",
345
+ "anyOf": [
346
+ {
347
+ "type": "object",
348
+ "properties": {
349
+ "strict": {
350
+ "description": "Whether the branch must also be up to date with its base before merging; `false` requires only the checks to pass.",
351
+ "type": "boolean"
352
+ },
353
+ "contexts": {
354
+ "description": "The required checks by name; `[]` keeps the requirement on while requiring none.",
355
+ "type": "array",
356
+ "items": {
357
+ "type": "string"
358
+ }
359
+ },
360
+ "checks": {
361
+ "description": "The required checks as {context, app_id} pairs, the PUT's second spelling of the list; the names are derived into `contexts` for the PUT when the file declares only `checks`. GitHub's PUT takes no other field in an item, so any other key is refused upfront, named, with the fix.",
362
+ "type": "array",
363
+ "items": {
364
+ "type": "object",
365
+ "properties": {
366
+ "context": {
367
+ "description": "The name of the required check.",
368
+ "type": "string"
369
+ },
370
+ "app_id": {
371
+ "description": "The id of the GitHub App that must report the check. `-1` lets any App report it (`null`, GitHub's read-back spelling of the same, is sent as `-1`); an omitted id pins whichever App reported it last.",
372
+ "type": [
373
+ "integer",
374
+ "null"
375
+ ]
376
+ }
377
+ },
378
+ "required": [
379
+ "context"
380
+ ],
381
+ "additionalProperties": false
382
+ }
383
+ }
384
+ },
385
+ "required": [
386
+ "strict"
387
+ ],
388
+ "additionalProperties": {},
389
+ "anyOf": [
390
+ {
391
+ "required": [
392
+ "contexts"
393
+ ]
394
+ },
395
+ {
396
+ "required": [
397
+ "checks"
398
+ ]
399
+ }
400
+ ]
401
+ },
402
+ {
403
+ "type": "null"
404
+ }
405
+ ]
406
+ },
407
+ "required_pull_request_reviews": {
408
+ "description": "Require pull request reviews before merging; `null` turns the requirement off. Every review setting beside the count and the two actor holders (`dismiss_stale_reviews`, `require_code_owner_reviews`, ...) passes through to the PUT.",
409
+ "anyOf": [
410
+ {
411
+ "type": "object",
412
+ "properties": {
413
+ "required_approving_review_count": {
414
+ "description": "Approving reviews required before merging: 1 to 6, or 0 to require no approvals. GitHub accepts no other value, so the file is refused upfront instead of the PUT failing at apply.",
415
+ "type": "integer",
416
+ "minimum": 0,
417
+ "maximum": 6
418
+ },
419
+ "dismissal_restrictions": {
420
+ "description": "Who may dismiss pull request reviews, as `users`, `teams`, and `apps` lists of login/slug strings, each list optional; an empty mapping lets anyone with push access dismiss. GitHub's GET expands each actor into an object, which the PUT rejects, so a copied one is refused naming the string to write.",
421
+ "type": "object",
422
+ "properties": {
423
+ "users": {
424
+ "description": "User logins (\"octocat\").",
425
+ "type": "array",
426
+ "items": {
427
+ "type": "string"
428
+ }
429
+ },
430
+ "teams": {
431
+ "description": "Team slugs (\"platform-team\").",
432
+ "type": "array",
433
+ "items": {
434
+ "type": "string"
435
+ }
436
+ },
437
+ "apps": {
438
+ "description": "GitHub App slugs (\"deploy-gate\").",
439
+ "type": "array",
440
+ "items": {
441
+ "type": "string"
442
+ }
443
+ }
444
+ },
445
+ "additionalProperties": {}
446
+ },
447
+ "bypass_pull_request_allowances": {
448
+ "description": "Who may push without a pull request review, as `users`, `teams`, and `apps` lists of login/slug strings, each list optional. GitHub's GET expands each actor into an object, which the PUT rejects, so a copied one is refused naming the string to write.",
449
+ "type": "object",
450
+ "properties": {
451
+ "users": {
452
+ "description": "User logins (\"octocat\").",
453
+ "type": "array",
454
+ "items": {
455
+ "type": "string"
456
+ }
457
+ },
458
+ "teams": {
459
+ "description": "Team slugs (\"platform-team\").",
460
+ "type": "array",
461
+ "items": {
462
+ "type": "string"
463
+ }
464
+ },
465
+ "apps": {
466
+ "description": "GitHub App slugs (\"deploy-gate\").",
467
+ "type": "array",
468
+ "items": {
469
+ "type": "string"
470
+ }
471
+ }
472
+ },
473
+ "additionalProperties": {}
474
+ }
475
+ },
476
+ "additionalProperties": {}
477
+ },
478
+ {
479
+ "type": "null"
480
+ }
481
+ ]
482
+ },
483
+ "restrictions": {
484
+ "description": "Who may push to the branch, as `users`, `teams`, and `apps` lists of login/slug strings; the PUT requires `users` and `teams` (`[]` when none) and takes `apps` as optional, so a mapping missing either is refused upfront. An all-empty mapping lets nobody push, `null` lifts the restriction, and a copied GET actor object is refused naming the string to write. Literal branches only; wildcard rules point at the rulesets section.",
485
+ "anyOf": [
486
+ {
487
+ "type": "object",
488
+ "properties": {
489
+ "users": {
490
+ "description": "User logins (\"octocat\"); required, `[]` when none.",
491
+ "type": "array",
492
+ "items": {
493
+ "type": "string"
494
+ }
495
+ },
496
+ "teams": {
497
+ "description": "Team slugs (\"platform-team\"); required, `[]` when none.",
498
+ "type": "array",
499
+ "items": {
500
+ "type": "string"
501
+ }
502
+ },
503
+ "apps": {
504
+ "description": "GitHub App slugs (\"deploy-gate\"); optional.",
505
+ "type": "array",
506
+ "items": {
507
+ "type": "string"
508
+ }
509
+ }
510
+ },
511
+ "required": [
512
+ "users",
513
+ "teams"
514
+ ],
515
+ "additionalProperties": {}
516
+ },
517
+ {
518
+ "type": "null"
519
+ }
520
+ ]
521
+ },
522
+ "required_signatures": {
523
+ "description": "Require signed commits on the branch. On a literal branch this is a routed key the protection PUT silently drops, so it is applied through the POST/DELETE .../protection/required_signatures sub-endpoint: when it drifts, and again after any protection PUT (GitHub does not document whether the PUT preserves an existing requirement), so declare the toggle on any branch that carries one - a declared value is pinned either way. On a wildcard rule it rides the GraphQL rule mutation like every other key.",
524
+ "type": "boolean"
525
+ },
526
+ "force_push_bypassers": {
527
+ "description": "Who may force-push to the branch when \"allow force pushes\" is in its \"specify who\" mode. Each actor is one string: a bare login is a user (\"octocat\"), \"org/team-slug\" is a team, and \"app/slug\" is a GitHub App. A REST-invisible surface: on a literal branch this routed key is stripped from the protection PUT and applied through the updateBranchProtectionRule GraphQL mutation when it drifts, and again after any protection PUT; on a wildcard rule it rides the create or update mutation with the rest of the rule. The live list is read back through GraphQL. An empty list clears every allowance; an absent key leaves the live list untouched.",
528
+ "type": "array",
529
+ "items": {
530
+ "type": "string"
531
+ }
532
+ },
533
+ "required_deployments": {
534
+ "description": "Require deployments to succeed before merging (the checkbox and its environment list). REST-invisible like force_push_bypassers, so the routed key rides the same GraphQL mutation. Declaring `null` turns the requirement OFF; an absent key leaves the live state untouched. GitHub SILENTLY drops environment names that do not exist on the repository, so apply verifies the mutation's read-back and fails loudly naming any dropped name; the environments section runs before branches, so environments declared in the same settings file exist by the time this key applies.",
535
+ "anyOf": [
536
+ {
537
+ "type": "object",
538
+ "properties": {
539
+ "environments": {
540
+ "description": "The environments whose deployments must succeed before merging.",
541
+ "type": "array",
542
+ "items": {
543
+ "type": "string"
544
+ }
545
+ }
546
+ },
547
+ "required": [
548
+ "environments"
549
+ ],
550
+ "additionalProperties": false
551
+ },
552
+ {
553
+ "type": "null"
554
+ }
555
+ ]
556
+ }
557
+ },
558
+ "additionalProperties": {}
559
+ },
560
+ "BypassActorConfig": {
561
+ "description": "One actor that may bypass the ruleset. Integration, RepositoryRole, Team, and User need their numeric actor_id; DeployKey takes none (null); OrganizationAdmin ignores it.",
562
+ "type": "object",
563
+ "properties": {
564
+ "actor_id": {
565
+ "description": "The id GitHub assigns the app, role, team, or user. Required for Integration, RepositoryRole, Team, and User; refused for DeployKey (write null or omit it); ignored for OrganizationAdmin.",
566
+ "type": [
567
+ "integer",
568
+ "null"
569
+ ]
570
+ },
571
+ "actor_type": {
572
+ "description": "Integration, OrganizationAdmin, RepositoryRole, Team, DeployKey, or User, as GitHub spells them.",
573
+ "type": "string",
574
+ "enum": [
575
+ "Integration",
576
+ "OrganizationAdmin",
577
+ "RepositoryRole",
578
+ "Team",
579
+ "DeployKey",
580
+ "User"
581
+ ]
582
+ },
583
+ "bypass_mode": {
584
+ "description": "\"always\" (the default), \"pull_request\" (bypass only through a pull request; branch rulesets only, and never for a DeployKey), or \"exempt\" (rules are not run for the actor).",
585
+ "type": "string",
586
+ "enum": [
587
+ "always",
588
+ "pull_request",
589
+ "exempt"
590
+ ]
591
+ }
592
+ },
593
+ "required": [
594
+ "actor_type"
595
+ ],
596
+ "additionalProperties": {}
597
+ },
598
+ "CheckSuitePreferencesConfig": {
599
+ "description": "PATCH /repos/{r}/check-suites/preferences, sent verbatim. Write-only upstream: GitHub exposes no read endpoint for these preferences, so check mode cannot verify them and apply re-asserts the declared preferences on every run.",
600
+ "type": "object",
601
+ "properties": {
602
+ "auto_trigger_checks": {
603
+ "description": "Per-app toggles for whether pushes automatically create check suites, one entry per app_id.",
604
+ "type": "array",
605
+ "items": {
606
+ "$ref": "#/definitions/AutoTriggerCheckConfig"
607
+ }
608
+ }
609
+ },
610
+ "required": [
611
+ "auto_trigger_checks"
612
+ ],
613
+ "additionalProperties": {
614
+ "description": "Future preference fields pass through verbatim."
615
+ }
616
+ },
617
+ "CodeQualitySetupConfig": {
618
+ "description": "PATCH /repos/{r}/code-quality/setup, sent verbatim.",
619
+ "type": "object",
620
+ "properties": {
621
+ "state": {
622
+ "description": "Turn code quality analysis on (\"configured\") or off (\"not-configured\").",
623
+ "type": "string",
624
+ "enum": [
625
+ "configured",
626
+ "not-configured"
627
+ ]
628
+ },
629
+ "languages": {
630
+ "description": "Languages to analyze, in the PATCH's vocabulary (the GET's \"rust\" cannot be declared and stays as detected), compared as a set; GitHub auto-detects when omitted.",
631
+ "type": "array",
632
+ "items": {
633
+ "type": "string",
634
+ "enum": [
635
+ "csharp",
636
+ "go",
637
+ "java-kotlin",
638
+ "javascript-typescript",
639
+ "python",
640
+ "ruby"
641
+ ]
642
+ }
643
+ },
644
+ "runner_type": {
645
+ "description": "Run on GitHub-hosted (\"standard\") or labeled self-hosted runners.",
646
+ "type": "string",
647
+ "enum": [
648
+ "standard",
649
+ "labeled"
650
+ ]
651
+ },
652
+ "runner_label": {
653
+ "description": "Runner label: a string needs runner_type: \"labeled\" and is refused under any other; null clears it under runner_type: \"standard\" or none.",
654
+ "type": [
655
+ "string",
656
+ "null"
657
+ ]
658
+ },
659
+ "ai_findings_option": {
660
+ "description": "AI-powered findings: \"on_push\" runs them on every push, \"disabled\" turns them off.",
661
+ "type": "string",
662
+ "enum": [
663
+ "disabled",
664
+ "on_push"
665
+ ]
666
+ }
667
+ }
668
+ },
669
+ "CodeScanningDefaultSetupConfig": {
670
+ "description": "PATCH /repos/{r}/code-scanning/default-setup, sent verbatim.",
671
+ "type": "object",
672
+ "properties": {
673
+ "state": {
674
+ "description": "Turn default setup on (\"configured\") or off (\"not-configured\").",
675
+ "type": "string",
676
+ "enum": [
677
+ "configured",
678
+ "not-configured"
679
+ ]
680
+ },
681
+ "query_suite": {
682
+ "description": "CodeQL query suite to run.",
683
+ "type": "string",
684
+ "enum": [
685
+ "default",
686
+ "extended"
687
+ ]
688
+ },
689
+ "languages": {
690
+ "description": "Languages to scan, in the PATCH's vocabulary (\"javascript-typescript\", never the GET's separate \"javascript\" and \"typescript\"), compared as a set; GitHub auto-detects when omitted.",
691
+ "type": "array",
692
+ "items": {
693
+ "type": "string",
694
+ "enum": [
695
+ "actions",
696
+ "c-cpp",
697
+ "csharp",
698
+ "go",
699
+ "java-kotlin",
700
+ "javascript-typescript",
701
+ "python",
702
+ "ruby",
703
+ "swift"
704
+ ]
705
+ }
706
+ },
707
+ "runner_type": {
708
+ "description": "Run on GitHub-hosted (\"standard\") or labeled self-hosted runners.",
709
+ "type": "string",
710
+ "enum": [
711
+ "standard",
712
+ "labeled"
713
+ ]
714
+ },
715
+ "runner_label": {
716
+ "description": "Runner label: a string needs runner_type: \"labeled\" and is refused under any other; null clears it under runner_type: \"standard\" or none.",
717
+ "type": [
718
+ "string",
719
+ "null"
720
+ ]
721
+ },
722
+ "threat_model": {
723
+ "description": "Whether to model local sources as threats in addition to remote ones.",
724
+ "type": "string",
725
+ "enum": [
726
+ "remote",
727
+ "remote_and_local"
728
+ ]
729
+ }
730
+ }
731
+ },
732
+ "CodeScanningToolConfig": {
733
+ "description": "One tool that must provide code scanning results.",
734
+ "type": "object",
735
+ "properties": {
736
+ "alerts_threshold": {
737
+ "description": "The alert severity that blocks the update: none, errors, errors_and_warnings, or all.",
738
+ "type": "string",
739
+ "enum": [
740
+ "none",
741
+ "errors",
742
+ "errors_and_warnings",
743
+ "all"
744
+ ]
745
+ },
746
+ "security_alerts_threshold": {
747
+ "description": "The security severity that blocks the update: none, critical, high_or_higher, medium_or_higher, or all.",
748
+ "type": "string",
749
+ "enum": [
750
+ "none",
751
+ "critical",
752
+ "high_or_higher",
753
+ "medium_or_higher",
754
+ "all"
755
+ ]
756
+ },
757
+ "tool": {
758
+ "description": "The code scanning tool's name.",
759
+ "type": "string"
760
+ }
761
+ },
762
+ "required": [
763
+ "alerts_threshold",
764
+ "security_alerts_threshold",
765
+ "tool"
766
+ ],
767
+ "additionalProperties": {}
768
+ },
769
+ "CodespacesSecretConfig": {
770
+ "description": "One repository Codespaces secret, matched by case-insensitive name (GitHub stores secret names uppercase). Keys other than name and value are rejected: the API body is built from the sealed value alone, so an extra key would silently do nothing.",
771
+ "type": "object",
772
+ "properties": {
773
+ "name": {
774
+ "description": "The secret name, the natural key; compared case-insensitively and written uppercase. GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case (`github_token` is the reserved `GITHUB_TOKEN` once uppercased).",
775
+ "type": "string",
776
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
777
+ },
778
+ "value": {
779
+ "description": "A whole-value `$NAME` reference to an environment variable holding the secret - never a literal (settings files are committed plaintext). Resolved from the action step's env at run time and sealed client-side into the sealed box GitHub's secrets API expects (libsodium's crypto_box_seal format) before upload; GitHub cannot return the value, so check mode verifies existence only and apply re-seals it on every run.",
780
+ "type": "string"
781
+ }
782
+ },
783
+ "required": [
784
+ "name",
785
+ "value"
786
+ ]
787
+ },
788
+ "CollaboratorConfig": {
789
+ "description": "One direct collaborator, matched by username. Keys other than username and permission are rejected (a misspelled \"permission\" would otherwise silently grant the default role).",
790
+ "type": "object",
791
+ "properties": {
792
+ "username": {
793
+ "description": "GitHub login, the natural key.",
794
+ "type": "string"
795
+ },
796
+ "permission": {
797
+ "description": "\"pull\", \"triage\", \"push\", \"maintain\", \"admin\", or a custom org role name; defaults to \"push\". The grant's own vocabulary, lowercase: \"read\" and \"write\" are what GitHub reports a role as, not what a grant accepts, so they and a mis-cased standard permission fail at parse time, naming the form to declare.",
798
+ "type": "string",
799
+ "pattern": "^(?:pull|triage|push|maintain|admin|(?!(?:[Pp][Uu][Ll][Ll]|[Tt][Rr][Ii][Aa][Gg][Ee]|[Pp][Uu][Ss][Hh]|[Mm][Aa][Ii][Nn][Tt][Aa][Ii][Nn]|[Aa][Dd][Mm][Ii][Nn]|[Ww][Rr][Ii][Tt][Ee]|[Rr][Ee][Aa][Dd])$)\\S(?:.*\\S)?)$"
800
+ }
801
+ },
802
+ "required": [
803
+ "username"
804
+ ]
805
+ },
806
+ "CustomPropertyConfig": {
807
+ "description": "One custom property value, matched by the API's property_name verbatim. Keys other than property_name and value are rejected: the bulk PATCH body is built from exactly these two fields, so an extra key would have no destination.",
808
+ "type": "object",
809
+ "properties": {
810
+ "property_name": {
811
+ "description": "The organization-defined property's name, the natural key.",
812
+ "type": "string"
813
+ },
814
+ "value": {
815
+ "description": "The value to set: a string (single_select and string properties), a list of strings (multi_select, compared as a set - list each option once), or a boolean (true_false, normalized to the \"true\"/\"false\" string GitHub transports). Numbers are likewise sent as their string form - through YAML's parsed number, so quote any numeric value you want sent verbatim (unquoted, 1.10 arrives as \"1.1\" and 1e21 as \"1e+21\"). `null` unsets the property, reverting to the org default, if any.",
816
+ "anyOf": [
817
+ {
818
+ "type": "string"
819
+ },
820
+ {
821
+ "type": "array",
822
+ "items": {
823
+ "type": "string"
824
+ }
825
+ },
826
+ {
827
+ "type": "boolean"
828
+ },
829
+ {
830
+ "type": "number"
831
+ },
832
+ {
833
+ "type": "null"
834
+ }
835
+ ]
836
+ }
837
+ },
838
+ "required": [
839
+ "property_name",
840
+ "value"
841
+ ]
842
+ },
843
+ "DependabotSecretConfig": {
844
+ "description": "One repository Dependabot secret, matched by case-insensitive name (GitHub stores secret names uppercase). Keys other than name and value are rejected: the API body is built from the sealed value alone, so an extra key would silently do nothing.",
845
+ "type": "object",
846
+ "properties": {
847
+ "name": {
848
+ "description": "The secret name, the natural key; compared case-insensitively and written uppercase. GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case (`github_token` is the reserved `GITHUB_TOKEN` once uppercased).",
849
+ "type": "string",
850
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
851
+ },
852
+ "value": {
853
+ "description": "A whole-value `$NAME` reference to an environment variable holding the secret - never a literal (settings files are committed plaintext). Resolved from the action step's env at run time and sealed client-side into the sealed box GitHub's secrets API expects (libsodium's crypto_box_seal format) before upload; GitHub cannot return the value, so check mode verifies existence only and apply re-seals it on every run.",
854
+ "type": "string"
855
+ }
856
+ },
857
+ "required": [
858
+ "name",
859
+ "value"
860
+ ]
861
+ },
862
+ "DeployKeyConfig": {
863
+ "description": "One deploy key, matched by exact title (GitHub documents no case folding for titles). Extra fields pass through to the create call verbatim.",
864
+ "type": "object",
865
+ "properties": {
866
+ "title": {
867
+ "description": "The key title shown in the settings UI, the natural key.",
868
+ "type": "string"
869
+ },
870
+ "key": {
871
+ "description": "The PUBLIC key as one line, \"<algorithm> <base64> [comment]\" (the .pub file), the algorithm one of ssh-ed25519, ssh-rsa, ecdsa-sha2-nistp256/384/521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com (GitHub dropped DSA in 2022). Anything else, a line break included, is refused when the settings file is read; a private key is named, never echoed. Compared as algorithm + blob, comment ignored; immutable upstream, so a changed key is delete plus recreate.",
872
+ "type": "string",
873
+ "pattern": "^[ \\t]*(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|sk-ssh-ed25519@openssh\\.com|sk-ecdsa-sha2-nistp256@openssh\\.com)[ \\t]+((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=))(?:[ \\t][^\\r\\n]*)?$"
874
+ },
875
+ "read_only": {
876
+ "description": "Whether the key is restricted to read-only access; GitHub defaults to false (read/write).",
877
+ "type": "boolean"
878
+ }
879
+ },
880
+ "required": [
881
+ "title",
882
+ "key"
883
+ ]
884
+ },
885
+ "DeploymentBranchPolicyConfig": {
886
+ "description": "One custom deployment branch-policy pattern, matched by exact name. Extra fields pass through to the create call verbatim.",
887
+ "type": "object",
888
+ "properties": {
889
+ "name": {
890
+ "description": "The name pattern branches or tags must match to deploy (e.g. \"release/*\"), the natural key.",
891
+ "type": "string"
892
+ },
893
+ "type": {
894
+ "description": "What the pattern matches: \"branch\" (the upstream default) or \"tag\". Immutable on GitHub, so changing it is applied as delete plus recreate.",
895
+ "type": "string",
896
+ "enum": [
897
+ "branch",
898
+ "tag"
899
+ ]
900
+ }
901
+ },
902
+ "required": [
903
+ "name"
904
+ ]
905
+ },
906
+ "DeploymentProtectionRuleConfig": {
907
+ "description": "One custom deployment protection rule, matched by the slug of the GitHub App that provides it. No other key is accepted: the enable call sends only the App's resolved integration id, so an extra key would have no destination.",
908
+ "type": "object",
909
+ "properties": {
910
+ "app": {
911
+ "description": "The slug of the GitHub App providing the gate (e.g. \"my-gate-app\"), the natural key.",
912
+ "type": "string"
913
+ }
914
+ },
915
+ "required": [
916
+ "app"
917
+ ],
918
+ "additionalProperties": false
919
+ },
920
+ "EnvironmentConfig": {
921
+ "description": "One deployment environment, matched by name.",
922
+ "type": "object",
923
+ "properties": {
924
+ "name": {
925
+ "description": "The environment name, the natural key.",
926
+ "type": "string"
927
+ },
928
+ "pinned": {
929
+ "description": "Pin this environment on the repository home page's deployments sidebar (GraphQL-only; the REST environment PUT carries no pin field). Pin ORDER is the declaration order of the entries with `pinned: true` - together they must LEAD the repository's pinned list in that order, compared by rank (GitHub's live position numbers may carry holes after an unpin and are never read literally). `pinned: false` unpins; an entry without the key leaves its pin state untouched. Live pins on environments the settings file does not declare are never unpinned; when they sit among the declared ranks, apply moves them after the declared pins (surfaced as a note). GitHub allows at most 10 pinned environments, so more than 10 `pinned: true` entries are rejected upfront.",
930
+ "type": "boolean"
931
+ },
932
+ "wait_timer": {
933
+ "description": "Minutes to wait before deployments proceed, 0 to 43200 (30 days). 0 declares the wait timer off and matches a live environment without one.",
934
+ "type": "integer",
935
+ "minimum": 0,
936
+ "maximum": 43200
937
+ },
938
+ "prevent_self_review": {
939
+ "description": "Whether to prevent the deployer from approving their own deployment. The flag lives on the required-reviewers rule, so `true` needs at least one reviewer; `false` declares it off and matches a live environment without the rule.",
940
+ "type": "boolean"
941
+ },
942
+ "reviewers": {
943
+ "description": "Required reviewers by numeric user/team id, at most 6. An empty list declares required reviewers off and matches a live environment without the rule.",
944
+ "maxItems": 6,
945
+ "type": "array",
946
+ "items": {
947
+ "type": "object",
948
+ "properties": {
949
+ "type": {
950
+ "description": "User or Team.",
951
+ "type": "string",
952
+ "enum": [
953
+ "User",
954
+ "Team"
955
+ ]
956
+ },
957
+ "id": {
958
+ "description": "The user's or team's numeric id.",
959
+ "type": "number"
960
+ }
961
+ },
962
+ "required": [
963
+ "type",
964
+ "id"
965
+ ]
966
+ }
967
+ },
968
+ "deployment_branch_policy": {
969
+ "description": "Which branches may deploy; null lets any branch deploy. As an object, exactly one of the two flags is true: both true is rejected by GitHub, and both false is spelled null.",
970
+ "anyOf": [
971
+ {
972
+ "type": "object",
973
+ "properties": {
974
+ "protected_branches": {
975
+ "description": "Restrict to branches with protection rules.",
976
+ "type": "boolean"
977
+ },
978
+ "custom_branch_policies": {
979
+ "description": "Restrict to name patterns, declared under `deployment_branch_policies`.",
980
+ "type": "boolean"
981
+ }
982
+ },
983
+ "required": [
984
+ "protected_branches",
985
+ "custom_branch_policies"
986
+ ],
987
+ "if": {
988
+ "properties": {
989
+ "protected_branches": {
990
+ "const": true
991
+ }
992
+ }
993
+ },
994
+ "then": {
995
+ "properties": {
996
+ "custom_branch_policies": {
997
+ "const": false
998
+ }
999
+ }
1000
+ },
1001
+ "else": {
1002
+ "properties": {
1003
+ "custom_branch_policies": {
1004
+ "const": true
1005
+ }
1006
+ }
1007
+ }
1008
+ },
1009
+ {
1010
+ "type": "null"
1011
+ }
1012
+ ]
1013
+ },
1014
+ "deployment_branch_policies": {
1015
+ "description": "Custom deployment branch-policy patterns for this environment, reconciled only when this key is declared (an absent key leaves the live patterns untouched). Declaring it requires the sibling `deployment_branch_policy` to set `custom_branch_policies: true`; without the flag GitHub rejects every pattern write. A pattern's `type` is immutable on GitHub, so a declared type that differs from the live one is applied as delete plus recreate. Within a declared key, live patterns the entries do not declare are DELETED by default; the wrapped `{_undeclared: keep, entries}` form keeps them as notes.",
1016
+ "anyOf": [
1017
+ {
1018
+ "type": "array",
1019
+ "items": {
1020
+ "$ref": "#/definitions/DeploymentBranchPolicyConfig"
1021
+ }
1022
+ },
1023
+ {
1024
+ "$ref": "#/definitions/UndeclaredPolicyList%3CDeploymentBranchPolicyConfig%3E"
1025
+ }
1026
+ ]
1027
+ },
1028
+ "deployment_protection_rules": {
1029
+ "description": "Custom deployment protection rules for this environment, reconciled only when this key is declared (an absent key leaves the live rules untouched). Each rule is a GitHub App gate, declared by its App slug and resolved to the App's integration id at apply time; GitHub offers no update call, so the model is enable/disable only. Within a declared key, live rules the entries do not declare are KEPT by default - Apps can enable themselves as gates, and silently removing a deployment gate is security-relevant - and the wrapped `{_undeclared: delete, entries}` form opts into disabling them.",
1030
+ "anyOf": [
1031
+ {
1032
+ "type": "array",
1033
+ "items": {
1034
+ "$ref": "#/definitions/DeploymentProtectionRuleConfig"
1035
+ }
1036
+ },
1037
+ {
1038
+ "$ref": "#/definitions/UndeclaredPolicyList%3CDeploymentProtectionRuleConfig%3E"
1039
+ }
1040
+ ]
1041
+ },
1042
+ "variables": {
1043
+ "description": "Actions variables for this environment, reconciled only when this key is declared (an absent key leaves the live variables untouched). Values are plain text by design - use environment secrets for anything sensitive. Within a declared `variables` key, live variables the entries do not declare are DELETED by default; the wrapped `{_undeclared: keep, entries}` form keeps them as notes. Names match case-insensitively, as GitHub treats them.",
1044
+ "anyOf": [
1045
+ {
1046
+ "type": "array",
1047
+ "items": {
1048
+ "$ref": "#/definitions/EnvironmentVariableConfig"
1049
+ }
1050
+ },
1051
+ {
1052
+ "$ref": "#/definitions/UndeclaredPolicyList%3CEnvironmentVariableConfig%3E"
1053
+ }
1054
+ ]
1055
+ },
1056
+ "secrets": {
1057
+ "description": "Actions secrets for this environment, reconciled only when this key is declared (an absent key leaves the live secrets untouched). Each value is a whole-value `$NAME` reference to the action step's environment, never a literal, sealed client-side against the environment's public key; GitHub cannot return a value, so check mode verifies existence only and apply re-seals every declared value on each run. Within a declared `secrets` key, live secrets the entries do not declare are KEPT by default (their values are unrecoverable); the wrapped `{_undeclared: delete, entries}` form opts into deletion.",
1058
+ "anyOf": [
1059
+ {
1060
+ "type": "array",
1061
+ "items": {
1062
+ "$ref": "#/definitions/EnvironmentSecretConfig"
1063
+ }
1064
+ },
1065
+ {
1066
+ "$ref": "#/definitions/UndeclaredPolicyList%3CEnvironmentSecretConfig%3E"
1067
+ }
1068
+ ]
1069
+ }
1070
+ },
1071
+ "required": [
1072
+ "name"
1073
+ ],
1074
+ "allOf": [
1075
+ {
1076
+ "if": {
1077
+ "required": [
1078
+ "deployment_branch_policies"
1079
+ ]
1080
+ },
1081
+ "then": {
1082
+ "required": [
1083
+ "deployment_branch_policy"
1084
+ ],
1085
+ "properties": {
1086
+ "deployment_branch_policy": {
1087
+ "type": "object",
1088
+ "required": [
1089
+ "custom_branch_policies"
1090
+ ],
1091
+ "properties": {
1092
+ "custom_branch_policies": {
1093
+ "const": true
1094
+ }
1095
+ }
1096
+ }
1097
+ }
1098
+ }
1099
+ },
1100
+ {
1101
+ "if": {
1102
+ "required": [
1103
+ "prevent_self_review"
1104
+ ],
1105
+ "properties": {
1106
+ "prevent_self_review": {
1107
+ "const": true
1108
+ }
1109
+ }
1110
+ },
1111
+ "then": {
1112
+ "required": [
1113
+ "reviewers"
1114
+ ],
1115
+ "properties": {
1116
+ "reviewers": {
1117
+ "minItems": 1
1118
+ }
1119
+ }
1120
+ }
1121
+ }
1122
+ ]
1123
+ },
1124
+ "EnvironmentSecretConfig": {
1125
+ "description": "One per-environment Actions secret, matched by case-insensitive name (GitHub stores secret names uppercase). Keys other than name and value are rejected: the API body is built from the sealed value alone, so an extra key would silently do nothing.",
1126
+ "type": "object",
1127
+ "properties": {
1128
+ "name": {
1129
+ "description": "The secret name, the natural key; compared case-insensitively and written uppercase. GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case (`github_token` is the reserved `GITHUB_TOKEN` once uppercased).",
1130
+ "type": "string",
1131
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
1132
+ },
1133
+ "value": {
1134
+ "description": "A whole-value `$NAME` reference to an environment variable holding the secret - never a literal (settings files are committed plaintext). Resolved from the action step's env at run time and sealed client-side into the sealed box GitHub's secrets API expects (libsodium's crypto_box_seal format) before upload; GitHub cannot return the value, so check mode verifies existence only and apply re-seals it on every run.",
1135
+ "type": "string"
1136
+ }
1137
+ },
1138
+ "required": [
1139
+ "name",
1140
+ "value"
1141
+ ],
1142
+ "additionalProperties": false
1143
+ },
1144
+ "EnvironmentVariableConfig": {
1145
+ "description": "One per-environment Actions variable, matched by case-insensitive name.",
1146
+ "type": "object",
1147
+ "properties": {
1148
+ "name": {
1149
+ "description": "The variable name, the natural key (case-insensitive on GitHub). GitHub's naming rule is checked when the file is parsed, before any API call: ASCII letters, digits, and underscores only, not starting with a digit, and not starting with the reserved `GITHUB_` prefix in any case.",
1150
+ "type": "string",
1151
+ "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$"
1152
+ },
1153
+ "value": {
1154
+ "description": "The plain-text value. GitHub caps one variable at 48 KB; a value over 49152 bytes of UTF-8 is refused when the file is parsed, before any API call.",
1155
+ "type": "string",
1156
+ "maxLength": 49152
1157
+ }
1158
+ },
1159
+ "required": [
1160
+ "name",
1161
+ "value"
1162
+ ]
1163
+ },
1164
+ "InteractionLimitsConfig": {
1165
+ "description": "The `interaction_limits:` section, exactly four keys: `limit` and `expiry` are the body of PUT /repos/{r}/interaction-limits, and the two pull-request keys go to their own .../interaction-limits/pulls sub-endpoints. Any other key fails at parse time, origin and expires_at included: GitHub reports them on the GET but never accepts them. Declare at least one of `limit`, `pull_request_creation_cap`, or `pull_request_creation_bypass`.",
1166
+ "type": "object",
1167
+ "properties": {
1168
+ "limit": {
1169
+ "description": "Who may interact: \"existing_users\", \"contributors_only\", or \"collaborators_only\"; any other value fails at parse time (GitHub would 422 the PUT). Optional when only the pull-request keys below are declared; an omitted limit leaves the live base limit untouched.",
1170
+ "type": "string",
1171
+ "enum": [
1172
+ "existing_users",
1173
+ "contributors_only",
1174
+ "collaborators_only"
1175
+ ]
1176
+ },
1177
+ "expiry": {
1178
+ "description": "How long the limit lasts: \"one_day\", \"three_days\", \"one_week\", \"one_month\", or \"six_months\"; GitHub defaults to one_day, and any other value fails at parse time. Write-only: GitHub reports back the computed expires_at, never the duration, so check mode cannot verify this field and apply re-arms it on every run. Requires a sibling `limit`.",
1179
+ "type": "string",
1180
+ "enum": [
1181
+ "one_day",
1182
+ "three_days",
1183
+ "one_week",
1184
+ "one_month",
1185
+ "six_months"
1186
+ ]
1187
+ },
1188
+ "pull_request_creation_cap": {
1189
+ "description": "The pull request creation cap, routed to GET/PATCH /repos/{r}/interaction-limits/pulls/creation-cap. Unlike the base limit it is persistent desired state with no self-expiry and reads back verbatim, so check mode diffs it exactly and apply PATCHes only on divergence. max_open_pull_requests is 1-1000. On repositories where the cap is not available, the endpoints answer 405: apply surfaces that as a note, check mode as drift.",
1190
+ "type": "object",
1191
+ "properties": {
1192
+ "enabled": {
1193
+ "description": "Whether the cap is enforced.",
1194
+ "type": "boolean"
1195
+ },
1196
+ "max_open_pull_requests": {
1197
+ "description": "The maximum number of open pull requests one user may have, a whole number from 1 to 1000 (GitHub's range); anything else fails at parse time.",
1198
+ "type": "integer",
1199
+ "minimum": 1,
1200
+ "maximum": 1000
1201
+ }
1202
+ },
1203
+ "required": [
1204
+ "enabled"
1205
+ ]
1206
+ },
1207
+ "pull_request_creation_bypass": {
1208
+ "description": "User logins exempt from the pull request creation cap, routed to GET/PUT/DELETE /repos/{r}/interaction-limits/pulls/bypass-list and reconciled: apply removes the undeclared logins and then adds the missing ones (removals first - the list holds at most 100 users); logins compare case-insensitively. An empty list removes everyone. At most 100 logins.",
1209
+ "type": "array",
1210
+ "items": {
1211
+ "type": "string"
1212
+ }
1213
+ }
1214
+ },
1215
+ "additionalProperties": false
1216
+ },
1217
+ "LabelConfig": {
1218
+ "description": "One label, matched to the live repo by name.",
1219
+ "type": "object",
1220
+ "properties": {
1221
+ "name": {
1222
+ "description": "The label name, the natural key.",
1223
+ "type": "string"
1224
+ },
1225
+ "color": {
1226
+ "description": "Six hex digits, the leading \"#\" optional (\"#d73a4a\" or \"d73a4a\"). Color names and three-digit shorthand fail at parse time; GitHub rejects them.",
1227
+ "type": "string",
1228
+ "pattern": "^#?[0-9a-fA-F]{6}$"
1229
+ },
1230
+ "description": {
1231
+ "description": "Short explanation shown in the label picker, at most 100 characters (GitHub's cap); longer ones fail at parse time.",
1232
+ "type": "string",
1233
+ "maxLength": 100
1234
+ },
1235
+ "new_name": {
1236
+ "description": "Probot compat: rename an existing label.",
1237
+ "type": "string"
1238
+ }
1239
+ },
1240
+ "required": [
1241
+ "name"
1242
+ ]
1243
+ },
1244
+ "LayeredList<BranchConfig>": {
1245
+ "description": "The wrapped form of a list section that applies no undeclared policy (environments, branches, workflows): the plain array beside `{_layering, entries}`. The wrapper exists for the render directive alone, so the rendered document always holds the plain array, and with `_layering` omitted it behaves exactly like the plain array. Its keys are strict: anything besides `_layering` and `entries` (there is no `_undeclared` here, since the section keeps every live resource it does not declare) is rejected upfront as a typo.",
1246
+ "type": "object",
1247
+ "properties": {
1248
+ "_layering": {
1249
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (an environment's name, a branch name or pattern, a workflow path). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, the entry's nested lists (an environment's variables, secrets, branch policies, protection rules, and reviewers, each by its own key) unioning the same way. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, and the rendered document never carries it.",
1250
+ "type": "string",
1251
+ "enum": [
1252
+ "replace",
1253
+ "shallow",
1254
+ "deep"
1255
+ ]
1256
+ },
1257
+ "entries": {
1258
+ "description": "The declared entries, exactly as the plain array form lists them.",
1259
+ "type": "array",
1260
+ "items": {
1261
+ "$ref": "#/definitions/BranchConfig"
1262
+ }
1263
+ }
1264
+ },
1265
+ "required": [
1266
+ "entries"
1267
+ ],
1268
+ "additionalProperties": false
1269
+ },
1270
+ "LayeredList<EnvironmentConfig>": {
1271
+ "description": "The wrapped form of a list section that applies no undeclared policy (environments, branches, workflows): the plain array beside `{_layering, entries}`. The wrapper exists for the render directive alone, so the rendered document always holds the plain array, and with `_layering` omitted it behaves exactly like the plain array. Its keys are strict: anything besides `_layering` and `entries` (there is no `_undeclared` here, since the section keeps every live resource it does not declare) is rejected upfront as a typo.",
1272
+ "type": "object",
1273
+ "properties": {
1274
+ "_layering": {
1275
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (an environment's name, a branch name or pattern, a workflow path). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, the entry's nested lists (an environment's variables, secrets, branch policies, protection rules, and reviewers, each by its own key) unioning the same way. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, and the rendered document never carries it.",
1276
+ "type": "string",
1277
+ "enum": [
1278
+ "replace",
1279
+ "shallow",
1280
+ "deep"
1281
+ ]
1282
+ },
1283
+ "entries": {
1284
+ "description": "The declared entries, exactly as the plain array form lists them.",
1285
+ "type": "array",
1286
+ "items": {
1287
+ "$ref": "#/definitions/EnvironmentConfig"
1288
+ }
1289
+ }
1290
+ },
1291
+ "required": [
1292
+ "entries"
1293
+ ],
1294
+ "additionalProperties": false
1295
+ },
1296
+ "LayeredList<WorkflowConfig>": {
1297
+ "description": "The wrapped form of a list section that applies no undeclared policy (environments, branches, workflows): the plain array beside `{_layering, entries}`. The wrapper exists for the render directive alone, so the rendered document always holds the plain array, and with `_layering` omitted it behaves exactly like the plain array. Its keys are strict: anything besides `_layering` and `entries` (there is no `_undeclared` here, since the section keeps every live resource it does not declare) is rejected upfront as a typo.",
1298
+ "type": "object",
1299
+ "properties": {
1300
+ "_layering": {
1301
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (an environment's name, a branch name or pattern, a workflow path). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, the entry's nested lists (an environment's variables, secrets, branch policies, protection rules, and reviewers, each by its own key) unioning the same way. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, and the rendered document never carries it.",
1302
+ "type": "string",
1303
+ "enum": [
1304
+ "replace",
1305
+ "shallow",
1306
+ "deep"
1307
+ ]
1308
+ },
1309
+ "entries": {
1310
+ "description": "The declared entries, exactly as the plain array form lists them.",
1311
+ "type": "array",
1312
+ "items": {
1313
+ "$ref": "#/definitions/WorkflowConfig"
1314
+ }
1315
+ }
1316
+ },
1317
+ "required": [
1318
+ "entries"
1319
+ ],
1320
+ "additionalProperties": false
1321
+ },
1322
+ "MilestoneConfig": {
1323
+ "description": "One milestone, matched by title.",
1324
+ "type": "object",
1325
+ "properties": {
1326
+ "title": {
1327
+ "description": "The milestone title, the natural key.",
1328
+ "type": "string"
1329
+ },
1330
+ "description": {
1331
+ "description": "Longer explanation of the milestone.",
1332
+ "type": "string"
1333
+ },
1334
+ "state": {
1335
+ "description": "Open or closed; untouched unless declared.",
1336
+ "type": "string",
1337
+ "enum": [
1338
+ "open",
1339
+ "closed"
1340
+ ]
1341
+ },
1342
+ "due_on": {
1343
+ "description": "The due day as `YYYY-MM-DD`; GitHub keeps only the day, so only the day is compared, and a snapshot reads it back as the day. The day is sent as noon UTC, `YYYY-MM-DDT12:00:00Z`, which GitHub stores on the same calendar day in PST and PDT. A UTC timestamp `YYYY-MM-DDTHH:MM:SSZ` is accepted for its date part.",
1344
+ "anyOf": [
1345
+ {
1346
+ "type": "string",
1347
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
1348
+ },
1349
+ {
1350
+ "type": "string",
1351
+ "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
1352
+ }
1353
+ ]
1354
+ }
1355
+ },
1356
+ "required": [
1357
+ "title"
1358
+ ]
1359
+ },
1360
+ "PagesConfig": {
1361
+ "description": "GitHub Pages site configuration; use `pages: null` to disable the site.",
1362
+ "type": "object",
1363
+ "properties": {
1364
+ "build_type": {
1365
+ "description": "\"workflow\" (GitHub Actions) or \"legacy\" (branch).",
1366
+ "type": "string",
1367
+ "enum": [
1368
+ "workflow",
1369
+ "legacy"
1370
+ ]
1371
+ },
1372
+ "source": {
1373
+ "description": "The update PUT requires both branch and path when source is sent.",
1374
+ "type": "object",
1375
+ "properties": {
1376
+ "branch": {
1377
+ "description": "The branch Pages publishes from.",
1378
+ "type": "string"
1379
+ },
1380
+ "path": {
1381
+ "description": "The directory within the branch Pages publishes: / or /docs.",
1382
+ "type": "string",
1383
+ "enum": [
1384
+ "/",
1385
+ "/docs"
1386
+ ]
1387
+ }
1388
+ },
1389
+ "required": [
1390
+ "branch"
1391
+ ]
1392
+ },
1393
+ "cname": {
1394
+ "description": "Custom domain; null removes it.",
1395
+ "type": [
1396
+ "string",
1397
+ "null"
1398
+ ]
1399
+ },
1400
+ "https_enforced": {
1401
+ "description": "Whether HTTPS is enforced for the site.",
1402
+ "type": "boolean"
1403
+ },
1404
+ "public": {
1405
+ "description": "Enterprise Cloud site visibility: true for public, false for repository members only. Only an organization on Enterprise Cloud can set it; everywhere else GitHub reports true and ignores the field, so false drifts on every run.",
1406
+ "type": "boolean"
1407
+ }
1408
+ },
1409
+ "not": {
1410
+ "anyOf": [
1411
+ {
1412
+ "required": [
1413
+ "url"
1414
+ ]
1415
+ },
1416
+ {
1417
+ "required": [
1418
+ "html_url"
1419
+ ]
1420
+ },
1421
+ {
1422
+ "required": [
1423
+ "status"
1424
+ ]
1425
+ },
1426
+ {
1427
+ "required": [
1428
+ "custom_404"
1429
+ ]
1430
+ },
1431
+ {
1432
+ "required": [
1433
+ "protected_domain_state"
1434
+ ]
1435
+ },
1436
+ {
1437
+ "required": [
1438
+ "pending_domain_unverified_at"
1439
+ ]
1440
+ },
1441
+ {
1442
+ "required": [
1443
+ "https_certificate"
1444
+ ]
1445
+ }
1446
+ ]
1447
+ }
1448
+ },
1449
+ "PatternRuleParameters": {
1450
+ "description": "The pattern and operator the five *_pattern rule types share.",
1451
+ "type": "object",
1452
+ "properties": {
1453
+ "name": {
1454
+ "description": "How the rule appears when configuring it.",
1455
+ "type": "string"
1456
+ },
1457
+ "negate": {
1458
+ "description": "Whether the rule fails when the pattern matches.",
1459
+ "type": "boolean"
1460
+ },
1461
+ "operator": {
1462
+ "description": "starts_with, ends_with, contains, or regex, in that spelling.",
1463
+ "type": "string",
1464
+ "enum": [
1465
+ "starts_with",
1466
+ "ends_with",
1467
+ "contains",
1468
+ "regex"
1469
+ ]
1470
+ },
1471
+ "pattern": {
1472
+ "description": "The pattern to match.",
1473
+ "type": "string"
1474
+ }
1475
+ },
1476
+ "required": [
1477
+ "operator",
1478
+ "pattern"
1479
+ ],
1480
+ "additionalProperties": {}
1481
+ },
1482
+ "RepositoryConfig": {
1483
+ "description": "The `repository:` section, where only declared keys are ever applied or compared. A field not documented here is sent verbatim to PATCH /repos/{r}, so a field GitHub adds later works unchanged; the keys below carry GitHub's types (a toggle is true or false, never null or quoted) or route to their own endpoints. GET-only fields (ids, urls, counts, has_downloads, has_pages, custom_properties) are refused, since they would drift on every run.",
1484
+ "type": "object",
1485
+ "properties": {
1486
+ "description": {
1487
+ "description": "A short description of the repository; null clears it.",
1488
+ "type": [
1489
+ "string",
1490
+ "null"
1491
+ ]
1492
+ },
1493
+ "homepage": {
1494
+ "description": "A URL with more information about the repository; null clears it.",
1495
+ "type": [
1496
+ "string",
1497
+ "null"
1498
+ ]
1499
+ },
1500
+ "private": {
1501
+ "description": "Make the repository private (true) or public (false).",
1502
+ "type": "boolean"
1503
+ },
1504
+ "visibility": {
1505
+ "description": "public, private, or internal (Enterprise); a free string, since the spec omits internal.",
1506
+ "type": "string"
1507
+ },
1508
+ "security_and_analysis": {
1509
+ "description": "The security_and_analysis object of PATCH /repos/{r}: GitHub Advanced Security, secret scanning, push protection, and the other nested feature toggles.",
1510
+ "anyOf": [
1511
+ {
1512
+ "$ref": "#/definitions/SecurityAndAnalysisConfig"
1513
+ },
1514
+ {
1515
+ "type": "null"
1516
+ }
1517
+ ]
1518
+ },
1519
+ "has_issues": {
1520
+ "description": "Enable issues (true) or disable them (false).",
1521
+ "type": "boolean"
1522
+ },
1523
+ "has_projects": {
1524
+ "description": "Enable projects (true) or disable them (false); an organization that disabled repository projects rejects true.",
1525
+ "type": "boolean"
1526
+ },
1527
+ "has_wiki": {
1528
+ "description": "Enable the wiki (true) or disable it (false).",
1529
+ "type": "boolean"
1530
+ },
1531
+ "has_discussions": {
1532
+ "description": "Enable discussions (true) or disable them (false); accepted by the PATCH though the descriptor omits it.",
1533
+ "type": "boolean"
1534
+ },
1535
+ "has_pull_requests": {
1536
+ "description": "Allow pull requests (true) or prevent them (false).",
1537
+ "type": "boolean"
1538
+ },
1539
+ "pull_request_creation_policy": {
1540
+ "description": "Who may create pull requests: \"all\" (everyone) or \"collaborators_only\".",
1541
+ "type": "string",
1542
+ "enum": [
1543
+ "all",
1544
+ "collaborators_only"
1545
+ ]
1546
+ },
1547
+ "is_template": {
1548
+ "description": "Offer the repository as a template (true) or not (false).",
1549
+ "type": "boolean"
1550
+ },
1551
+ "default_branch": {
1552
+ "description": "The default branch; an existing branch name.",
1553
+ "type": "string"
1554
+ },
1555
+ "allow_squash_merge": {
1556
+ "description": "Allow squash-merging pull requests (true) or not (false).",
1557
+ "type": "boolean"
1558
+ },
1559
+ "allow_merge_commit": {
1560
+ "description": "Allow merge commits on pull requests (true) or not (false).",
1561
+ "type": "boolean"
1562
+ },
1563
+ "allow_rebase_merge": {
1564
+ "description": "Allow rebase-merging pull requests (true) or not (false).",
1565
+ "type": "boolean"
1566
+ },
1567
+ "allow_auto_merge": {
1568
+ "description": "Allow auto-merge on pull requests (true) or not (false).",
1569
+ "type": "boolean"
1570
+ },
1571
+ "delete_branch_on_merge": {
1572
+ "description": "Delete head branches when pull requests merge (true) or keep them (false).",
1573
+ "type": "boolean"
1574
+ },
1575
+ "allow_update_branch": {
1576
+ "description": "Offer to update a pull request branch behind its base (true) or not (false).",
1577
+ "type": "boolean"
1578
+ },
1579
+ "use_squash_pr_title_as_default": {
1580
+ "description": "Deprecated by GitHub in favor of squash_merge_commit_title: use the PR title as the squash commit title (true) or not (false).",
1581
+ "type": "boolean"
1582
+ },
1583
+ "squash_merge_commit_title": {
1584
+ "description": "The default title of a squash merge commit: PR_TITLE or COMMIT_OR_PR_TITLE. Required beside squash_merge_commit_message; legal pairs are PR_TITLE with PR_BODY, BLANK, or COMMIT_MESSAGES, and COMMIT_OR_PR_TITLE with COMMIT_MESSAGES.",
1585
+ "type": "string",
1586
+ "enum": [
1587
+ "PR_TITLE",
1588
+ "COMMIT_OR_PR_TITLE"
1589
+ ]
1590
+ },
1591
+ "squash_merge_commit_message": {
1592
+ "description": "The default message of a squash merge commit: PR_BODY, BLANK, or COMMIT_MESSAGES. Needs squash_merge_commit_title declared beside it, in one of the legal pairs.",
1593
+ "type": "string",
1594
+ "enum": [
1595
+ "PR_BODY",
1596
+ "BLANK",
1597
+ "COMMIT_MESSAGES"
1598
+ ]
1599
+ },
1600
+ "merge_commit_title": {
1601
+ "description": "The default title of a merge commit: PR_TITLE or MERGE_MESSAGE. Required beside merge_commit_message.",
1602
+ "type": "string",
1603
+ "enum": [
1604
+ "PR_TITLE",
1605
+ "MERGE_MESSAGE"
1606
+ ]
1607
+ },
1608
+ "merge_commit_message": {
1609
+ "description": "The default message of a merge commit: PR_BODY, PR_TITLE, or BLANK. Needs merge_commit_title declared beside it.",
1610
+ "type": "string",
1611
+ "enum": [
1612
+ "PR_BODY",
1613
+ "BLANK",
1614
+ "PR_TITLE"
1615
+ ]
1616
+ },
1617
+ "archived": {
1618
+ "description": "Archive the repository (true) or unarchive it (false).",
1619
+ "type": "boolean"
1620
+ },
1621
+ "allow_forking": {
1622
+ "description": "Allow private forks (true) or not (false).",
1623
+ "type": "boolean"
1624
+ },
1625
+ "web_commit_signoff_required": {
1626
+ "description": "Require contributors to sign off on web-based commits (true) or not (false).",
1627
+ "type": "boolean"
1628
+ },
1629
+ "topics": {
1630
+ "description": "Repository topics, replaced wholesale via PUT /repos/{r}/topics; a comma-separated string or a list, lowercased and deduped. Each topic is 1 to 50 letters, digits, and hyphens, starting with a letter or digit (uppercase is lowercased on the wire); at most 20 distinct topics. An empty entry is refused; an empty list removes every topic.",
1631
+ "anyOf": [
1632
+ {
1633
+ "type": "string",
1634
+ "pattern": "^\\s*[A-Za-z0-9][A-Za-z0-9-]{0,49}\\s*(,\\s*[A-Za-z0-9][A-Za-z0-9-]{0,49}\\s*)*$"
1635
+ },
1636
+ {
1637
+ "type": "array",
1638
+ "items": {
1639
+ "type": "string",
1640
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9-]{0,49}$"
1641
+ }
1642
+ }
1643
+ ]
1644
+ },
1645
+ "enable_vulnerability_alerts": {
1646
+ "description": "Dependabot alerts, via PUT/DELETE /repos/{r}/vulnerability-alerts. On read, 404 means off.",
1647
+ "type": "boolean"
1648
+ },
1649
+ "enable_automated_security_fixes": {
1650
+ "description": "Dependabot security updates, via PUT/DELETE /repos/{r}/automated-security-fixes. On read, 404 means off, as does a 200 body with enabled: false.",
1651
+ "type": "boolean"
1652
+ },
1653
+ "enable_private_vulnerability_reporting": {
1654
+ "description": "Private vulnerability reporting, via PUT/DELETE /repos/{r}/private-vulnerability-reporting. Repositories where the feature does not apply (observed: private repos) read as off.",
1655
+ "type": "boolean"
1656
+ },
1657
+ "enable_git_lfs": {
1658
+ "description": "Git LFS, via PUT/DELETE /repos/{r}/lfs. Write-only upstream: check mode cannot verify it, and apply re-asserts it on every run.",
1659
+ "type": "boolean"
1660
+ },
1661
+ "enable_immutable_releases": {
1662
+ "description": "Immutable releases, via PUT/DELETE /repos/{r}/immutable-releases. On read, 404 means off. When the repository owner enforces immutable releases (enforced_by_owner in the GET body), writes answer 409 and the setting cannot be changed from the repository; apply reports that as a note instead of a change.",
1663
+ "type": "boolean"
1664
+ },
1665
+ "enable_sponsorships": {
1666
+ "description": "Display a Sponsor button on the repository, via the GraphQL updateRepository mutation (hasSponsorshipsEnabled) - GraphQL is the setting's only read and write surface (the REST repo PATCH and GET carry no such field). A stored repository toggle independent of any FUNDING.yml content.",
1667
+ "type": "boolean"
1668
+ },
1669
+ "issue_creation_policy": {
1670
+ "description": "Who may create issues: \"all\" (everyone) or \"collaborators_only\", mapped to GitHub's ALL/COLLABORATORS_ONLY GraphQL enum at the API boundary. GraphQL-only upstream (Repository.issueCreationPolicy and the updateRepository mutation): the REST repo PATCH accepts an issue_creation_policy field and silently ignores it, and no REST GET returns it.",
1671
+ "type": "string",
1672
+ "enum": [
1673
+ "all",
1674
+ "collaborators_only"
1675
+ ]
1676
+ }
1677
+ },
1678
+ "additionalProperties": {
1679
+ "description": "Everything else passes through to PATCH /repos/{r} verbatim."
1680
+ },
1681
+ "allOf": [
1682
+ {
1683
+ "if": {
1684
+ "required": [
1685
+ "squash_merge_commit_message"
1686
+ ]
1687
+ },
1688
+ "then": {
1689
+ "required": [
1690
+ "squash_merge_commit_title"
1691
+ ]
1692
+ }
1693
+ },
1694
+ {
1695
+ "if": {
1696
+ "required": [
1697
+ "squash_merge_commit_title"
1698
+ ],
1699
+ "properties": {
1700
+ "squash_merge_commit_title": {
1701
+ "const": "PR_TITLE"
1702
+ }
1703
+ }
1704
+ },
1705
+ "then": {
1706
+ "properties": {
1707
+ "squash_merge_commit_message": {
1708
+ "enum": [
1709
+ "PR_BODY",
1710
+ "BLANK",
1711
+ "COMMIT_MESSAGES"
1712
+ ]
1713
+ }
1714
+ }
1715
+ }
1716
+ },
1717
+ {
1718
+ "if": {
1719
+ "required": [
1720
+ "squash_merge_commit_title"
1721
+ ],
1722
+ "properties": {
1723
+ "squash_merge_commit_title": {
1724
+ "const": "COMMIT_OR_PR_TITLE"
1725
+ }
1726
+ }
1727
+ },
1728
+ "then": {
1729
+ "properties": {
1730
+ "squash_merge_commit_message": {
1731
+ "enum": [
1732
+ "COMMIT_MESSAGES"
1733
+ ]
1734
+ }
1735
+ }
1736
+ }
1737
+ },
1738
+ {
1739
+ "if": {
1740
+ "required": [
1741
+ "merge_commit_message"
1742
+ ]
1743
+ },
1744
+ "then": {
1745
+ "required": [
1746
+ "merge_commit_title"
1747
+ ]
1748
+ }
1749
+ }
1750
+ ]
1751
+ },
1752
+ "RequiredReviewerConfig": {
1753
+ "description": "A team and the file patterns whose changes it must approve.",
1754
+ "type": "object",
1755
+ "properties": {
1756
+ "file_patterns": {
1757
+ "description": "fnmatch patterns of the files the team must review.",
1758
+ "type": "array",
1759
+ "items": {
1760
+ "type": "string"
1761
+ }
1762
+ },
1763
+ "minimum_approvals": {
1764
+ "description": "Approvals required from the team; zero adds the team as a reviewer without requiring approval.",
1765
+ "type": "integer"
1766
+ },
1767
+ "reviewer": {
1768
+ "description": "The reviewing team.",
1769
+ "type": "object",
1770
+ "properties": {
1771
+ "id": {
1772
+ "description": "The team's id.",
1773
+ "type": "integer"
1774
+ },
1775
+ "type": {
1776
+ "description": "Always \"Team\".",
1777
+ "type": "string",
1778
+ "const": "Team"
1779
+ }
1780
+ },
1781
+ "required": [
1782
+ "id",
1783
+ "type"
1784
+ ],
1785
+ "additionalProperties": {}
1786
+ }
1787
+ },
1788
+ "required": [
1789
+ "file_patterns",
1790
+ "minimum_approvals",
1791
+ "reviewer"
1792
+ ],
1793
+ "additionalProperties": {}
1794
+ },
1795
+ "ReviewDismissalActorConfig": {
1796
+ "description": "One actor allowed to dismiss pull request reviews.",
1797
+ "type": "object",
1798
+ "properties": {
1799
+ "id": {
1800
+ "description": "The actor's id.",
1801
+ "type": "integer"
1802
+ },
1803
+ "type": {
1804
+ "description": "User, Team, IntegrationInstallation, or RepositoryRole.",
1805
+ "type": "string",
1806
+ "enum": [
1807
+ "User",
1808
+ "Team",
1809
+ "IntegrationInstallation",
1810
+ "RepositoryRole"
1811
+ ]
1812
+ }
1813
+ },
1814
+ "required": [
1815
+ "id",
1816
+ "type"
1817
+ ],
1818
+ "additionalProperties": {}
1819
+ },
1820
+ "Rule<branch_name_pattern>": {
1821
+ "description": "Branch names must match (or not match) a pattern.",
1822
+ "type": "object",
1823
+ "properties": {
1824
+ "type": {
1825
+ "description": "The rule type, as the rulesets API names it.",
1826
+ "type": "string",
1827
+ "const": "branch_name_pattern"
1828
+ },
1829
+ "parameters": {
1830
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1831
+ "allOf": [
1832
+ {
1833
+ "$ref": "#/definitions/PatternRuleParameters"
1834
+ }
1835
+ ]
1836
+ }
1837
+ },
1838
+ "required": [
1839
+ "type"
1840
+ ],
1841
+ "additionalProperties": {}
1842
+ },
1843
+ "Rule<code_scanning>": {
1844
+ "description": "Named code scanning tools must report before the ref is updated.",
1845
+ "type": "object",
1846
+ "properties": {
1847
+ "type": {
1848
+ "description": "The rule type, as the rulesets API names it.",
1849
+ "type": "string",
1850
+ "const": "code_scanning"
1851
+ },
1852
+ "parameters": {
1853
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1854
+ "type": "object",
1855
+ "properties": {
1856
+ "code_scanning_tools": {
1857
+ "description": "The tools that must provide results.",
1858
+ "type": "array",
1859
+ "items": {
1860
+ "$ref": "#/definitions/CodeScanningToolConfig"
1861
+ }
1862
+ }
1863
+ },
1864
+ "required": [
1865
+ "code_scanning_tools"
1866
+ ],
1867
+ "additionalProperties": {}
1868
+ }
1869
+ },
1870
+ "required": [
1871
+ "type"
1872
+ ],
1873
+ "additionalProperties": {}
1874
+ },
1875
+ "Rule<commit_author_email_pattern>": {
1876
+ "description": "Commit author emails must match (or not match) a pattern.",
1877
+ "type": "object",
1878
+ "properties": {
1879
+ "type": {
1880
+ "description": "The rule type, as the rulesets API names it.",
1881
+ "type": "string",
1882
+ "const": "commit_author_email_pattern"
1883
+ },
1884
+ "parameters": {
1885
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1886
+ "allOf": [
1887
+ {
1888
+ "$ref": "#/definitions/PatternRuleParameters"
1889
+ }
1890
+ ]
1891
+ }
1892
+ },
1893
+ "required": [
1894
+ "type"
1895
+ ],
1896
+ "additionalProperties": {}
1897
+ },
1898
+ "Rule<commit_message_pattern>": {
1899
+ "description": "Commit messages must match (or not match) a pattern.",
1900
+ "type": "object",
1901
+ "properties": {
1902
+ "type": {
1903
+ "description": "The rule type, as the rulesets API names it.",
1904
+ "type": "string",
1905
+ "const": "commit_message_pattern"
1906
+ },
1907
+ "parameters": {
1908
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1909
+ "allOf": [
1910
+ {
1911
+ "$ref": "#/definitions/PatternRuleParameters"
1912
+ }
1913
+ ]
1914
+ }
1915
+ },
1916
+ "required": [
1917
+ "type"
1918
+ ],
1919
+ "additionalProperties": {}
1920
+ },
1921
+ "Rule<committer_email_pattern>": {
1922
+ "description": "Committer emails must match (or not match) a pattern.",
1923
+ "type": "object",
1924
+ "properties": {
1925
+ "type": {
1926
+ "description": "The rule type, as the rulesets API names it.",
1927
+ "type": "string",
1928
+ "const": "committer_email_pattern"
1929
+ },
1930
+ "parameters": {
1931
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1932
+ "allOf": [
1933
+ {
1934
+ "$ref": "#/definitions/PatternRuleParameters"
1935
+ }
1936
+ ]
1937
+ }
1938
+ },
1939
+ "required": [
1940
+ "type"
1941
+ ],
1942
+ "additionalProperties": {}
1943
+ },
1944
+ "Rule<copilot_code_review>": {
1945
+ "description": "Copilot code review is requested on new pull requests automatically.",
1946
+ "type": "object",
1947
+ "properties": {
1948
+ "type": {
1949
+ "description": "The rule type, as the rulesets API names it.",
1950
+ "type": "string",
1951
+ "const": "copilot_code_review"
1952
+ },
1953
+ "parameters": {
1954
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
1955
+ "type": "object",
1956
+ "properties": {
1957
+ "review_draft_pull_requests": {
1958
+ "description": "Whether drafts are reviewed before they are marked ready.",
1959
+ "type": "boolean"
1960
+ },
1961
+ "review_on_push": {
1962
+ "description": "Whether each new push is reviewed.",
1963
+ "type": "boolean"
1964
+ }
1965
+ },
1966
+ "additionalProperties": {}
1967
+ }
1968
+ },
1969
+ "required": [
1970
+ "type"
1971
+ ],
1972
+ "additionalProperties": {}
1973
+ },
1974
+ "Rule<creation>": {
1975
+ "description": "Only actors with bypass permission may create matching refs.",
1976
+ "type": "object",
1977
+ "properties": {
1978
+ "type": {
1979
+ "description": "The rule type, as the rulesets API names it.",
1980
+ "type": "string",
1981
+ "const": "creation"
1982
+ }
1983
+ },
1984
+ "required": [
1985
+ "type"
1986
+ ],
1987
+ "additionalProperties": {}
1988
+ },
1989
+ "Rule<deletion>": {
1990
+ "description": "Only actors with bypass permission may delete matching refs.",
1991
+ "type": "object",
1992
+ "properties": {
1993
+ "type": {
1994
+ "description": "The rule type, as the rulesets API names it.",
1995
+ "type": "string",
1996
+ "const": "deletion"
1997
+ }
1998
+ },
1999
+ "required": [
2000
+ "type"
2001
+ ],
2002
+ "additionalProperties": {}
2003
+ },
2004
+ "Rule<file_extension_restriction>": {
2005
+ "description": "Commits adding files with the listed extensions are refused.",
2006
+ "type": "object",
2007
+ "properties": {
2008
+ "type": {
2009
+ "description": "The rule type, as the rulesets API names it.",
2010
+ "type": "string",
2011
+ "const": "file_extension_restriction"
2012
+ },
2013
+ "parameters": {
2014
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2015
+ "type": "object",
2016
+ "properties": {
2017
+ "restricted_file_extensions": {
2018
+ "description": "The file extensions refused.",
2019
+ "type": "array",
2020
+ "items": {
2021
+ "type": "string"
2022
+ }
2023
+ }
2024
+ },
2025
+ "required": [
2026
+ "restricted_file_extensions"
2027
+ ],
2028
+ "additionalProperties": {}
2029
+ }
2030
+ },
2031
+ "required": [
2032
+ "type"
2033
+ ],
2034
+ "additionalProperties": {}
2035
+ },
2036
+ "Rule<file_path_restriction>": {
2037
+ "description": "Commits touching the listed paths are refused.",
2038
+ "type": "object",
2039
+ "properties": {
2040
+ "type": {
2041
+ "description": "The rule type, as the rulesets API names it.",
2042
+ "type": "string",
2043
+ "const": "file_path_restriction"
2044
+ },
2045
+ "parameters": {
2046
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2047
+ "type": "object",
2048
+ "properties": {
2049
+ "restricted_file_paths": {
2050
+ "description": "The file and folder paths refused.",
2051
+ "type": "array",
2052
+ "items": {
2053
+ "type": "string"
2054
+ }
2055
+ }
2056
+ },
2057
+ "required": [
2058
+ "restricted_file_paths"
2059
+ ],
2060
+ "additionalProperties": {}
2061
+ }
2062
+ },
2063
+ "required": [
2064
+ "type"
2065
+ ],
2066
+ "additionalProperties": {}
2067
+ },
2068
+ "Rule<license_compliance_scanning>": {
2069
+ "description": "Added or changed dependencies must comply with the organization's license policy.",
2070
+ "type": "object",
2071
+ "properties": {
2072
+ "type": {
2073
+ "description": "The rule type, as the rulesets API names it.",
2074
+ "type": "string",
2075
+ "const": "license_compliance_scanning"
2076
+ }
2077
+ },
2078
+ "required": [
2079
+ "type"
2080
+ ],
2081
+ "additionalProperties": {}
2082
+ },
2083
+ "Rule<max_file_path_length>": {
2084
+ "description": "Commits with file paths over the length cap are refused.",
2085
+ "type": "object",
2086
+ "properties": {
2087
+ "type": {
2088
+ "description": "The rule type, as the rulesets API names it.",
2089
+ "type": "string",
2090
+ "const": "max_file_path_length"
2091
+ },
2092
+ "parameters": {
2093
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2094
+ "type": "object",
2095
+ "properties": {
2096
+ "max_file_path_length": {
2097
+ "description": "The most characters a file path may have (1 to 32767).",
2098
+ "type": "integer",
2099
+ "minimum": 1,
2100
+ "maximum": 32767
2101
+ }
2102
+ },
2103
+ "required": [
2104
+ "max_file_path_length"
2105
+ ],
2106
+ "additionalProperties": {}
2107
+ }
2108
+ },
2109
+ "required": [
2110
+ "type"
2111
+ ],
2112
+ "additionalProperties": {}
2113
+ },
2114
+ "Rule<max_file_size>": {
2115
+ "description": "Commits with a file over the size cap are refused.",
2116
+ "type": "object",
2117
+ "properties": {
2118
+ "type": {
2119
+ "description": "The rule type, as the rulesets API names it.",
2120
+ "type": "string",
2121
+ "const": "max_file_size"
2122
+ },
2123
+ "parameters": {
2124
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2125
+ "type": "object",
2126
+ "properties": {
2127
+ "max_file_size": {
2128
+ "description": "The largest file allowed, in megabytes (1 to 100); Git LFS objects are exempt.",
2129
+ "type": "integer",
2130
+ "minimum": 1,
2131
+ "maximum": 100
2132
+ }
2133
+ },
2134
+ "required": [
2135
+ "max_file_size"
2136
+ ],
2137
+ "additionalProperties": {}
2138
+ }
2139
+ },
2140
+ "required": [
2141
+ "type"
2142
+ ],
2143
+ "additionalProperties": {}
2144
+ },
2145
+ "Rule<merge_queue>": {
2146
+ "description": "Merges into matching branches go through a merge queue.",
2147
+ "type": "object",
2148
+ "properties": {
2149
+ "type": {
2150
+ "description": "The rule type, as the rulesets API names it.",
2151
+ "type": "string",
2152
+ "const": "merge_queue"
2153
+ },
2154
+ "parameters": {
2155
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2156
+ "type": "object",
2157
+ "properties": {
2158
+ "check_response_timeout_minutes": {
2159
+ "description": "Minutes a required status check may take before it counts as failed (1 to 360).",
2160
+ "type": "integer",
2161
+ "minimum": 1,
2162
+ "maximum": 360
2163
+ },
2164
+ "grouping_strategy": {
2165
+ "description": "ALLGREEN (every PR's merge commit must pass all required checks) or HEADGREEN (only the head of the merge group must), in GitHub's upper-case spelling.",
2166
+ "type": "string",
2167
+ "enum": [
2168
+ "ALLGREEN",
2169
+ "HEADGREEN"
2170
+ ]
2171
+ },
2172
+ "max_entries_to_build": {
2173
+ "description": "Cap on queued pull requests building at the same time (0 to 100).",
2174
+ "type": "integer",
2175
+ "minimum": 0,
2176
+ "maximum": 100
2177
+ },
2178
+ "max_entries_to_merge": {
2179
+ "description": "Cap on pull requests merged as one group (0 to 100).",
2180
+ "type": "integer",
2181
+ "minimum": 0,
2182
+ "maximum": 100
2183
+ },
2184
+ "merge_method": {
2185
+ "description": "MERGE, SQUASH, or REBASE, in GitHub's upper-case spelling (the lower-case pull_request allowed_merge_methods spelling is refused here).",
2186
+ "type": "string",
2187
+ "enum": [
2188
+ "MERGE",
2189
+ "SQUASH",
2190
+ "REBASE"
2191
+ ]
2192
+ },
2193
+ "min_entries_to_merge": {
2194
+ "description": "Minimum pull requests merged as one group (0 to 100).",
2195
+ "type": "integer",
2196
+ "minimum": 0,
2197
+ "maximum": 100
2198
+ },
2199
+ "min_entries_to_merge_wait_minutes": {
2200
+ "description": "Minutes the queue waits for the minimum group size before merging a smaller group (0 to 360).",
2201
+ "type": "integer",
2202
+ "minimum": 0,
2203
+ "maximum": 360
2204
+ }
2205
+ },
2206
+ "required": [
2207
+ "check_response_timeout_minutes",
2208
+ "grouping_strategy",
2209
+ "max_entries_to_build",
2210
+ "max_entries_to_merge",
2211
+ "merge_method",
2212
+ "min_entries_to_merge",
2213
+ "min_entries_to_merge_wait_minutes"
2214
+ ],
2215
+ "additionalProperties": {}
2216
+ }
2217
+ },
2218
+ "required": [
2219
+ "type"
2220
+ ],
2221
+ "additionalProperties": {}
2222
+ },
2223
+ "Rule<non_fast_forward>": {
2224
+ "description": "No force pushes to matching refs.",
2225
+ "type": "object",
2226
+ "properties": {
2227
+ "type": {
2228
+ "description": "The rule type, as the rulesets API names it.",
2229
+ "type": "string",
2230
+ "const": "non_fast_forward"
2231
+ }
2232
+ },
2233
+ "required": [
2234
+ "type"
2235
+ ],
2236
+ "additionalProperties": {}
2237
+ },
2238
+ "Rule<pull_request>": {
2239
+ "description": "Changes reach matching branches through a pull request only.",
2240
+ "type": "object",
2241
+ "properties": {
2242
+ "type": {
2243
+ "description": "The rule type, as the rulesets API names it.",
2244
+ "type": "string",
2245
+ "const": "pull_request"
2246
+ },
2247
+ "parameters": {
2248
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2249
+ "type": "object",
2250
+ "properties": {
2251
+ "allowed_merge_methods": {
2252
+ "description": "The merge methods allowed, lower-case merge, squash, rebase (the upper-case merge_queue spelling is refused here); at least one.",
2253
+ "minItems": 1,
2254
+ "type": "array",
2255
+ "items": {
2256
+ "type": "string",
2257
+ "enum": [
2258
+ "merge",
2259
+ "squash",
2260
+ "rebase"
2261
+ ]
2262
+ }
2263
+ },
2264
+ "dismiss_stale_reviews_on_push": {
2265
+ "description": "Whether a new reviewable push dismisses earlier approvals.",
2266
+ "type": "boolean"
2267
+ },
2268
+ "dismissal_restriction": {
2269
+ "description": "Who may dismiss pull request reviews.",
2270
+ "type": "object",
2271
+ "properties": {
2272
+ "allowed_actors": {
2273
+ "description": "The people, teams, or apps allowed to dismiss reviews.",
2274
+ "type": "array",
2275
+ "items": {
2276
+ "$ref": "#/definitions/ReviewDismissalActorConfig"
2277
+ }
2278
+ },
2279
+ "enabled": {
2280
+ "description": "Whether review dismissal is restricted to the listed actors.",
2281
+ "type": "boolean"
2282
+ }
2283
+ },
2284
+ "required": [
2285
+ "enabled"
2286
+ ],
2287
+ "additionalProperties": {}
2288
+ },
2289
+ "require_code_owner_review": {
2290
+ "description": "Whether files with a code owner need that owner's approving review.",
2291
+ "type": "boolean"
2292
+ },
2293
+ "require_last_push_approval": {
2294
+ "description": "Whether the most recent reviewable push must be approved by someone other than its pusher.",
2295
+ "type": "boolean"
2296
+ },
2297
+ "required_approving_review_count": {
2298
+ "description": "Approving reviews required (0 to 10).",
2299
+ "type": "integer",
2300
+ "minimum": 0,
2301
+ "maximum": 10
2302
+ },
2303
+ "required_review_thread_resolution": {
2304
+ "description": "Whether every review conversation must be resolved before merging.",
2305
+ "type": "boolean"
2306
+ },
2307
+ "required_reviewers": {
2308
+ "description": "Teams that must review changes to given file patterns (GitHub marks this beta).",
2309
+ "type": "array",
2310
+ "items": {
2311
+ "$ref": "#/definitions/RequiredReviewerConfig"
2312
+ }
2313
+ }
2314
+ },
2315
+ "required": [
2316
+ "dismiss_stale_reviews_on_push",
2317
+ "require_code_owner_review",
2318
+ "require_last_push_approval",
2319
+ "required_approving_review_count",
2320
+ "required_review_thread_resolution"
2321
+ ],
2322
+ "additionalProperties": {}
2323
+ }
2324
+ },
2325
+ "required": [
2326
+ "type"
2327
+ ],
2328
+ "additionalProperties": {}
2329
+ },
2330
+ "Rule<required_deployments>": {
2331
+ "description": "Named environments must deploy successfully before a push lands.",
2332
+ "type": "object",
2333
+ "properties": {
2334
+ "type": {
2335
+ "description": "The rule type, as the rulesets API names it.",
2336
+ "type": "string",
2337
+ "const": "required_deployments"
2338
+ },
2339
+ "parameters": {
2340
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2341
+ "type": "object",
2342
+ "properties": {
2343
+ "required_deployment_environments": {
2344
+ "description": "The environment names that must be deployed to first.",
2345
+ "type": "array",
2346
+ "items": {
2347
+ "type": "string"
2348
+ }
2349
+ }
2350
+ },
2351
+ "required": [
2352
+ "required_deployment_environments"
2353
+ ],
2354
+ "additionalProperties": {}
2355
+ }
2356
+ },
2357
+ "required": [
2358
+ "type"
2359
+ ],
2360
+ "additionalProperties": {}
2361
+ },
2362
+ "Rule<required_linear_history>": {
2363
+ "description": "No merge commits may be pushed to matching refs.",
2364
+ "type": "object",
2365
+ "properties": {
2366
+ "type": {
2367
+ "description": "The rule type, as the rulesets API names it.",
2368
+ "type": "string",
2369
+ "const": "required_linear_history"
2370
+ }
2371
+ },
2372
+ "required": [
2373
+ "type"
2374
+ ],
2375
+ "additionalProperties": {}
2376
+ },
2377
+ "Rule<required_signatures>": {
2378
+ "description": "Commits pushed to matching refs must carry verified signatures.",
2379
+ "type": "object",
2380
+ "properties": {
2381
+ "type": {
2382
+ "description": "The rule type, as the rulesets API names it.",
2383
+ "type": "string",
2384
+ "const": "required_signatures"
2385
+ }
2386
+ },
2387
+ "required": [
2388
+ "type"
2389
+ ],
2390
+ "additionalProperties": {}
2391
+ },
2392
+ "Rule<required_status_checks>": {
2393
+ "description": "Named status checks must pass before the ref is updated.",
2394
+ "type": "object",
2395
+ "properties": {
2396
+ "type": {
2397
+ "description": "The rule type, as the rulesets API names it.",
2398
+ "type": "string",
2399
+ "const": "required_status_checks"
2400
+ },
2401
+ "parameters": {
2402
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2403
+ "type": "object",
2404
+ "properties": {
2405
+ "do_not_enforce_on_create": {
2406
+ "description": "Whether a new ref may be created even when a check would otherwise block it.",
2407
+ "type": "boolean"
2408
+ },
2409
+ "required_status_checks": {
2410
+ "description": "The checks that must pass.",
2411
+ "type": "array",
2412
+ "items": {
2413
+ "$ref": "#/definitions/StatusCheckConfig"
2414
+ }
2415
+ },
2416
+ "strict_required_status_checks_policy": {
2417
+ "description": "Whether a pull request must be tested against the latest target commit.",
2418
+ "type": "boolean"
2419
+ }
2420
+ },
2421
+ "required": [
2422
+ "required_status_checks",
2423
+ "strict_required_status_checks_policy"
2424
+ ],
2425
+ "additionalProperties": {}
2426
+ }
2427
+ },
2428
+ "required": [
2429
+ "type"
2430
+ ],
2431
+ "additionalProperties": {}
2432
+ },
2433
+ "Rule<tag_name_pattern>": {
2434
+ "description": "Tag names must match (or not match) a pattern.",
2435
+ "type": "object",
2436
+ "properties": {
2437
+ "type": {
2438
+ "description": "The rule type, as the rulesets API names it.",
2439
+ "type": "string",
2440
+ "const": "tag_name_pattern"
2441
+ },
2442
+ "parameters": {
2443
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2444
+ "allOf": [
2445
+ {
2446
+ "$ref": "#/definitions/PatternRuleParameters"
2447
+ }
2448
+ ]
2449
+ }
2450
+ },
2451
+ "required": [
2452
+ "type"
2453
+ ],
2454
+ "additionalProperties": {}
2455
+ },
2456
+ "Rule<update>": {
2457
+ "description": "Only actors with bypass permission may update matching refs.",
2458
+ "type": "object",
2459
+ "properties": {
2460
+ "type": {
2461
+ "description": "The rule type, as the rulesets API names it.",
2462
+ "type": "string",
2463
+ "const": "update"
2464
+ },
2465
+ "parameters": {
2466
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2467
+ "type": "object",
2468
+ "properties": {
2469
+ "update_allows_fetch_and_merge": {
2470
+ "description": "Whether the branch may still pull changes from its upstream repository.",
2471
+ "type": "boolean"
2472
+ }
2473
+ },
2474
+ "required": [
2475
+ "update_allows_fetch_and_merge"
2476
+ ],
2477
+ "additionalProperties": {}
2478
+ }
2479
+ },
2480
+ "required": [
2481
+ "type"
2482
+ ],
2483
+ "additionalProperties": {}
2484
+ },
2485
+ "Rule<workflows>": {
2486
+ "description": "Named workflows must pass before changes merge into matching branches.",
2487
+ "type": "object",
2488
+ "properties": {
2489
+ "type": {
2490
+ "description": "The rule type, as the rulesets API names it.",
2491
+ "type": "string",
2492
+ "const": "workflows"
2493
+ },
2494
+ "parameters": {
2495
+ "description": "The rule's parameters, typed as the spec types them; a field GitHub adds later passes through.",
2496
+ "type": "object",
2497
+ "properties": {
2498
+ "do_not_enforce_on_create": {
2499
+ "description": "Whether a new ref may be created even when a workflow would otherwise block it.",
2500
+ "type": "boolean"
2501
+ },
2502
+ "workflows": {
2503
+ "description": "The workflow files that must pass.",
2504
+ "type": "array",
2505
+ "items": {
2506
+ "$ref": "#/definitions/WorkflowFileConfig"
2507
+ }
2508
+ }
2509
+ },
2510
+ "required": [
2511
+ "workflows"
2512
+ ],
2513
+ "additionalProperties": {}
2514
+ }
2515
+ },
2516
+ "required": [
2517
+ "type"
2518
+ ],
2519
+ "additionalProperties": {}
2520
+ },
2521
+ "RuleConfig": {
2522
+ "description": "One rule of the ruleset: a type the spec knows, with its parameters typed, or any other type, passed through as written.",
2523
+ "anyOf": [
2524
+ {
2525
+ "oneOf": [
2526
+ {
2527
+ "$ref": "#/definitions/Rule%3Ccreation%3E"
2528
+ },
2529
+ {
2530
+ "$ref": "#/definitions/Rule%3Cupdate%3E"
2531
+ },
2532
+ {
2533
+ "$ref": "#/definitions/Rule%3Cdeletion%3E"
2534
+ },
2535
+ {
2536
+ "$ref": "#/definitions/Rule%3Crequired_linear_history%3E"
2537
+ },
2538
+ {
2539
+ "$ref": "#/definitions/Rule%3Cmerge_queue%3E"
2540
+ },
2541
+ {
2542
+ "$ref": "#/definitions/Rule%3Crequired_deployments%3E"
2543
+ },
2544
+ {
2545
+ "$ref": "#/definitions/Rule%3Crequired_signatures%3E"
2546
+ },
2547
+ {
2548
+ "$ref": "#/definitions/Rule%3Cpull_request%3E"
2549
+ },
2550
+ {
2551
+ "$ref": "#/definitions/Rule%3Crequired_status_checks%3E"
2552
+ },
2553
+ {
2554
+ "$ref": "#/definitions/Rule%3Cnon_fast_forward%3E"
2555
+ },
2556
+ {
2557
+ "$ref": "#/definitions/Rule%3Ccommit_message_pattern%3E"
2558
+ },
2559
+ {
2560
+ "$ref": "#/definitions/Rule%3Ccommit_author_email_pattern%3E"
2561
+ },
2562
+ {
2563
+ "$ref": "#/definitions/Rule%3Ccommitter_email_pattern%3E"
2564
+ },
2565
+ {
2566
+ "$ref": "#/definitions/Rule%3Cbranch_name_pattern%3E"
2567
+ },
2568
+ {
2569
+ "$ref": "#/definitions/Rule%3Ctag_name_pattern%3E"
2570
+ },
2571
+ {
2572
+ "$ref": "#/definitions/Rule%3Cworkflows%3E"
2573
+ },
2574
+ {
2575
+ "$ref": "#/definitions/Rule%3Ccode_scanning%3E"
2576
+ },
2577
+ {
2578
+ "$ref": "#/definitions/Rule%3Ccopilot_code_review%3E"
2579
+ },
2580
+ {
2581
+ "$ref": "#/definitions/Rule%3Clicense_compliance_scanning%3E"
2582
+ },
2583
+ {
2584
+ "$ref": "#/definitions/Rule%3Cfile_path_restriction%3E"
2585
+ },
2586
+ {
2587
+ "$ref": "#/definitions/Rule%3Cmax_file_path_length%3E"
2588
+ },
2589
+ {
2590
+ "$ref": "#/definitions/Rule%3Cfile_extension_restriction%3E"
2591
+ },
2592
+ {
2593
+ "$ref": "#/definitions/Rule%3Cmax_file_size%3E"
2594
+ }
2595
+ ]
2596
+ },
2597
+ {
2598
+ "$ref": "#/definitions/UnknownRule"
2599
+ }
2600
+ ]
2601
+ },
2602
+ "RulesetConfig": {
2603
+ "description": "One repository ruleset, matched to the live repo by name.",
2604
+ "type": "object",
2605
+ "properties": {
2606
+ "name": {
2607
+ "description": "The ruleset name, the natural key.",
2608
+ "type": "string"
2609
+ },
2610
+ "target": {
2611
+ "description": "What the ruleset applies to. Omitted, it is \"branch\", the default GitHub documents, so a live branch ruleset is not drift under an entry without the key.",
2612
+ "default": "branch",
2613
+ "type": "string",
2614
+ "enum": [
2615
+ "branch",
2616
+ "tag",
2617
+ "push"
2618
+ ]
2619
+ },
2620
+ "enforcement": {
2621
+ "description": "\"active\", \"evaluate\", or \"disabled\", in that spelling (\"enabled\" and \"Active\" are refused at parse). Omitted, it is \"active\" (GitHub requires a value on create; this is the one chosen), so a live active ruleset is not drift under an entry without the key.",
2622
+ "default": "active",
2623
+ "type": "string",
2624
+ "enum": [
2625
+ "active",
2626
+ "evaluate",
2627
+ "disabled"
2628
+ ]
2629
+ },
2630
+ "conditions": {
2631
+ "description": "Which refs the ruleset covers.",
2632
+ "type": "object",
2633
+ "properties": {
2634
+ "ref_name": {
2635
+ "description": "Short ref names are auto-prefixed (staging -> refs/heads/staging).",
2636
+ "type": "object",
2637
+ "properties": {
2638
+ "include": {
2639
+ "description": "Ref patterns the ruleset targets (fnmatch). The tokens ~DEFAULT_BRANCH and ~ALL are accepted as written; any other value carrying \"~\", or one of \"^\", \":\", \"\\\\\", space, \"..\", \"@{\", or a control character, is refused at parse: git refuses these in a ref name and a ruleset pattern has no use for them. \"*\", \"?\", and \"[\" are pattern syntax and pass.",
2640
+ "type": "array",
2641
+ "items": {
2642
+ "type": "string",
2643
+ "pattern": "^(?:~ALL|~DEFAULT_BRANCH|(?:(?![~^:\\\\ \\x00-\\x1f\\x7f]|\\.\\.|@\\{)[\\s\\S])*)$"
2644
+ }
2645
+ },
2646
+ "exclude": {
2647
+ "description": "Ref patterns excluded from the ruleset; the same character rules apply.",
2648
+ "type": "array",
2649
+ "items": {
2650
+ "type": "string",
2651
+ "pattern": "^(?:~ALL|~DEFAULT_BRANCH|(?:(?![~^:\\\\ \\x00-\\x1f\\x7f]|\\.\\.|@\\{)[\\s\\S])*)$"
2652
+ }
2653
+ }
2654
+ }
2655
+ }
2656
+ }
2657
+ },
2658
+ "rules": {
2659
+ "description": "Rule list. A rule type the vendored spec knows has its parameters checked at parse; a type it does not know passes through verbatim, so a rule type GitHub ships tomorrow works today.",
2660
+ "type": "array",
2661
+ "items": {
2662
+ "$ref": "#/definitions/RuleConfig"
2663
+ }
2664
+ },
2665
+ "bypass_actors": {
2666
+ "description": "Who may bypass the ruleset; each actor is one (actor_type, actor_id) pair, bypass_mode defaulting to always. An entry without the key leaves a live bypass list as drift and apply refuses the PUT; `[]` clears it on purpose. GitHub returns it only to a token with write access to the ruleset, so without Administration write check mode notes it instead of judging drift.",
2667
+ "type": "array",
2668
+ "items": {
2669
+ "$ref": "#/definitions/BypassActorConfig"
2670
+ }
2671
+ }
2672
+ },
2673
+ "required": [
2674
+ "name"
2675
+ ]
2676
+ },
2677
+ "SecretScanningPatternConfig": {
2678
+ "description": "One secret scanning custom pattern, matched by exact name. Only the fields below are accepted: `state` and `push_protection_enabled` are readable but NOT writable through the custom-pattern endpoints, so they cannot be declared. A delimiter, once set, cannot be cleared back to GitHub's default through the update PATCH (the endpoint updates provided fields only); remove the pattern and redeclare it without the field instead.",
2679
+ "type": "object",
2680
+ "properties": {
2681
+ "name": {
2682
+ "description": "The pattern name, the natural key; immutable upstream, so a rename creates the new name (the old one follows the undeclared policy).",
2683
+ "type": "string"
2684
+ },
2685
+ "pattern": {
2686
+ "description": "The regular expression the secret format must match. Like every regex field here it passes a syntax check at parse, or the file is refused naming the field: the PCRE-only forms Hyperscan accepts (`(?P<name>`, `(?#comment)`, `\\x{HH}`, `(?i)`, atomic and possessive forms, `\\Q...\\E`, a leading `(*UTF8)`, `(*UTF)` or `(*UCP)`) are translated, then the result must compile as a flagless JavaScript RegExp. GitHub can still refuse at apply what Hyperscan alone refuses (lookbehind, backreferences, option modifiers).",
2687
+ "type": "string"
2688
+ },
2689
+ "start_delimiter": {
2690
+ "description": "Regular expression for the characters that must come before the secret; it passes the syntax check, like `pattern`. An empty string is rejected: a delimiter cannot be cleared through the update call - remove the pattern and redeclare it without the field instead.",
2691
+ "type": "string",
2692
+ "minLength": 1
2693
+ },
2694
+ "end_delimiter": {
2695
+ "description": "Regular expression for the characters that must come after the secret; it passes the syntax check, like `pattern`. An empty string is rejected, like start_delimiter.",
2696
+ "type": "string",
2697
+ "minLength": 1
2698
+ },
2699
+ "must_match": {
2700
+ "description": "Additional regular expressions a match must also satisfy, compared in order; each passes the syntax check, like `pattern`.",
2701
+ "type": "array",
2702
+ "items": {
2703
+ "type": "string"
2704
+ }
2705
+ },
2706
+ "must_not_match": {
2707
+ "description": "Regular expressions a match must NOT satisfy, compared in order; each passes the syntax check, like `pattern`.",
2708
+ "type": "array",
2709
+ "items": {
2710
+ "type": "string"
2711
+ }
2712
+ }
2713
+ },
2714
+ "required": [
2715
+ "name",
2716
+ "pattern"
2717
+ ]
2718
+ },
2719
+ "SecurityAndAnalysisConfig": {
2720
+ "description": "The nested security_and_analysis object, closed to the sub-keys the PATCH accepts (GitHub rejects any other with a 422). Each feature is {status: enabled/disabled}. dependabot_security_updates is not one of them: declare enable_automated_security_fixes instead.",
2721
+ "type": "object",
2722
+ "properties": {
2723
+ "advanced_security": {
2724
+ "description": "GitHub Advanced Security.",
2725
+ "allOf": [
2726
+ {
2727
+ "$ref": "#/definitions/SecurityFeatureToggle"
2728
+ }
2729
+ ]
2730
+ },
2731
+ "code_security": {
2732
+ "description": "GitHub Code Security.",
2733
+ "allOf": [
2734
+ {
2735
+ "$ref": "#/definitions/SecurityFeatureToggle"
2736
+ }
2737
+ ]
2738
+ },
2739
+ "secret_scanning": {
2740
+ "description": "Secret scanning.",
2741
+ "allOf": [
2742
+ {
2743
+ "$ref": "#/definitions/SecurityFeatureToggle"
2744
+ }
2745
+ ]
2746
+ },
2747
+ "secret_scanning_push_protection": {
2748
+ "description": "Secret scanning push protection.",
2749
+ "allOf": [
2750
+ {
2751
+ "$ref": "#/definitions/SecurityFeatureToggle"
2752
+ }
2753
+ ]
2754
+ },
2755
+ "secret_scanning_ai_detection": {
2756
+ "description": "AI detection of generic secrets.",
2757
+ "allOf": [
2758
+ {
2759
+ "$ref": "#/definitions/SecurityFeatureToggle"
2760
+ }
2761
+ ]
2762
+ },
2763
+ "secret_scanning_non_provider_patterns": {
2764
+ "description": "Non-provider secret patterns.",
2765
+ "allOf": [
2766
+ {
2767
+ "$ref": "#/definitions/SecurityFeatureToggle"
2768
+ }
2769
+ ]
2770
+ },
2771
+ "secret_scanning_delegated_alert_dismissal": {
2772
+ "description": "Delegated dismissal of secret scanning alerts.",
2773
+ "allOf": [
2774
+ {
2775
+ "$ref": "#/definitions/SecurityFeatureToggle"
2776
+ }
2777
+ ]
2778
+ },
2779
+ "secret_scanning_delegated_bypass": {
2780
+ "description": "Delegated bypass of push protection; the reviewers live in secret_scanning_delegated_bypass_options.",
2781
+ "allOf": [
2782
+ {
2783
+ "$ref": "#/definitions/SecurityFeatureToggle"
2784
+ }
2785
+ ]
2786
+ },
2787
+ "secret_scanning_delegated_bypass_options": {
2788
+ "description": "Who reviews push protection bypass requests; honored only while secret_scanning_delegated_bypass is enabled.",
2789
+ "type": "object",
2790
+ "properties": {
2791
+ "reviewers": {
2792
+ "description": "The bypass reviewers; left out, the existing set is unchanged.",
2793
+ "type": "array",
2794
+ "items": {
2795
+ "type": "object",
2796
+ "properties": {
2797
+ "reviewer_id": {
2798
+ "description": "The id of the team or role selected as a reviewer.",
2799
+ "type": "integer"
2800
+ },
2801
+ "reviewer_type": {
2802
+ "description": "TEAM or ROLE.",
2803
+ "type": "string",
2804
+ "enum": [
2805
+ "TEAM",
2806
+ "ROLE"
2807
+ ]
2808
+ },
2809
+ "mode": {
2810
+ "description": "ALWAYS (the default: every bypass needs review) or EXEMPT (this reviewer's own pushes skip it).",
2811
+ "type": "string",
2812
+ "enum": [
2813
+ "ALWAYS",
2814
+ "EXEMPT"
2815
+ ]
2816
+ }
2817
+ },
2818
+ "required": [
2819
+ "reviewer_id",
2820
+ "reviewer_type"
2821
+ ],
2822
+ "additionalProperties": false
2823
+ }
2824
+ }
2825
+ },
2826
+ "additionalProperties": false
2827
+ },
2828
+ "secret_scanning_validity_checks": {
2829
+ "description": "Validity checks for detected secrets (documented in the GHEC flavor of the spec).",
2830
+ "allOf": [
2831
+ {
2832
+ "$ref": "#/definitions/SecurityFeatureToggle"
2833
+ }
2834
+ ]
2835
+ }
2836
+ },
2837
+ "additionalProperties": false
2838
+ },
2839
+ "SecurityFeatureToggle": {
2840
+ "description": "One security_and_analysis feature.",
2841
+ "type": "object",
2842
+ "properties": {
2843
+ "status": {
2844
+ "description": "\"enabled\" or \"disabled\".",
2845
+ "type": "string",
2846
+ "enum": [
2847
+ "enabled",
2848
+ "disabled"
2849
+ ]
2850
+ }
2851
+ },
2852
+ "additionalProperties": false
2853
+ },
2854
+ "SettingsFile": {
2855
+ "description": "One settings.yml document: every top-level section is optional.",
2856
+ "type": "object",
2857
+ "properties": {
2858
+ "repository": {
2859
+ "description": "Repo fields sent verbatim to PATCH /repos/{r}, plus the special keys RepositoryConfig documents.",
2860
+ "allOf": [
2861
+ {
2862
+ "$ref": "#/definitions/RepositoryConfig"
2863
+ }
2864
+ ]
2865
+ },
2866
+ "labels": {
2867
+ "description": "Issue/PR labels; undeclared labels are DELETED by default (Probot parity; the wrapped form can set `_undeclared: keep`).",
2868
+ "anyOf": [
2869
+ {
2870
+ "type": "array",
2871
+ "items": {
2872
+ "$ref": "#/definitions/LabelConfig"
2873
+ }
2874
+ },
2875
+ {
2876
+ "$ref": "#/definitions/UndeclaredPolicyList%3CLabelConfig%3E"
2877
+ }
2878
+ ]
2879
+ },
2880
+ "rulesets": {
2881
+ "description": "Repository rulesets, upserted by name; undeclared ones are kept by default (the wrapped form can set `_undeclared: delete`).",
2882
+ "anyOf": [
2883
+ {
2884
+ "type": "array",
2885
+ "items": {
2886
+ "$ref": "#/definitions/RulesetConfig"
2887
+ }
2888
+ },
2889
+ {
2890
+ "$ref": "#/definitions/UndeclaredPolicyList%3CRulesetConfig%3E"
2891
+ }
2892
+ ]
2893
+ },
2894
+ "branches": {
2895
+ "description": "Classic branch protection per branch.",
2896
+ "anyOf": [
2897
+ {
2898
+ "type": "array",
2899
+ "items": {
2900
+ "$ref": "#/definitions/BranchConfig"
2901
+ }
2902
+ },
2903
+ {
2904
+ "$ref": "#/definitions/LayeredList%3CBranchConfig%3E"
2905
+ }
2906
+ ]
2907
+ },
2908
+ "environments": {
2909
+ "description": "Deployment environments, upserted by name.",
2910
+ "anyOf": [
2911
+ {
2912
+ "type": "array",
2913
+ "items": {
2914
+ "$ref": "#/definitions/EnvironmentConfig"
2915
+ }
2916
+ },
2917
+ {
2918
+ "$ref": "#/definitions/LayeredList%3CEnvironmentConfig%3E"
2919
+ }
2920
+ ]
2921
+ },
2922
+ "autolinks": {
2923
+ "description": "Autolink references; undeclared ones are DELETED by default (the wrapped form can set `_undeclared: keep`).",
2924
+ "anyOf": [
2925
+ {
2926
+ "type": "array",
2927
+ "items": {
2928
+ "$ref": "#/definitions/AutolinkConfig"
2929
+ }
2930
+ },
2931
+ {
2932
+ "$ref": "#/definitions/UndeclaredPolicyList%3CAutolinkConfig%3E"
2933
+ }
2934
+ ]
2935
+ },
2936
+ "actions": {
2937
+ "description": "GitHub Actions permissions for the repository.",
2938
+ "allOf": [
2939
+ {
2940
+ "$ref": "#/definitions/ActionsConfig"
2941
+ }
2942
+ ]
2943
+ },
2944
+ "actions_secrets": {
2945
+ "description": "Repository Actions secrets, written by name with values sealed client-side; each value is a whole-value `$NAME` reference to the action step's environment, never a literal. Undeclared secrets are kept by default (the wrapped form can set `_undeclared: delete`; a deleted secret's value is unrecoverable).",
2946
+ "anyOf": [
2947
+ {
2948
+ "type": "array",
2949
+ "items": {
2950
+ "$ref": "#/definitions/ActionsSecretConfig"
2951
+ }
2952
+ },
2953
+ {
2954
+ "$ref": "#/definitions/UndeclaredPolicyList%3CActionsSecretConfig%3E"
2955
+ }
2956
+ ]
2957
+ },
2958
+ "dependabot_secrets": {
2959
+ "description": "Repository Dependabot secrets (private-registry credentials Dependabot uses), written by name with values sealed client-side; each value is a whole-value `$NAME` reference to the action step's environment, never a literal. Undeclared secrets are kept by default (the wrapped form can set `_undeclared: delete`; a deleted secret's value is unrecoverable).",
2960
+ "anyOf": [
2961
+ {
2962
+ "type": "array",
2963
+ "items": {
2964
+ "$ref": "#/definitions/DependabotSecretConfig"
2965
+ }
2966
+ },
2967
+ {
2968
+ "$ref": "#/definitions/UndeclaredPolicyList%3CDependabotSecretConfig%3E"
2969
+ }
2970
+ ]
2971
+ },
2972
+ "codespaces_secrets": {
2973
+ "description": "Repository Codespaces secrets (development environment secrets), written by name with values sealed client-side; each value is a whole-value `$NAME` reference to the action step's environment, never a literal. Undeclared secrets are kept by default (the wrapped form can set `_undeclared: delete`; a deleted secret's value is unrecoverable).",
2974
+ "anyOf": [
2975
+ {
2976
+ "type": "array",
2977
+ "items": {
2978
+ "$ref": "#/definitions/CodespacesSecretConfig"
2979
+ }
2980
+ },
2981
+ {
2982
+ "$ref": "#/definitions/UndeclaredPolicyList%3CCodespacesSecretConfig%3E"
2983
+ }
2984
+ ]
2985
+ },
2986
+ "agents_secrets": {
2987
+ "description": "Repository Copilot agents secrets (the secret store Copilot coding agents read), written by name with values sealed client-side; each value is a whole-value `$NAME` reference to the action step's environment, never a literal. Undeclared secrets are kept by default (the wrapped form can set `_undeclared: delete`; a deleted secret's value is unrecoverable).",
2988
+ "anyOf": [
2989
+ {
2990
+ "type": "array",
2991
+ "items": {
2992
+ "$ref": "#/definitions/AgentsSecretConfig"
2993
+ }
2994
+ },
2995
+ {
2996
+ "$ref": "#/definitions/UndeclaredPolicyList%3CAgentsSecretConfig%3E"
2997
+ }
2998
+ ]
2999
+ },
3000
+ "workflows": {
3001
+ "description": "Per-workflow enable/disable state; undeclared workflows are untouched.",
3002
+ "anyOf": [
3003
+ {
3004
+ "type": "array",
3005
+ "items": {
3006
+ "$ref": "#/definitions/WorkflowConfig"
3007
+ }
3008
+ },
3009
+ {
3010
+ "$ref": "#/definitions/LayeredList%3CWorkflowConfig%3E"
3011
+ }
3012
+ ]
3013
+ },
3014
+ "check_suite_preferences": {
3015
+ "description": "Check suite preferences: per-GitHub-App `auto_trigger_checks` toggles controlling whether pushes automatically create check suites. Write-only upstream (GitHub exposes no read endpoint), so check mode cannot verify them and apply re-asserts the declared preferences on every run. The token owner must be a repository administrator.",
3016
+ "allOf": [
3017
+ {
3018
+ "$ref": "#/definitions/CheckSuitePreferencesConfig"
3019
+ }
3020
+ ]
3021
+ },
3022
+ "pages": {
3023
+ "description": "GitHub Pages configuration; null disables Pages on the repository.",
3024
+ "anyOf": [
3025
+ {
3026
+ "$ref": "#/definitions/PagesConfig"
3027
+ },
3028
+ {
3029
+ "type": "null"
3030
+ }
3031
+ ]
3032
+ },
3033
+ "code_scanning_default_setup": {
3034
+ "description": "Code scanning default setup (CodeQL).",
3035
+ "allOf": [
3036
+ {
3037
+ "$ref": "#/definitions/CodeScanningDefaultSetupConfig"
3038
+ }
3039
+ ]
3040
+ },
3041
+ "code_quality_setup": {
3042
+ "description": "Code quality analysis setup.",
3043
+ "allOf": [
3044
+ {
3045
+ "$ref": "#/definitions/CodeQualitySetupConfig"
3046
+ }
3047
+ ]
3048
+ },
3049
+ "collaborators": {
3050
+ "description": "Direct collaborators, with pending invitations reconciled alongside; undeclared ones are REMOVED (pending invitations cancelled) by default (owner never touched; the wrapped form can set `_undeclared: keep`).",
3051
+ "anyOf": [
3052
+ {
3053
+ "type": "array",
3054
+ "items": {
3055
+ "$ref": "#/definitions/CollaboratorConfig"
3056
+ }
3057
+ },
3058
+ {
3059
+ "$ref": "#/definitions/UndeclaredPolicyList%3CCollaboratorConfig%3E"
3060
+ }
3061
+ ]
3062
+ },
3063
+ "teams": {
3064
+ "description": "Org team access to the repo; skipped on personal accounts. Undeclared teams are kept by default and noted; the wrapped form can set `_undeclared: delete` to revoke their direct access (a grant made at the organization level is never touched). A declared child team can hold its access through an undeclared parent's grant, which `delete` revokes: declare the parent too, or keep.",
3065
+ "anyOf": [
3066
+ {
3067
+ "type": "array",
3068
+ "items": {
3069
+ "$ref": "#/definitions/TeamConfig"
3070
+ }
3071
+ },
3072
+ {
3073
+ "$ref": "#/definitions/UndeclaredPolicyList%3CTeamConfig%3E"
3074
+ }
3075
+ ]
3076
+ },
3077
+ "milestones": {
3078
+ "description": "Milestones, upserted by title; undeclared ones are kept by default (the wrapped form can set `_undeclared: delete`, which detaches deleted milestones from their issues).",
3079
+ "anyOf": [
3080
+ {
3081
+ "type": "array",
3082
+ "items": {
3083
+ "$ref": "#/definitions/MilestoneConfig"
3084
+ }
3085
+ },
3086
+ {
3087
+ "$ref": "#/definitions/UndeclaredPolicyList%3CMilestoneConfig%3E"
3088
+ }
3089
+ ]
3090
+ },
3091
+ "interaction_limits": {
3092
+ "description": "Temporary interaction limits; null clears an active repo-level limit, and an absent key leaves whatever is live untouched. Limits self-expire (GitHub's expiry tops out at six_months), so apply re-arms the declared limit on every run and check mode reports drift once it lapses. The pull_request_creation_cap and pull_request_creation_bypass keys manage the persistent pull request creation cap and its bypass list instead; `interaction_limits: null` clears the base limit only and never touches them.",
3093
+ "anyOf": [
3094
+ {
3095
+ "$ref": "#/definitions/InteractionLimitsConfig"
3096
+ },
3097
+ {
3098
+ "type": "null"
3099
+ }
3100
+ ]
3101
+ },
3102
+ "actions_variables": {
3103
+ "description": "GitHub Actions repository variables, upserted by name; undeclared ones are DELETED by default (the wrapped form can set `_undeclared: keep`). Names are case-insensitive (GitHub stores them uppercased). Values are plain text BY DESIGN - variables are readable configuration, which is what makes check-mode diffing possible; secrets are write-only material and deliberately not this section.",
3104
+ "anyOf": [
3105
+ {
3106
+ "type": "array",
3107
+ "items": {
3108
+ "$ref": "#/definitions/ActionsVariableConfig"
3109
+ }
3110
+ },
3111
+ {
3112
+ "$ref": "#/definitions/UndeclaredPolicyList%3CActionsVariableConfig%3E"
3113
+ }
3114
+ ]
3115
+ },
3116
+ "agents_variables": {
3117
+ "description": "Copilot agents repository variables (the plain-text configuration Copilot coding agents read), upserted by name; undeclared ones are DELETED by default (the wrapped form can set `_undeclared: keep`). Names are case-insensitive (GitHub stores them uppercased). Values are plain text BY DESIGN - variables are readable configuration, which is what makes check-mode diffing possible; secrets are write-only material and deliberately not this section.",
3118
+ "anyOf": [
3119
+ {
3120
+ "type": "array",
3121
+ "items": {
3122
+ "$ref": "#/definitions/AgentsVariableConfig"
3123
+ }
3124
+ },
3125
+ {
3126
+ "$ref": "#/definitions/UndeclaredPolicyList%3CAgentsVariableConfig%3E"
3127
+ }
3128
+ ]
3129
+ },
3130
+ "webhooks": {
3131
+ "description": "Repository webhooks, managed one per config.url; undeclared hooks are kept by default and surfaced as notes, since integrations create their own hooks (the wrapped form can set `_undeclared: delete`).",
3132
+ "anyOf": [
3133
+ {
3134
+ "type": "array",
3135
+ "items": {
3136
+ "$ref": "#/definitions/WebhookConfig"
3137
+ }
3138
+ },
3139
+ {
3140
+ "$ref": "#/definitions/UndeclaredPolicyList%3CWebhookConfig%3E"
3141
+ }
3142
+ ]
3143
+ },
3144
+ "custom_properties": {
3145
+ "description": "Values of organization-defined custom properties, set per repository (the property DEFINITIONS are organization-scoped and out of scope); organization repos only, skipped with a note on personal accounts. `value: null` unsets a property (reverting to the org default, if any), and booleans/numbers are normalized to their string form (GitHub transports true_false values as the strings \"true\"/\"false\"). Undeclared live values are kept by default - an unset can revert to an org default this action does not model, and a property whose values only org actors may edit would reject the write - and the wrapped form can set `_undeclared: delete` to opt into unsetting them.",
3146
+ "anyOf": [
3147
+ {
3148
+ "type": "array",
3149
+ "items": {
3150
+ "$ref": "#/definitions/CustomPropertyConfig"
3151
+ }
3152
+ },
3153
+ {
3154
+ "$ref": "#/definitions/UndeclaredPolicyList%3CCustomPropertyConfig%3E"
3155
+ }
3156
+ ]
3157
+ },
3158
+ "deploy_keys": {
3159
+ "description": "Deploy keys, matched by title. The declared material is a PUBLIC key, safe in a committed settings file. Keys are immutable upstream, so any change is applied as delete plus recreate. Undeclared keys are kept by default - deleting a live deploy key breaks whatever service authenticates with it, and deployment tooling installs its own keys - and the wrapped form can set `_undeclared: delete`.",
3160
+ "anyOf": [
3161
+ {
3162
+ "type": "array",
3163
+ "items": {
3164
+ "$ref": "#/definitions/DeployKeyConfig"
3165
+ }
3166
+ },
3167
+ {
3168
+ "$ref": "#/definitions/UndeclaredPolicyList%3CDeployKeyConfig%3E"
3169
+ }
3170
+ ]
3171
+ },
3172
+ "secret_scanning_custom_patterns": {
3173
+ "description": "Repository-level secret scanning custom patterns, matched by name. The name is immutable upstream (the update PATCH takes no name field), so a renamed entry is applied as a create of the new name - plus, under `_undeclared: delete`, deletion of the old one; under the default keep policy the old pattern stays live and is surfaced as a note. Undeclared patterns are kept by default: removing a pattern disposes of its alerts, so deletion stays a human opt-in (the wrapped form can set `_undeclared: delete`). When this action deletes a pattern it always asks GitHub to RESOLVE the pattern's alerts rather than delete them, keeping the audit trail.",
3174
+ "anyOf": [
3175
+ {
3176
+ "type": "array",
3177
+ "items": {
3178
+ "$ref": "#/definitions/SecretScanningPatternConfig"
3179
+ }
3180
+ },
3181
+ {
3182
+ "$ref": "#/definitions/UndeclaredPolicyList%3CSecretScanningPatternConfig%3E"
3183
+ }
3184
+ ]
3185
+ },
3186
+ "_layering": {
3187
+ "description": "mode: render only: a layer-level default for how this document's list sections combine with the layers below it, overriding the run's layering input; a section's own wrapper-level `_layering` overrides it again. `replace` lets each of this document's lists win wholesale; `shallow` unions the entries by the section's key and swaps a same-key entry for this document's; `deep` unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. Consumed by the render, never applied: the rendered document carries no `_layering`, and apply and check ignore it like any `_` key.",
3188
+ "type": "string",
3189
+ "enum": [
3190
+ "replace",
3191
+ "shallow",
3192
+ "deep"
3193
+ ]
3194
+ },
3195
+ "_undeclared": {
3196
+ "description": "The file-wide undeclared policy: what apply does to a live resource a list does not declare, for every list in this document that takes the `_undeclared` knob (the knobbed sections and an environment's variables, secrets, deployment branch policies, and deployment protection rules) and whose own wrapper sets none. A wrapper's `_undeclared` wins over it; it wins over the run's `undeclared` input; each list's own default applies when none of the three is set. Resolved into every list's wrapper, so the rendered document carries no `_undeclared` at its top. In a layered merge the highest layer that sets it steers the whole fold: a directive, not a merged value.",
3197
+ "allOf": [
3198
+ {
3199
+ "$ref": "#/definitions/UndeclaredPolicy"
3200
+ }
3201
+ ]
3202
+ }
3203
+ }
3204
+ },
3205
+ "StatusCheckConfig": {
3206
+ "description": "One required status check.",
3207
+ "type": "object",
3208
+ "properties": {
3209
+ "context": {
3210
+ "description": "The status check context name that must be present on the commit.",
3211
+ "type": "string"
3212
+ },
3213
+ "integration_id": {
3214
+ "description": "The GitHub App the check must come from, when pinned.",
3215
+ "type": "integer"
3216
+ }
3217
+ },
3218
+ "required": [
3219
+ "context"
3220
+ ],
3221
+ "additionalProperties": {}
3222
+ },
3223
+ "TeamConfig": {
3224
+ "description": "One org team's access to the repository, matched by team slug. Keys other than name and permission are rejected (a misspelled \"permission\" would otherwise silently grant the default role).",
3225
+ "type": "object",
3226
+ "properties": {
3227
+ "name": {
3228
+ "description": "The team slug (the name in the team's URL), the natural key: letters, digits, \".\", \"_\", and \"-\". A display name with spaces fails at parse time, since the slug is what every API path takes and a wrong one reads as \"no access\".",
3229
+ "type": "string",
3230
+ "pattern": "^(?=.*[A-Za-z0-9])[A-Za-z0-9._-]+$"
3231
+ },
3232
+ "permission": {
3233
+ "description": "Same vocabulary and parse rules as collaborators; defaults to \"push\".",
3234
+ "type": "string",
3235
+ "pattern": "^(?:pull|triage|push|maintain|admin|(?!(?:[Pp][Uu][Ll][Ll]|[Tt][Rr][Ii][Aa][Gg][Ee]|[Pp][Uu][Ss][Hh]|[Mm][Aa][Ii][Nn][Tt][Aa][Ii][Nn]|[Aa][Dd][Mm][Ii][Nn]|[Ww][Rr][Ii][Tt][Ee]|[Rr][Ee][Aa][Dd])$)\\S(?:.*\\S)?)$"
3236
+ }
3237
+ },
3238
+ "required": [
3239
+ "name"
3240
+ ]
3241
+ },
3242
+ "UndeclaredPolicy": {
3243
+ "description": "What apply does to live resources the settings file does not declare.",
3244
+ "type": "string",
3245
+ "enum": [
3246
+ "keep",
3247
+ "delete"
3248
+ ]
3249
+ },
3250
+ "UndeclaredPolicyList<ActionsSecretConfig>": {
3251
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3252
+ "type": "object",
3253
+ "properties": {
3254
+ "_undeclared": {
3255
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3256
+ "allOf": [
3257
+ {
3258
+ "$ref": "#/definitions/UndeclaredPolicy"
3259
+ }
3260
+ ]
3261
+ },
3262
+ "entries": {
3263
+ "description": "The declared entries, exactly as the plain array form lists them.",
3264
+ "type": "array",
3265
+ "items": {
3266
+ "$ref": "#/definitions/ActionsSecretConfig"
3267
+ }
3268
+ },
3269
+ "_layering": {
3270
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3271
+ "type": "string",
3272
+ "enum": [
3273
+ "replace",
3274
+ "shallow",
3275
+ "deep"
3276
+ ]
3277
+ }
3278
+ },
3279
+ "required": [
3280
+ "entries"
3281
+ ],
3282
+ "additionalProperties": false
3283
+ },
3284
+ "UndeclaredPolicyList<ActionsVariableConfig>": {
3285
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3286
+ "type": "object",
3287
+ "properties": {
3288
+ "_undeclared": {
3289
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3290
+ "allOf": [
3291
+ {
3292
+ "$ref": "#/definitions/UndeclaredPolicy"
3293
+ }
3294
+ ]
3295
+ },
3296
+ "entries": {
3297
+ "description": "The declared entries, exactly as the plain array form lists them.",
3298
+ "type": "array",
3299
+ "items": {
3300
+ "$ref": "#/definitions/ActionsVariableConfig"
3301
+ }
3302
+ },
3303
+ "_layering": {
3304
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3305
+ "type": "string",
3306
+ "enum": [
3307
+ "replace",
3308
+ "shallow",
3309
+ "deep"
3310
+ ]
3311
+ }
3312
+ },
3313
+ "required": [
3314
+ "entries"
3315
+ ],
3316
+ "additionalProperties": false
3317
+ },
3318
+ "UndeclaredPolicyList<AgentsSecretConfig>": {
3319
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3320
+ "type": "object",
3321
+ "properties": {
3322
+ "_undeclared": {
3323
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3324
+ "allOf": [
3325
+ {
3326
+ "$ref": "#/definitions/UndeclaredPolicy"
3327
+ }
3328
+ ]
3329
+ },
3330
+ "entries": {
3331
+ "description": "The declared entries, exactly as the plain array form lists them.",
3332
+ "type": "array",
3333
+ "items": {
3334
+ "$ref": "#/definitions/AgentsSecretConfig"
3335
+ }
3336
+ },
3337
+ "_layering": {
3338
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3339
+ "type": "string",
3340
+ "enum": [
3341
+ "replace",
3342
+ "shallow",
3343
+ "deep"
3344
+ ]
3345
+ }
3346
+ },
3347
+ "required": [
3348
+ "entries"
3349
+ ],
3350
+ "additionalProperties": false
3351
+ },
3352
+ "UndeclaredPolicyList<AgentsVariableConfig>": {
3353
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3354
+ "type": "object",
3355
+ "properties": {
3356
+ "_undeclared": {
3357
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3358
+ "allOf": [
3359
+ {
3360
+ "$ref": "#/definitions/UndeclaredPolicy"
3361
+ }
3362
+ ]
3363
+ },
3364
+ "entries": {
3365
+ "description": "The declared entries, exactly as the plain array form lists them.",
3366
+ "type": "array",
3367
+ "items": {
3368
+ "$ref": "#/definitions/AgentsVariableConfig"
3369
+ }
3370
+ },
3371
+ "_layering": {
3372
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3373
+ "type": "string",
3374
+ "enum": [
3375
+ "replace",
3376
+ "shallow",
3377
+ "deep"
3378
+ ]
3379
+ }
3380
+ },
3381
+ "required": [
3382
+ "entries"
3383
+ ],
3384
+ "additionalProperties": false
3385
+ },
3386
+ "UndeclaredPolicyList<AutolinkConfig>": {
3387
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3388
+ "type": "object",
3389
+ "properties": {
3390
+ "_undeclared": {
3391
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3392
+ "allOf": [
3393
+ {
3394
+ "$ref": "#/definitions/UndeclaredPolicy"
3395
+ }
3396
+ ]
3397
+ },
3398
+ "entries": {
3399
+ "description": "The declared entries, exactly as the plain array form lists them.",
3400
+ "type": "array",
3401
+ "items": {
3402
+ "$ref": "#/definitions/AutolinkConfig"
3403
+ }
3404
+ },
3405
+ "_layering": {
3406
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3407
+ "type": "string",
3408
+ "enum": [
3409
+ "replace",
3410
+ "shallow",
3411
+ "deep"
3412
+ ]
3413
+ }
3414
+ },
3415
+ "required": [
3416
+ "entries"
3417
+ ],
3418
+ "additionalProperties": false
3419
+ },
3420
+ "UndeclaredPolicyList<CodespacesSecretConfig>": {
3421
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3422
+ "type": "object",
3423
+ "properties": {
3424
+ "_undeclared": {
3425
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3426
+ "allOf": [
3427
+ {
3428
+ "$ref": "#/definitions/UndeclaredPolicy"
3429
+ }
3430
+ ]
3431
+ },
3432
+ "entries": {
3433
+ "description": "The declared entries, exactly as the plain array form lists them.",
3434
+ "type": "array",
3435
+ "items": {
3436
+ "$ref": "#/definitions/CodespacesSecretConfig"
3437
+ }
3438
+ },
3439
+ "_layering": {
3440
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3441
+ "type": "string",
3442
+ "enum": [
3443
+ "replace",
3444
+ "shallow",
3445
+ "deep"
3446
+ ]
3447
+ }
3448
+ },
3449
+ "required": [
3450
+ "entries"
3451
+ ],
3452
+ "additionalProperties": false
3453
+ },
3454
+ "UndeclaredPolicyList<CollaboratorConfig>": {
3455
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3456
+ "type": "object",
3457
+ "properties": {
3458
+ "_undeclared": {
3459
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3460
+ "allOf": [
3461
+ {
3462
+ "$ref": "#/definitions/UndeclaredPolicy"
3463
+ }
3464
+ ]
3465
+ },
3466
+ "entries": {
3467
+ "description": "The declared entries, exactly as the plain array form lists them.",
3468
+ "type": "array",
3469
+ "items": {
3470
+ "$ref": "#/definitions/CollaboratorConfig"
3471
+ }
3472
+ },
3473
+ "_layering": {
3474
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3475
+ "type": "string",
3476
+ "enum": [
3477
+ "replace",
3478
+ "shallow",
3479
+ "deep"
3480
+ ]
3481
+ }
3482
+ },
3483
+ "required": [
3484
+ "entries"
3485
+ ],
3486
+ "additionalProperties": false
3487
+ },
3488
+ "UndeclaredPolicyList<CustomPropertyConfig>": {
3489
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3490
+ "type": "object",
3491
+ "properties": {
3492
+ "_undeclared": {
3493
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3494
+ "allOf": [
3495
+ {
3496
+ "$ref": "#/definitions/UndeclaredPolicy"
3497
+ }
3498
+ ]
3499
+ },
3500
+ "entries": {
3501
+ "description": "The declared entries, exactly as the plain array form lists them.",
3502
+ "type": "array",
3503
+ "items": {
3504
+ "$ref": "#/definitions/CustomPropertyConfig"
3505
+ }
3506
+ },
3507
+ "_layering": {
3508
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3509
+ "type": "string",
3510
+ "enum": [
3511
+ "replace",
3512
+ "shallow",
3513
+ "deep"
3514
+ ]
3515
+ }
3516
+ },
3517
+ "required": [
3518
+ "entries"
3519
+ ],
3520
+ "additionalProperties": false
3521
+ },
3522
+ "UndeclaredPolicyList<DependabotSecretConfig>": {
3523
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3524
+ "type": "object",
3525
+ "properties": {
3526
+ "_undeclared": {
3527
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3528
+ "allOf": [
3529
+ {
3530
+ "$ref": "#/definitions/UndeclaredPolicy"
3531
+ }
3532
+ ]
3533
+ },
3534
+ "entries": {
3535
+ "description": "The declared entries, exactly as the plain array form lists them.",
3536
+ "type": "array",
3537
+ "items": {
3538
+ "$ref": "#/definitions/DependabotSecretConfig"
3539
+ }
3540
+ },
3541
+ "_layering": {
3542
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3543
+ "type": "string",
3544
+ "enum": [
3545
+ "replace",
3546
+ "shallow",
3547
+ "deep"
3548
+ ]
3549
+ }
3550
+ },
3551
+ "required": [
3552
+ "entries"
3553
+ ],
3554
+ "additionalProperties": false
3555
+ },
3556
+ "UndeclaredPolicyList<DeployKeyConfig>": {
3557
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3558
+ "type": "object",
3559
+ "properties": {
3560
+ "_undeclared": {
3561
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3562
+ "allOf": [
3563
+ {
3564
+ "$ref": "#/definitions/UndeclaredPolicy"
3565
+ }
3566
+ ]
3567
+ },
3568
+ "entries": {
3569
+ "description": "The declared entries, exactly as the plain array form lists them.",
3570
+ "type": "array",
3571
+ "items": {
3572
+ "$ref": "#/definitions/DeployKeyConfig"
3573
+ }
3574
+ },
3575
+ "_layering": {
3576
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3577
+ "type": "string",
3578
+ "enum": [
3579
+ "replace",
3580
+ "shallow",
3581
+ "deep"
3582
+ ]
3583
+ }
3584
+ },
3585
+ "required": [
3586
+ "entries"
3587
+ ],
3588
+ "additionalProperties": false
3589
+ },
3590
+ "UndeclaredPolicyList<DeploymentBranchPolicyConfig>": {
3591
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3592
+ "type": "object",
3593
+ "properties": {
3594
+ "_undeclared": {
3595
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3596
+ "allOf": [
3597
+ {
3598
+ "$ref": "#/definitions/UndeclaredPolicy"
3599
+ }
3600
+ ]
3601
+ },
3602
+ "entries": {
3603
+ "description": "The declared entries, exactly as the plain array form lists them.",
3604
+ "type": "array",
3605
+ "items": {
3606
+ "$ref": "#/definitions/DeploymentBranchPolicyConfig"
3607
+ }
3608
+ }
3609
+ },
3610
+ "required": [
3611
+ "entries"
3612
+ ],
3613
+ "additionalProperties": false
3614
+ },
3615
+ "UndeclaredPolicyList<DeploymentProtectionRuleConfig>": {
3616
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3617
+ "type": "object",
3618
+ "properties": {
3619
+ "_undeclared": {
3620
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3621
+ "allOf": [
3622
+ {
3623
+ "$ref": "#/definitions/UndeclaredPolicy"
3624
+ }
3625
+ ]
3626
+ },
3627
+ "entries": {
3628
+ "description": "The declared entries, exactly as the plain array form lists them.",
3629
+ "type": "array",
3630
+ "items": {
3631
+ "$ref": "#/definitions/DeploymentProtectionRuleConfig"
3632
+ }
3633
+ }
3634
+ },
3635
+ "required": [
3636
+ "entries"
3637
+ ],
3638
+ "additionalProperties": false
3639
+ },
3640
+ "UndeclaredPolicyList<EnvironmentSecretConfig>": {
3641
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3642
+ "type": "object",
3643
+ "properties": {
3644
+ "_undeclared": {
3645
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3646
+ "allOf": [
3647
+ {
3648
+ "$ref": "#/definitions/UndeclaredPolicy"
3649
+ }
3650
+ ]
3651
+ },
3652
+ "entries": {
3653
+ "description": "The declared entries, exactly as the plain array form lists them.",
3654
+ "type": "array",
3655
+ "items": {
3656
+ "$ref": "#/definitions/EnvironmentSecretConfig"
3657
+ }
3658
+ }
3659
+ },
3660
+ "required": [
3661
+ "entries"
3662
+ ],
3663
+ "additionalProperties": false
3664
+ },
3665
+ "UndeclaredPolicyList<EnvironmentVariableConfig>": {
3666
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3667
+ "type": "object",
3668
+ "properties": {
3669
+ "_undeclared": {
3670
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3671
+ "allOf": [
3672
+ {
3673
+ "$ref": "#/definitions/UndeclaredPolicy"
3674
+ }
3675
+ ]
3676
+ },
3677
+ "entries": {
3678
+ "description": "The declared entries, exactly as the plain array form lists them.",
3679
+ "type": "array",
3680
+ "items": {
3681
+ "$ref": "#/definitions/EnvironmentVariableConfig"
3682
+ }
3683
+ }
3684
+ },
3685
+ "required": [
3686
+ "entries"
3687
+ ],
3688
+ "additionalProperties": false
3689
+ },
3690
+ "UndeclaredPolicyList<LabelConfig>": {
3691
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3692
+ "type": "object",
3693
+ "properties": {
3694
+ "_undeclared": {
3695
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3696
+ "allOf": [
3697
+ {
3698
+ "$ref": "#/definitions/UndeclaredPolicy"
3699
+ }
3700
+ ]
3701
+ },
3702
+ "entries": {
3703
+ "description": "The declared entries, exactly as the plain array form lists them.",
3704
+ "type": "array",
3705
+ "items": {
3706
+ "$ref": "#/definitions/LabelConfig"
3707
+ }
3708
+ },
3709
+ "_layering": {
3710
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3711
+ "type": "string",
3712
+ "enum": [
3713
+ "replace",
3714
+ "shallow",
3715
+ "deep"
3716
+ ]
3717
+ }
3718
+ },
3719
+ "required": [
3720
+ "entries"
3721
+ ],
3722
+ "additionalProperties": false
3723
+ },
3724
+ "UndeclaredPolicyList<MilestoneConfig>": {
3725
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3726
+ "type": "object",
3727
+ "properties": {
3728
+ "_undeclared": {
3729
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3730
+ "allOf": [
3731
+ {
3732
+ "$ref": "#/definitions/UndeclaredPolicy"
3733
+ }
3734
+ ]
3735
+ },
3736
+ "entries": {
3737
+ "description": "The declared entries, exactly as the plain array form lists them.",
3738
+ "type": "array",
3739
+ "items": {
3740
+ "$ref": "#/definitions/MilestoneConfig"
3741
+ }
3742
+ },
3743
+ "_layering": {
3744
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3745
+ "type": "string",
3746
+ "enum": [
3747
+ "replace",
3748
+ "shallow",
3749
+ "deep"
3750
+ ]
3751
+ }
3752
+ },
3753
+ "required": [
3754
+ "entries"
3755
+ ],
3756
+ "additionalProperties": false
3757
+ },
3758
+ "UndeclaredPolicyList<RulesetConfig>": {
3759
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3760
+ "type": "object",
3761
+ "properties": {
3762
+ "_undeclared": {
3763
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3764
+ "allOf": [
3765
+ {
3766
+ "$ref": "#/definitions/UndeclaredPolicy"
3767
+ }
3768
+ ]
3769
+ },
3770
+ "entries": {
3771
+ "description": "The declared entries, exactly as the plain array form lists them.",
3772
+ "type": "array",
3773
+ "items": {
3774
+ "$ref": "#/definitions/RulesetConfig"
3775
+ }
3776
+ },
3777
+ "_layering": {
3778
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3779
+ "type": "string",
3780
+ "enum": [
3781
+ "replace",
3782
+ "shallow",
3783
+ "deep"
3784
+ ]
3785
+ }
3786
+ },
3787
+ "required": [
3788
+ "entries"
3789
+ ],
3790
+ "additionalProperties": false
3791
+ },
3792
+ "UndeclaredPolicyList<SecretScanningPatternConfig>": {
3793
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3794
+ "type": "object",
3795
+ "properties": {
3796
+ "_undeclared": {
3797
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3798
+ "allOf": [
3799
+ {
3800
+ "$ref": "#/definitions/UndeclaredPolicy"
3801
+ }
3802
+ ]
3803
+ },
3804
+ "entries": {
3805
+ "description": "The declared entries, exactly as the plain array form lists them.",
3806
+ "type": "array",
3807
+ "items": {
3808
+ "$ref": "#/definitions/SecretScanningPatternConfig"
3809
+ }
3810
+ },
3811
+ "_layering": {
3812
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3813
+ "type": "string",
3814
+ "enum": [
3815
+ "replace",
3816
+ "shallow",
3817
+ "deep"
3818
+ ]
3819
+ }
3820
+ },
3821
+ "required": [
3822
+ "entries"
3823
+ ],
3824
+ "additionalProperties": false
3825
+ },
3826
+ "UndeclaredPolicyList<TeamConfig>": {
3827
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3828
+ "type": "object",
3829
+ "properties": {
3830
+ "_undeclared": {
3831
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3832
+ "allOf": [
3833
+ {
3834
+ "$ref": "#/definitions/UndeclaredPolicy"
3835
+ }
3836
+ ]
3837
+ },
3838
+ "entries": {
3839
+ "description": "The declared entries, exactly as the plain array form lists them.",
3840
+ "type": "array",
3841
+ "items": {
3842
+ "$ref": "#/definitions/TeamConfig"
3843
+ }
3844
+ },
3845
+ "_layering": {
3846
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3847
+ "type": "string",
3848
+ "enum": [
3849
+ "replace",
3850
+ "shallow",
3851
+ "deep"
3852
+ ]
3853
+ }
3854
+ },
3855
+ "required": [
3856
+ "entries"
3857
+ ],
3858
+ "additionalProperties": false
3859
+ },
3860
+ "UndeclaredPolicyList<WebhookConfig>": {
3861
+ "description": "The wrapped form of a list, overriding what happens to live resources the file does not declare. The plain array form takes the file's top-level `_undeclared`, else the run's `undeclared` input, else the list's own default (the section default for a top-level section, a fixed default for a nested list such as environments[].variables); this wrapper can set it explicitly, and with `_undeclared` omitted it behaves exactly like the plain array. The wrapper is this action's own vocabulary (nothing here passes through to GitHub), so its keys are strict: anything besides `_undeclared`, `entries`, and `_layering` (the directives wear the underscore; a nested list's wrapper does not take `_layering`) is rejected upfront as a typo.",
3862
+ "type": "object",
3863
+ "properties": {
3864
+ "_undeclared": {
3865
+ "description": "What apply does to live resources `entries` does not declare: \"delete\" removes them, \"keep\" leaves them alone and surfaces each as a note. Omitted, the file's top-level `_undeclared` applies, else the run's `undeclared` input, else the list's own default.",
3866
+ "allOf": [
3867
+ {
3868
+ "$ref": "#/definitions/UndeclaredPolicy"
3869
+ }
3870
+ ]
3871
+ },
3872
+ "entries": {
3873
+ "description": "The declared entries, exactly as the plain array form lists them.",
3874
+ "type": "array",
3875
+ "items": {
3876
+ "$ref": "#/definitions/WebhookConfig"
3877
+ }
3878
+ },
3879
+ "_layering": {
3880
+ "description": "A render-time directive: how this section combines with the layers BELOW it in a layered merge, by the section's key (a label's name, a secret's name, a webhook's URL, ...). \"replace\" lets this layer's list win wholesale; \"shallow\" unions the entries by key and swaps a same-key entry for this layer's; \"deep\" unions by key and merges a same-key pair field by field, a nested keyed list (a ruleset's rules, by type) unioning the same way. To clear a list, write \"replace\" with an empty list: under \"shallow\" and \"deep\" an empty list adds nothing. Omitted, the file's `_layering` applies, else the run's layering. It has no effect on a single document, the rendered document never carries it, and a list nested inside a section entry does not take it.",
3881
+ "type": "string",
3882
+ "enum": [
3883
+ "replace",
3884
+ "shallow",
3885
+ "deep"
3886
+ ]
3887
+ }
3888
+ },
3889
+ "required": [
3890
+ "entries"
3891
+ ],
3892
+ "additionalProperties": false
3893
+ },
3894
+ "UnknownRule": {
3895
+ "description": "A rule type the vendored spec does not know, passed through verbatim so a type GitHub ships tomorrow reaches it the day it ships; a typo comes back as GitHub's own 422 naming it.",
3896
+ "type": "object",
3897
+ "properties": {
3898
+ "type": {
3899
+ "description": "The rule type, as the rulesets API names it; none of the types the spec knows.",
3900
+ "type": "string",
3901
+ "not": {
3902
+ "enum": [
3903
+ "creation",
3904
+ "update",
3905
+ "deletion",
3906
+ "required_linear_history",
3907
+ "merge_queue",
3908
+ "required_deployments",
3909
+ "required_signatures",
3910
+ "pull_request",
3911
+ "required_status_checks",
3912
+ "non_fast_forward",
3913
+ "commit_message_pattern",
3914
+ "commit_author_email_pattern",
3915
+ "committer_email_pattern",
3916
+ "branch_name_pattern",
3917
+ "tag_name_pattern",
3918
+ "workflows",
3919
+ "code_scanning",
3920
+ "copilot_code_review",
3921
+ "license_compliance_scanning",
3922
+ "file_path_restriction",
3923
+ "max_file_path_length",
3924
+ "file_extension_restriction",
3925
+ "max_file_size"
3926
+ ]
3927
+ }
3928
+ },
3929
+ "parameters": {
3930
+ "description": "The rule's parameters, as the API documents them for its type.",
3931
+ "type": "object",
3932
+ "additionalProperties": {}
3933
+ }
3934
+ },
3935
+ "required": [
3936
+ "type"
3937
+ ],
3938
+ "additionalProperties": {}
3939
+ },
3940
+ "WebhookConfig": {
3941
+ "description": "One repository webhook, matched to the live repo by config.url. Hook URLs are configuration, not credentials: they appear in drift lines and notes on purpose. The secret never does.",
3942
+ "type": "object",
3943
+ "properties": {
3944
+ "name": {
3945
+ "description": "GitHub's hook name; \"web\" is the only value modern hooks take, so anything else is rejected.",
3946
+ "type": "string",
3947
+ "const": "web"
3948
+ },
3949
+ "config": {
3950
+ "description": "The delivery settings; config.url is the natural key.",
3951
+ "allOf": [
3952
+ {
3953
+ "$ref": "#/definitions/WebhookDeliveryConfig"
3954
+ }
3955
+ ]
3956
+ },
3957
+ "events": {
3958
+ "description": "Events that trigger deliveries, compared order-insensitively; GitHub defaults a new hook to [\"push\"]. Each name is one GitHub delivers to repository webhooks, or \"*\" for every event; anything else is refused at parse time, since GitHub would 422 it at apply time. The accepted names come from GitHub's webhooks OpenAPI description, pinned through the @octokit/openapi-webhooks package, so an event GitHub adds is accepted once a release bumps that package.",
3959
+ "type": "array",
3960
+ "items": {
3961
+ "type": "string",
3962
+ "enum": [
3963
+ "branch_protection_configuration",
3964
+ "branch_protection_rule",
3965
+ "check_run",
3966
+ "check_suite",
3967
+ "code_scanning_alert",
3968
+ "commit_comment",
3969
+ "create",
3970
+ "custom_property_values",
3971
+ "delete",
3972
+ "dependabot_alert",
3973
+ "deploy_key",
3974
+ "deployment",
3975
+ "deployment_status",
3976
+ "discussion",
3977
+ "discussion_comment",
3978
+ "fork",
3979
+ "gollum",
3980
+ "issue_comment",
3981
+ "issue_dependencies",
3982
+ "issues",
3983
+ "label",
3984
+ "member",
3985
+ "meta",
3986
+ "milestone",
3987
+ "package",
3988
+ "page_build",
3989
+ "ping",
3990
+ "project",
3991
+ "project_card",
3992
+ "project_column",
3993
+ "public",
3994
+ "pull_request",
3995
+ "pull_request_review",
3996
+ "pull_request_review_comment",
3997
+ "pull_request_review_thread",
3998
+ "push",
3999
+ "registry_package",
4000
+ "release",
4001
+ "repository",
4002
+ "repository_advisory",
4003
+ "repository_import",
4004
+ "repository_ruleset",
4005
+ "repository_vulnerability_alert",
4006
+ "secret_scanning_alert",
4007
+ "secret_scanning_alert_location",
4008
+ "secret_scanning_scan",
4009
+ "security_and_analysis",
4010
+ "star",
4011
+ "status",
4012
+ "sub_issues",
4013
+ "team_add",
4014
+ "watch",
4015
+ "workflow_job",
4016
+ "workflow_run",
4017
+ "*"
4018
+ ]
4019
+ }
4020
+ },
4021
+ "active": {
4022
+ "description": "Whether deliveries fire; GitHub defaults a new hook to true.",
4023
+ "type": "boolean"
4024
+ }
4025
+ },
4026
+ "required": [
4027
+ "config"
4028
+ ]
4029
+ },
4030
+ "WebhookDeliveryConfig": {
4031
+ "description": "A webhook's `config` mapping, sent to the config sub-endpoint on update.",
4032
+ "type": "object",
4033
+ "properties": {
4034
+ "url": {
4035
+ "description": "The delivery URL, the natural key: a changed url declares a NEW hook (the old one becomes undeclared). Must be an absolute URL; GitHub refuses anything else.",
4036
+ "type": "string"
4037
+ },
4038
+ "content_type": {
4039
+ "description": "Payload encoding: exactly \"json\" or \"form\" (GitHub's default); other spellings such as \"JSON\" or a MIME type are refused at parse time.",
4040
+ "type": "string",
4041
+ "enum": [
4042
+ "json",
4043
+ "form"
4044
+ ]
4045
+ },
4046
+ "secret": {
4047
+ "description": "The shared delivery secret, as a whole-value `$NAME` reference to an environment variable on the action step (never a literal: settings files are committed plaintext). Resolved at apply time; GitHub echoes it back as \"********\", so check mode cannot verify it and apply re-sends it on every run so rotations propagate.",
4048
+ "type": "string"
4049
+ },
4050
+ "insecure_ssl": {
4051
+ "description": "Whether to skip TLS verification: \"0\" (verify) or \"1\" (skip), as the string or the number; GitHub stores the string, and any other spelling is refused at parse time.",
4052
+ "anyOf": [
4053
+ {
4054
+ "type": "string",
4055
+ "enum": [
4056
+ "0",
4057
+ "1"
4058
+ ]
4059
+ },
4060
+ {
4061
+ "type": "number",
4062
+ "const": 0
4063
+ },
4064
+ {
4065
+ "type": "number",
4066
+ "const": 1
4067
+ }
4068
+ ]
4069
+ }
4070
+ },
4071
+ "required": [
4072
+ "url"
4073
+ ],
4074
+ "additionalProperties": {
4075
+ "description": "Future config fields pass through verbatim."
4076
+ }
4077
+ },
4078
+ "WorkflowConfig": {
4079
+ "description": "One workflow's enable/disable state, keyed by its file path. Keys other than path and state are rejected (the enable/disable calls carry no payload, so an extra key could only be a typo).",
4080
+ "type": "object",
4081
+ "properties": {
4082
+ "path": {
4083
+ "description": "Full \".github/workflows/ci.yml\" or the bare \"ci.yml\" file name.",
4084
+ "type": "string"
4085
+ },
4086
+ "state": {
4087
+ "description": "Desired state; every live disabled_* variant counts as \"disabled\".",
4088
+ "type": "string",
4089
+ "enum": [
4090
+ "active",
4091
+ "disabled"
4092
+ ]
4093
+ }
4094
+ },
4095
+ "required": [
4096
+ "path",
4097
+ "state"
4098
+ ]
4099
+ },
4100
+ "WorkflowFileConfig": {
4101
+ "description": "One workflow that must run for the rule to pass.",
4102
+ "type": "object",
4103
+ "properties": {
4104
+ "path": {
4105
+ "description": "The path to the workflow file.",
4106
+ "type": "string"
4107
+ },
4108
+ "ref": {
4109
+ "description": "The branch or tag of the workflow file to use.",
4110
+ "type": "string"
4111
+ },
4112
+ "repository_id": {
4113
+ "description": "The id of the repository that holds the workflow.",
4114
+ "type": "integer"
4115
+ },
4116
+ "sha": {
4117
+ "description": "The commit of the workflow file to use.",
4118
+ "type": "string"
4119
+ }
4120
+ },
4121
+ "required": [
4122
+ "path",
4123
+ "repository_id"
4124
+ ],
4125
+ "additionalProperties": {}
4126
+ }
4127
+ }
4128
+ }