Imported from VilnaCRM-Org/bootstrap-infrastructure (
AGENTS.md). Install upstream withnpx skills add VilnaCRM-Org/bootstrap-infrastructure. Copyright stays with the author.
AGENTS
This repository is a Pulumi-based infrastructure template. Agents should keep changes minimal, preserve the local developer workflow, and avoid introducing hidden cloud dependencies into CI.
Working rules
- Make the smallest change that satisfies the task.
- Prefer updating tests, docs, and examples before widening release or deployment behavior.
- Run the narrowest useful validation for the files you touched.
- Use
pulumi -C pulumi ...for direct Pulumi CLI commands. - Use
uv run ...for Python CLI commands instead of invoking tools directly from the global environment. - Seed local
uvenvironments withexport UV_PROJECT_ENVIRONMENT="${HOME}/.venvs/bootstrap-infrastructure"; uv venv --seed "${UV_PROJECT_ENVIRONMENT}"before syncing if you need to run Pulumi Automation outside Docker. - Keep the structural, policy, quality, unit, integration, mutation, CLI, and aggregate local-battery suites runnable without live AWS credentials.
- Use
make ci-prwhen you want the non-mutation GitHub PR battery,make cifor the full local superset including mutation, andmake testfor the faster non-mutation developer battery. - Use
make doctorbefore debugging local Docker or Compose issues. - Run
make startwhen changing Docker-backed CI jobs so workspace preparation stays consistent across workflows and local runs. - Keep
./scripts/prepare_policy_pack.py,policy/PulumiPolicy.yaml,policy/.venv, and the shareduvenvironment contract aligned when changing Pulumi policy-pack behavior. - Reproduce PR safety checks with
make test-security,make test-repo-hygiene,make test-guardrails, ormake ci-prbefore pushing infra-related workflow or policy changes. - Do not add long-lived static AWS credentials to workflows; use the documented OIDC role variables instead.
- Treat
allow-destructive-infra-changeas the only supported override for destructive Pulumi diffs. - Keep
make test-coveragegreen when changing Python code; the repo expects 100% branch coverage across the covered Pulumi, policy, and helper modules, with the unit, integration, and policy suites each held to 100% line coverage. - Keep
make test-dependency-hygienegreen when editingpyproject.toml,uv.lock, or import relationships. - Use
make report-qualitywhen you need the scheduled Wily, Vulture, docstring-coverage, and SBOM reports locally. - If local Pulumi plugin downloads hit GitHub rate limits, pass
GITHUB_TOKEN="$(gh auth token)"only to the specific preview-oriented Make command you are running. - Prefer Make targets plus Python helpers under
scripts/*.py; do not introduce new repository bash helper scripts for CI orchestration. - Treat shared Pulumi backends as KMS-backed for CI and maintainer docs; do not document passphrase-backed shared backends as the default path.
BMAD/BMALPH planning
- Keep BMAD and BMALPH planning artifacts under
specs/. - Create one
specs/<issue-or-feature-slug>/directory per planned change, and put PRDs, architecture notes, epics/stories, readiness reports, and review scorecards there. - When asking BMAD agents or BMALPH workflows to create or update planning docs, explicitly tell them to use
specs/<issue-or-feature-slug>/as the planning output directory. - If a local BMAD installation generates
_bmad/config.yaml, setoutput_folder: specsandplanning_artifacts: specsbefore generating planning documents. - Treat
.ralph/specs/as BMALPH/Ralph generated implementation input only; do not use it as the canonical planning source. - Do not commit generated BMAD/BMALPH/Ralph framework or state files such as
_bmad/,_bmad-output/,bmalph/,.ralph/, or.agents/skills/bmad-*. - Do not commit alternate planning roots such as
docs/planning/, top-levelplanning/,.bmad/, or.bmad-core/.
Multi-repo governance onboarding flow
This repository hosts the Kravalg-gated multi-repo IAM/OIDC governance stack in
pulumi/governance/. It provisions per-repo state buckets, KMS keys, and
GitHubCiPreview/Apply/Drift + GitHubCiConfigRead roles for every
*-infrastructure service repo listed in pulumi/repositories.governance.json.
Two separate AWS accounts give test/prod isolation: the test stack deploys
account 891377212104 and the prod stack deploys account 933245420672, both
in eu-central-1. @Kravalg is the sole approver (CODEOWNERS + the protected
governance GitHub Environment); @dmytrocraft opens PRs and may always run
plan. Applies are IaC-only and saved-plan based — there is no human pulumi up
in CI; the governance runner only replays a make pulumi-up-plan saved plan.
Each step below is tagged CODE (reviewed committable IaC/docs) or
OPERATOR (an authorized live AWS/GitHub operation). The runbook is
docs/governance-stack.md. Never add bootstrap-infrastructure to
pulumi/repositories.governance.json: it self-manages through
github-ci-bootstrap, and a catalog entry would double-manage its identities.
The real platform entrypoint uses manage_control_resources=False. Only
github-ci-bootstrap owns platform CI secrets, the OIDC provider, CI deployment
and configuration roles, legacy PulumiAutomation/PulumiDeploy roles, Config
recorder IAM, and fixed platform state/log replication IAM. The platform reads
those identities with get() and retains workload resources. Immutable control
boundaries cap legacy role grants; platform apply cannot mutate these identities
or their boundaries. Existing deployments require the reviewed ownership
migration and encrypted state backups before the first operator apply; a code
mode switch alone does not resolve existing duplicate state owners.
First resolve the actual GitHub repository identity [OPERATOR]. Inspect an existing repository, or create the empty repository when absent, and record its immutable repository/owner identifiers and current OIDC subject contract. This precedes the catalog grant and boundary provisioning because trust must bind the real identity. Preserve existing content; do not guess IDs from a repository name.
Before a new repository's first governance apply, the operator must preview and
apply the reviewed github-ci-bootstrap change that provisions its immutable
service/replication boundaries and extends the dedicated governor's exact
resource inventory. Those boundaries and runner policies are bootstrap-owned;
the governor cannot widen them or modify its own roles. This is an explicit
privileged prerequisite, including when a later repository is added by catalog
configuration. Do not claim zero operator work for new delegation inventory.
- PR A — Grant deploy roles (governance) [CODE]: add
X-infrastructuretopulumi/repositories.governance.json;projectis the full repo slug. After the reviewed bootstrap boundary/inventory prerequisite [OPERATOR], A current write-permission maintainer other than@Kravalgrequests/pulumi test up, then/pulumi prod up;@Kravalgreviews and approves the protected environment. Both apply jobs useenvironment: governanceand replay saved plans. The stack provisions X's state bucket, replica, KMS key/alias, bounded preview/apply/drift roles, config-read roles and fixed CI secrets. Merge only after current-headGovernance Promotionproof and all required reviews/checks pass. - PR B — Bootstrap generic infra for
X-infrastructure[CODE, gated apply]: prepare the complete repository scaffold and reviewed baseline. Include its comment intake, local CI action, Make/helper tooling, dependency files and deployment workflow. The initial service boundary permits backend/configuration access only; existing workload resources need explicit reviewed capability and boundary extensions before they can be deployed. Do not apply a downstream scaffold before its repo, variables and protected environments exist. - Publish scaffold to the identified repo [OPERATOR]: use the repository
resolved before PR A and preserve any existing content. Push the reviewed,
complete scaffold modelled on
pulumi/user-service-infrastructure/. Configure the account-local variables from governance outputs and the required protected environments. Prove all local-action, helper and dependency references resolve in a clean checkout. - PR C — Grant OIDC apply permissions [CODE, @Kravalg-gated]: review the final service role capabilities and protected-environment OIDC subjects against the actual service resource inventory. Apply the reviewed grants through the same gated test-then-prod flow [OPERATOR], then prove the downstream comment intake, exact-SHA plan, saved-plan apply and drift path.
After PR C, X may self-deploy through its own
.github/workflows/self-deploy.yml only when the complete setup has passed the
same-head test/prod smoke. Maintainers use /pulumi test up and
/pulumi prod up; no static/admin credentials or platform IAM privileges are
inherited. Service roles, state buckets and keys live in the governance stack;
immutable boundaries and dedicated governance runners live in the operator
bootstrap stack.
The required Governance Promotion check enforces success before merge for
governance-touching PRs. It is bound to the dedicated environment-protected GitHub App issuer and exact PR
head, and requires successful test apply, test drift, prod apply and prod drift with an
immutable proof artifact. Non-governance PRs receive a scope-based success.
A test-only apply, plan, stale head or failed/skipped production cannot satisfy
this promotion gate. CODEOWNERS review and protected environment approvals
remain additional controls. Any informational Governance Apply status is not
a substitute for the required promotion proof.
The governance runner consumes only dedicated
AWS_GOVERNANCE_{TEST,PROD}_{PREVIEW,DRIFT,APPLY}_ROLE_ARN variables and the
matching account, region, backend and KMS metadata. Preview/drift run under
governance-preview, apply under governance. Preview/drift can read the
isolated governance backend but can write only Pulumi lock objects. Follow the
operator runbook for provisioning, provider pinning, variables, real applies,
metadata-only evidence and audited break-glass.
Secret handling
These rules are mandatory for AI coding agents in this repository.
- Never read, print, summarize, diff, or copy raw secret material.
- Treat the following as off-limits unless the user explicitly asks for a secret-management task:
.env,.env.*, and shell files that export credentials- AWS shared credentials/config files, access keys, session tokens, and STS credentials
- Pulumi stack files or exports containing
secure:values orencryptedkeymetadata - GitHub Actions secrets, deploy keys, private keys, certificates, kubeconfigs, and token files
- Never run commands that reveal secrets in terminal output. This includes
env,printenv,docker compose config,docker inspect,pulumi config --show-secrets,pulumi stack output --show-secrets, and cloud-secret fetch commands unless the user explicitly requests that exact action. - Prefer metadata-only checks such as
aws sts get-caller-identity,pulumi stack ls, andpulumi configwithout secret-revealing flags. - When a secret must be set, write it directly with
pulumi config set --secret ...or the relevant cloud secret store command without echoing the value back into the terminal transcript. - Never commit secret values, decrypted outputs, copied stack exports, or temporary files containing secrets.
Pulumi workflow
- Structural, quality, unit, integration, mutation, and CLI checks should stay local-backend-friendly.
- Preview before apply when working against a real stack.
- Prefer ephemeral validation stacks such as
pr-<number>orsmokefor manual checks. - Destroy ephemeral validation stacks after the check completes.
Review-driven changes
- Use
gh pr view <PR>andgh pr checks <PR>for context. - Pull review threads with
gh api graphqland resolve every actionable thread. - Keep refactors minimal and directly tied to review feedback.
- Update
docs/whenever the developer workflow, CI surface, or credential contract changes. - Re-run the relevant checks before pushing.
- Keep the Pulumi policy pack under
policy/aligned with the runtime guardrails inpulumi/app/.
Finish PR
- Confirm the current branch still matches the target PR head before making changes.
- Review unresolved, non-outdated human and CodeRabbit comments before widening the patch.
- Keep fixes scoped to the active review feedback and the failing checks.
- Re-run the narrowest local validation that proves the comment or failure is addressed.
- Reply on every human and CodeRabbit review thread after fixing it, including brief verification context when useful.
- When a CodeRabbit comment is fixed, explicitly ask CodeRabbit on that same thread to re-check the comment because the fix is now present.
- Wait until CodeRabbit has answered every per-comment reply before asking for a new PR-wide bot review.
- After all fixed comments have been re-checked, ask
@coderabbitai reviewor@coderabbitai full reviewon the PR only once the new head is ready for another full pass. - Do not call the PR finished until all required GitHub CI checks are green, current review threads are resolved, and CodeRabbit has approved the PR.
- If CodeRabbit still withholds approval, inspect the latest current-head CodeRabbit review summary with
gh pr view <PR> --json reviews, address any current-head findings even when no inline thread remains open, then repeat the per-comment recheck flow before requesting another PR-wide review.