diff --git a/aiden/main.tf b/aiden/main.tf index 405cf9a..000a8c9 100644 --- a/aiden/main.tf +++ b/aiden/main.tf @@ -308,10 +308,10 @@ resource "sg_workflow" "bootstrap" { { stage_id = "open-controls-pr", description = "Copy reviewed templates and open one security-controls PR only when the control is absent. When it is already present, record the verified main commit and continue; do not end the workflow.", required = true }, { stage_id = "validate-controls-pr", description = "Verify identity, base, prefix, paths, digests, file types, checks, and unchanged head SHA only for a controls PR. With an existing main control, record this stage as safely not required and continue; do not end the workflow.", required = true }, { stage_id = "merge-controls-pr", description = "Auto-merge only the validated controls PR without submitting an approval. With an existing main control, record no merge required and continue to configure-gate; do not end the workflow.", required = true }, - { stage_id = "configure-gate", description = "Create or verify the dedicated security-gate ruleset and record its ID. This stage is required whether controls were newly installed or already present.", required = true }, - { stage_id = "comment-application-pr", description = "Comment on the original PR with an exact audit summary using gh pr comment --body-file, never --body @path. This stage is required whether controls were newly installed or already present.", required = true }, - { stage_id = "update-application-branch", description = "Update the original branch with expected_head_sha compare-and-swap. This stage is required whether controls were newly installed or already present.", required = true }, - { stage_id = "verify-security-run", description = "Verify a new SHA and started Security gate workflow.", required = true }, + { stage_id = "configure-gate", description = "Create or verify the dedicated security-gate ruleset when repository administration is available; record a permission or plan limitation and continue otherwise. This cannot end the workflow before the application branch is advanced.", required = true }, + { stage_id = "comment-application-pr", description = "Comment on the original PR with an exact audit summary using gh pr comment --body-file, never --body @path, even when ruleset administration is unavailable.", required = true }, + { stage_id = "update-application-branch", description = "Update the original branch with expected_head_sha compare-and-swap after the audit comment. A genuine conflict or concurrent-head mismatch must be commented explicitly.", required = true }, + { stage_id = "verify-security-run", description = "Require a new application SHA and started Security gate workflow before completing; do not finish after controls merge alone.", required = true }, ] stage_bindings = [ diff --git a/aiden/runbooks/security-control-bootstrap.md.tftpl b/aiden/runbooks/security-control-bootstrap.md.tftpl index bfa0da1..8d975e1 100644 --- a/aiden/runbooks/security-control-bootstrap.md.tftpl +++ b/aiden/runbooks/security-control-bootstrap.md.tftpl @@ -10,7 +10,7 @@ Repository allowlist: `${repository}`. Default branch: `${default_branch}`. Auth 6. Only for a newly created or reused controls PR, re-read it. Require author `${github_app_login}`, expected base, expected branch prefix, exact allowlisted destinations, exact digests, no additional files, no binaries, no symlinks, no submodules, and unchanged controls head SHA. 7. Only for a controls PR, wait for required validation checks. Stop if any required check is not successful. 8. Only for a controls PR, merge it using its validated head SHA. Do not approve it and do not use a force operation. -9. Verify destinations on `${default_branch}`. Create or update a dedicated ruleset named `talkdesk-demo-security-gate` requiring a strict status check named `security-gate`; do not call the ruleset installed if that rule is absent. Grant `${github_app_login}` bypass for pull requests only. Store its numeric ID in repository variable `DEMO_SECURITY_RULESET_ID`. If GitHub returns its private-repository 403 upgrade response for rulesets, record `ruleset_status=unavailable_on_current_plan`, do not claim a requirement was configured, and continue: the visible `Security gate` workflow still runs. Treat any other ruleset error as a stop condition. -10. Comment once on the original application PR with the controls PR URL and merge SHA when this run installed controls, otherwise the verified `${default_branch}` control commit; include installed destinations, `security-gate`, the truthful ruleset status, and that the branch will now be updated. Write the comment to a temporary file and invoke `gh pr comment --repo ${repository} --body-file `; do not use `--body @`, which posts the literal file name. -11. Only after the comment succeeds, call GitHub update-branch for the application PR with its captured SHA as `expected_head_sha`. If the branch already contains the current `${default_branch}` head, record that no update is required and continue to verification; do not treat an already-up-to-date branch as a failure. -12. Verify the application head SHA changed and a workflow named `Security gate` started for that SHA. Comment and stop on conflicts or concurrent changes. +9. Verify destinations on `${default_branch}`. Attempt to create or update a dedicated ruleset named `talkdesk-demo-security-gate` requiring a strict status check named `security-gate`; do not call the ruleset installed if that rule is absent. Grant `${github_app_login}` bypass for pull requests only. Ruleset administration, and storing its ID in a repository Actions variable, are optional convenience actions. If GitHub denies either operation because the integration lacks repository-administration permission or the current plan does not support rulesets, set `ruleset_status=unavailable` and continue; the visible `Security gate` workflow remains the deterministic enforcement. Stop only on an error that indicates an unexpected repository or control-integrity condition. +10. Comment once on the original application PR with the controls PR URL and merge SHA when this run installed controls, otherwise the verified `${default_branch}` control commit; include installed destinations, `security-gate`, the truthful ruleset status, and that the branch will now be updated. Write the comment to a temporary file and invoke `gh pr comment --repo ${repository} --body-file `; do not use `--body @`, which posts the literal file name. This comment is mandatory even when `ruleset_status=unavailable`. +11. Only after the comment succeeds, call GitHub update-branch for the application PR with its captured SHA as `expected_head_sha`. Treat HTTP 202 as accepted and poll the PR. If the branch already contains the current `${default_branch}` head, record that no update is required and continue to verification; do not treat an already-up-to-date branch as a failure. +12. Verify the application head SHA changed and a workflow named `Security gate` started for that SHA. The workflow must not complete until this verification succeeds. Comment and stop on a genuine update conflict or concurrent-head mismatch; do not stop after controls merge or ruleset configuration.