Skip to content

Latest commit

 

History

History
216 lines (178 loc) · 53.3 KB

File metadata and controls

216 lines (178 loc) · 53.3 KB

Milestone 4 — HulumiOperationsHardeningPack (O_* rules + tier-monotonicity meta-test)

Parent runbook: docs/slo/completed/RUNBOOK-hulumi-operations.md. Read Carmack-Style Best Practices, the Global Execution Rules (especially Rule 0 + Rules 11–14) + the Global Entry Rules + docs/slo/lessons/hulumi-operations-m{1,2,3}.md before starting.

Goal: After M4, @hulumi/policies.HulumiOperationsHardeningPack ships as a CrossGuard policy pack mirroring the existing HulumiHardeningPack (H_*) and HulumiGithubHardeningPack (G_*) shape. Five rules under prefix O_, tier-aware (Sandbox: advisory; StartupHardened: mandatory) where appropriate. Plus the existing Suppression API extends to accept the new IDs. Plus a tier-monotonicity meta-test (H4-shape) that asserts Sandbox emits ≤ controls than StartupHardened across the new pack. Plus license-boundary mappings in docs/mappings/ for CIS / NIST / PCI-DSS — IDs only.

Context: The design record docs/slo/design/hulumi-for-operations.md § Decision: HulumiOperationsHardeningPack shape commits the five rule IDs and their tier-aware levels. The threat model rows tm-hulumi-ops-abuse-raw-ec2-rejected, tm-hulumi-ops-abuse-scanonpush-false-rejected, tm-hulumi-ops-abuse-tier-monotonicity-violation, tm-hulumi-ops-abuse-license-boundary, tm-hulumi-ops-abuse-suppression-without-reason are the abuse-case surface. The five rules:

  • O_PATCH_1: every aws.ec2.Instance must have a Patch:Group ∈ {dev, staging, production} tag (Sandbox: advisory; StartupHardened: mandatory). Updated 2026-05-01 per Flaw 2 — tightened from free-form value to enum check.
  • O_PATCH_2: every aws.ssm.PatchBaseline must associate to a MaintenanceWindow (both: mandatory).
  • O_DETECT_1: account-level stack with EC2 / ECR resources but no DetectiveServicesEnable (Sandbox: advisory; StartupHardened: mandatory).
  • O_AUDIT_1: account-level stack without an AuditTrail (Sandbox: advisory; StartupHardened: mandatory).
  • O_INSPECTOR_1: every aws.ecr.Repository with imageScanningConfiguration.scanOnPush != true (both: mandatory).

Carmack-style reliability goal: Strengthen Rule 5 — invalid-states-unrepresentable at the policy-pack layer (rules express what cannot exist in the consumer's stack), and Rule 4 — bounded resources via the Operations-pack-cap (max 10 distinct rule IDs in the pack, refuse to register an 11th — see top-level runbook Rule 12).

Important design rule: O_* rule IDs follow the existing prefix convention (H_*, G_*, now O_*). The Suppression API accepts rule IDs from any pack indifferently — no per-pack suppression scoping, mirroring the existing behavior. Every O_* rule's metadata controls field cites framework IDs (CIS / NIST / PCI-DSS) but NEVER verbatim text — license-boundary-lint extension covers the new pack.

Refactor budget: Surgical addition only. New files under packages/policies/src/aws/operations-pack/ and matching tests + mappings docs. One existing file modified: packages/policies/src/index.ts (re-exports). The Suppression API itself is unchanged — accepting new IDs is data, not code change. The license-boundary lint is extended additively to glob-cover the new mappings doc.

Contract Block

Field Value
Inputs The HulumiOperationsHardeningPack PolicyPack ctor accepts args: { tier: Tier; suppressions?: Suppression[] } — same shape as existing HulumiHardeningPack. The five rule functions are not exported individually; they're attached to the pack.
Outputs The pack instance, ready to pass to Pulumi CrossGuard. Same output shape as existing packs.
Interfaces touched New stable surface: @hulumi/policies#{HulumiOperationsHardeningPack}. New rule IDs accepted by the existing Suppression API: O_PATCH_1, O_PATCH_2, O_DETECT_1, O_AUDIT_1, O_INSPECTOR_1. License-boundary mapping doc: docs/mappings/operations.md (NEW).
Data classification Public. Policy rules + their CIS / NIST / PCI-DSS mappings are public framework references. The pack does not handle consumer data.
Proactive controls in play (a) C1 Define Security RequirementsO_* rules ARE the requirements at the IaC-policy layer. (b) @hulumi/policies.HulumiHardeningPack (existing) — pattern precedent. (c) Suppression API (existing) — accepts new IDs without code change; reason field already mandatory. (d) license-boundary-lint — extended additively. (e) tier-monotonicity meta-test (H4-shape) — extended.
Abuse acceptance scenarios Five BDD rows below cite tm-hulumi-ops-abuse-N: tm-hulumi-ops-abuse-raw-ec2-rejected (O_PATCH_1 rejects aws.ec2.Instance without Patch:Group=* tag at StartupHardened), tm-hulumi-ops-abuse-scanonpush-false-rejected (O_INSPECTOR_1 rejects ECR repo with scanOnPush: false), tm-hulumi-ops-abuse-tier-monotonicity-violation (meta-test asserts count(Sandbox-mandatory rules) ≤ count(StartupHardened-mandatory rules)), tm-hulumi-ops-abuse-license-boundary (license-boundary-lint extends to cover operations.md mapping doc; verbatim CIS / NIST / PCI-DSS text in the pack source rejected at lint), tm-hulumi-ops-abuse-suppression-without-reason (existing compliance-justified-suppressions meta-test extends to cover O_* IDs; suppression without reason field rejected).
Files allowed to change NEW: packages/policies/src/aws/operations-pack/{index.ts,o-patch-1.ts,o-patch-2.ts,o-detect-1.ts,o-audit-1.ts,o-inspector-1.ts,operations-pack.ts}, packages/policies/tests/aws/operations-pack/{o-patch-1.test.ts,o-patch-2.test.ts,o-detect-1.test.ts,o-audit-1.test.ts,o-inspector-1.test.ts,tier-monotonicity.test.ts,suppression-discipline.test.ts}, docs/mappings/operations.md, docs/components/hulumi-operations-hardening-pack.md (one-line stub), docs/slo/lessons/hulumi-operations-m4.md, docs/slo/completion/hulumi-operations-m4.md. MODIFIED: packages/policies/src/index.ts (re-export HulumiOperationsHardeningPack), scripts/license-boundary-lint.mjs (additive glob — covers docs/mappings/operations.md + the new pack source dir; the lint logic itself is unchanged), docs/slo/completed/RUNBOOK-hulumi-operations.md Milestone Tracker, docs/slo/runbook-milestones/hulumi-operations-m4.md (this file — Evidence Log only), docs/ARCHITECTURE.md (one paragraph), docs/mappings/README.md (index entry for the new mappings doc). REFUSE TO TOUCH: any packages/baseline/, packages/drift/, packages/k8s-baseline/.
Files to read before changing anything docs/slo/completed/RUNBOOK-hulumi-operations.md; docs/slo/design/hulumi-for-operations.md § Decision: HulumiOperationsHardeningPack; docs/slo/design/hulumi-for-operations-threat-model.md HulumiOperationsHardeningPack STRIDE rows + Compliance mapping table; docs/slo/lessons/hulumi-operations-m{1,2,3}.md; packages/policies/src/aws/hardening-pack/ (the existing H_* pack — pattern precedent); packages/policies/src/aws/cis-v5-pack/ (the existing CIS pack — mapping precedent); packages/policies/tests/aws/hardening-pack/tier-monotonicity.test.ts (the existing meta-test we mirror); scripts/license-boundary-lint.mjs; docs/mappings/README.md; docs/mappings/aws.md (existing mapping doc — shape precedent).
New files allowed All NEW entries above.
New dependencies allowed none. Pulumi CrossGuard is already a peer dep of @hulumi/policies.
Migration allowed no — additive only. Suppression API accepts new IDs as data, not as code change.
Compatibility commitments The five O_* rule IDs are stable from M4 — renaming O_PATCH_1 to O_PATCH_BASELINE_REQUIRED_TAG would be a major-version bump. The Suppression API shape unchanged. The pack ships in @hulumi/policies@1.2.0 (M5 release).
Resource bounds introduced/changed (v4 Rule 4) (a) HulumiOperationsHardeningPack rule count: 5 in M4, hard cap of 10 (per top-level Rule 12); refusing to register an 11th rule is encoded as a runtime check + a meta-test. (b) Per-rule severity-level cardinality: each rule emits exactly one severity per evaluation (no fan-out within a single rule).
Invariants/assertions required (v4 Rule 3) (i) Each rule's name field starts with O_ and ends with a digit. (ii) Each rule has a description, a severity (advisory or mandatory per tier), and a controls array of framework IDs (no verbatim text). (iii) Tier monotonicity: for each rule, severity_at_StartupHardened ≥ severity_at_Sandbox (where mandatory > advisory). Asserted in tier-monotonicity.test.ts. (iv) Every Suppression for an O_* ID has a non-empty reason field. Asserted in suppression-discipline.test.ts. (v) The pack instance count of distinct rule IDs is ≤ 10 (the bound); attempting to register an 11th throws.
Debugger / inspection expectation (v4 Rule 1) Pulumi CrossGuard policy violations are observable via pulumi preview output. If a rule fires unexpectedly, the agent runs pulumi preview --policy-pack <path> against a synthetic stack to inspect the violation message before speculating about rule logic. Pulumi mock-runtime supports introspecting args.props inside the rule function — same debugger pattern as M1/M2/M3.
Static analysis gates (v4 Rule 2) Same as M1/M2/M3 — formatter, typecheck, lint, license-boundary, exact-pin guard. License-boundary lint is the gate that protects this milestone the most because it catches verbatim CIS/NIST/PCI-DSS text in any new file.
Forbidden shortcuts (a) NEVER ship verbatim CIS / NIST / PCI-DSS control text in any rule's description or controls metadata — IDs only, framework URLs at the file level. (b) NEVER rename an existing rule ID. (c) NEVER make O_PATCH_2 / O_INSPECTOR_1 advisory at any tier — both are mandatory per design record. (d) NEVER add a sixth rule in M4 — five rules ship; if a sixth is needed, defer to v1.3 with a fresh contract block. (e) NEVER allow a Suppression for an O_* ID without a reason — meta-test catches this. (f) NEVER widen the license-boundary glob beyond what's needed (additive only — covers operations.md and the new pack source dir, not anything else). (g) NEVER rely on O_DETECT_1 / O_AUDIT_1 being able to detect the absence of a component without explicit hint — these rules look for a stack-level marker tag (hulumi:detective-services-enable: present or hulumi:audit-trail: present) emitted by the M2/M3 components; the rule fails closed if the marker is missing AND the stack has the gating resource type.

Out of Scope / Must Not Do

  • No skill scenarios — those are M5.
  • No additional rules beyond the five committed.
  • No CIS v8 mappings — v5 is the canonical set; v8 deferred.
  • No Suppression API changes — accepts new IDs as data.
  • No HulumiHardeningPack (H_*) or HulumiGithubHardeningPack (G_*) modifications.
  • No skill-side wiring of the pack — skills don't declare CrossGuard dependencies.

Pre-Flight

  1. Complete Global Entry Rules.
  2. Read lessons-m1, lessons-m2, lessons-m3 — apply corrections.
  3. Read the design record's HulumiOperationsHardeningPack decision + the threat-model compliance-mapping table.
  4. Read the existing HulumiHardeningPack source end-to-end as the pattern precedent.
  5. Re-state load-bearing constraints: (i) IDs only (no verbatim framework text); (ii) tier monotonicity; (iii) O_DETECT_1 / O_AUDIT_1 rely on M2/M3 marker tags emitted by the components; (iv) hard cap of 10 rules in pack.
  6. Verify the existing tier-monotonicity.test.ts and compliance-justified-suppressions.test.ts tests pass at baseline.

Files Allowed To Change

File Planned Change
packages/policies/src/aws/operations-pack/index.ts NEW: re-export HulumiOperationsHardeningPack
packages/policies/src/aws/operations-pack/operations-pack.ts NEW: HulumiOperationsHardeningPack ctor
packages/policies/src/aws/operations-pack/{o-patch-1,o-patch-2,o-detect-1,o-audit-1,o-inspector-1}.ts NEW: per-rule logic
packages/policies/src/index.ts MODIFY: re-export HulumiOperationsHardeningPack
packages/policies/tests/aws/operations-pack/{o-*.test.ts,tier-monotonicity.test.ts,suppression-discipline.test.ts} NEW: tests
docs/mappings/operations.md NEW: CIS / NIST / PCI-DSS / SOC 2 / ISO 27001 mappings — IDs only (per design record's compliance table)
docs/mappings/README.md MODIFY: add index entry pointing at operations.md
scripts/license-boundary-lint.mjs MODIFY: additive glob extension (covers docs/mappings/operations.md and packages/policies/src/aws/operations-pack/); lint logic unchanged
docs/components/hulumi-operations-hardening-pack.md NEW (one-line stub)
docs/slo/completed/RUNBOOK-hulumi-operations.md Milestone Tracker MODIFY
docs/slo/runbook-milestones/hulumi-operations-m4.md MODIFY: Evidence Log fill-in
docs/slo/lessons/hulumi-operations-m4.md NEW per v4 lessons template
docs/slo/completion/hulumi-operations-m4.md NEW per v4 completion template
docs/ARCHITECTURE.md MODIFY: one paragraph

Step-by-Step

  1. Pre-flight + re-state constraints.
  2. Write per-rule BDD tests (o-*.test.ts) covering happy-path-stack, violation-stack, suppression-with-reason, suppression-without-reason. Run — expect failures.
  3. Implement o-patch-1.ts: walks every aws.ec2.Instance resource in the stack, checks tags["Patch:Group"] is set AND its value is one of {"dev", "staging", "production"} (tightened 2026-05-01 per Flaw 2); tier-aware severity. Each rule file ~30 lines.
  4. Implement o-patch-2.ts: walks every aws.ssm.PatchBaseline, checks for an associated MaintenanceWindowTarget referencing it; mandatory both tiers.
  5. Implement o-detect-1.ts: walks the stack for aws.ec2.Instance, aws.ecr.Repository, aws.lambda.Function resources; if any present AND no resource emits the marker tag hulumi:component=DetectiveServicesEnable, fail tier-aware.
  6. Implement o-audit-1.ts: walks the stack for any aws.cloudtrail.Trail-eligible state; if no hulumi:component=AuditTrail marker present, fail tier-aware.
  7. Implement o-inspector-1.ts: walks every aws.ecr.Repository, checks imageScanningConfiguration.scanOnPush === true; mandatory both tiers.
  8. Implement operations-pack.ts: registers all five rules under the HulumiOperationsHardeningPack PolicyPack class; tier-aware via the existing Tier-resolved-severity helper from HulumiHardeningPack.
  9. Re-export from packages/policies/src/index.ts.
  10. Write tier-monotonicity.test.ts (asserts every rule's StartupHardened severity ≥ Sandbox severity) and suppression-discipline.test.ts (asserts every O_* suppression in fixture stacks has a non-empty reason).
  11. Write docs/mappings/operations.md (IDs only — copy table from threat-model compliance-mapping section verbatim, add framework URLs).
  12. Extend scripts/license-boundary-lint.mjs glob list. Run — verify it catches a synthetic verbatim-text fixture before final commit.
  13. Run full repo suite. Self-Review Gate. Update Tracker, write lessons + completion files.

BDD Acceptance Scenarios

Feature: @hulumi/policies.HulumiOperationsHardeningPack — five O_* rules with tier-aware severity, license-boundary-clean, suppression-disciplined

Scenario Category Given When Then Threat-model row Control
Happy path — all rules satisfied at StartupHardened happy path synthetic stack: 1 EC2 with Patch:Group=production tag, 1 PatchBaseline + MW, DetectiveServicesEnable + AuditTrail markers, ECR with scanOnPush:true pulumi preview with the pack zero violations across all five rules n/a n/a
O_PATCH_1 mandatory at StartupHardened — raw EC2 rejected abuse case synthetic stack: 1 aws.ec2.Instance with no Patch:Group=* tag pulumi preview at tier: StartupHardened O_PATCH_1 violation; severity mandatory; message contains "Patch:Group" + the resource URN tm-hulumi-ops-abuse-raw-ec2-rejected C5 + Forbidden (b)
O_PATCH_1 advisory at Sandbox — raw EC2 warning, not blocking tier ladder same synthetic stack pulumi preview at tier: Sandbox O_PATCH_1 violation; severity advisory; preview proceeds n/a tier discipline
O_PATCH_1 rejects tag value outside enum (NEW 2026-05-01 per Flaw 2) abuse case synthetic stack: 1 aws.ec2.Instance with Patch:Group=experiment (free-form value) pulumi preview at tier: StartupHardened O_PATCH_1 violation; severity mandatory; message contains "must be one of [dev, staging, production]" + the resource URN; the prior pattern (any value present) is no longer sufficient tm-hulumi-ops-abuse-tag-outside-enum invariant + Forbidden (l)
O_PATCH_2 mandatory at both tiers — orphan PatchBaseline violation synthetic stack: 1 PatchBaseline with no MaintenanceWindowTarget pulumi preview at either tier O_PATCH_2 violation; severity mandatory n/a n/a
O_DETECT_1 — ECR resource present, no DetectiveServicesEnable marker violation synthetic stack: 1 ECR repo, no marker pulumi preview at StartupHardened O_DETECT_1 violation; mandatory n/a (data-flow check; abuse covered in M2) C9
O_AUDIT_1 — account-level resources present, no AuditTrail marker violation synthetic stack: 1 EC2, 1 ECR, no hulumi:component=AuditTrail marker tag pulumi preview at StartupHardened O_AUDIT_1 violation; mandatory n/a C9
O_INSPECTOR_1 mandatory both tiers — ECR with scanOnPush: false abuse case synthetic stack: 1 ECR with imageScanningConfiguration.scanOnPush: false pulumi preview at either tier O_INSPECTOR_1 violation; mandatory; message contains "scanOnPush" tm-hulumi-ops-abuse-scanonpush-false-rejected C5 + Forbidden (c)
Suppression with reason accepted happy path (suppression) synthetic stack with O_INSPECTOR_1 violation; pack instantiated with suppressions: [{ id: "O_INSPECTOR_1", reason: "Legacy registry; replacing in Q3 2026" }] pulumi preview violation suppressed; preview proceeds; suppression recorded in suppression-audit.log (existing pattern) n/a C9 + Suppression API
Abuse case — Suppression without reason rejected abuse case suppressions: [{ id: "O_INSPECTOR_1" } as any] (cast through any to bypass TS) Suppression API construction the existing Suppression ctor's runtime check throws Error('Suppression: reason is required') tm-hulumi-ops-abuse-suppression-without-reason Forbidden (e)
Abuse case — verbatim CIS / NIST text in rule source rejected by lint abuse case synthetic source file with verbatim CIS control description embedded in a rule's description pnpm run lint:license-boundary lint exits non-zero; specific file:line of the verbatim text reported tm-hulumi-ops-abuse-license-boundary Forbidden (a) + (f)
Abuse case — tier monotonicity violation rejected by meta-test abuse case synthetic rule definition with Sandbox: mandatory AND StartupHardened: advisory pnpm --filter @hulumi/policies test -- tier-monotonicity meta-test fails; specific rule ID called out tm-hulumi-ops-abuse-tier-monotonicity-violation Rule 11 + invariant (iii)
Resource bound — pack with 11 distinct rule IDs rejected resource bound synthetic pack with 11 O_* rules registered HulumiOperationsHardeningPack constructor throws Error('HulumiOperationsHardeningPack: rule count exceeds hard cap of 10') n/a Rule 4 + invariant (v)
Compatibility — existing H_* and G_* packs unchanged compatibility HulumiHardeningPack + HulumiGithubHardeningPack packs in the consumer stack pulumi preview with all three packs all three packs run independently; no rule-ID collision; no false-positive cross-pack effect n/a additive

Regression Tests

  • All M1 + M2 + M3 BDD continue to pass.
  • All existing AWS / GitHub / K8s BDD continue to pass.
  • Existing HulumiHardeningPack / CisV5Pack / HulumiGithubHardeningPack rule tests unchanged — re-run, all green.
  • Existing tier-monotonicity.test.ts for H_* rules unchanged.
  • Existing compliance-justified-suppressions.test.ts for H_* and G_* IDs unchanged; the new test file is for O_* IDs.
  • License-boundary lint: re-run on existing source — no false positives.

Compatibility Checklist

  • HulumiOperationsHardeningPack re-exported from @hulumi/policies.
  • No new dependencies.
  • Static-analysis gates green.
  • License-boundary lint catches verbatim text in synthetic fixture (fixture committed under tests, NOT in production source).
  • License header on every new .ts file.
  • DCO sign-off carried over.
  • All M1 + M2 + M3 + existing AWS / GitHub / K8s BDD scenarios produce valid output unchanged.
  • Existing Suppression API call sites unchanged.
  • Existing H_* / G_* rule pack tests unchanged.

E2E Runtime Validation

Policy packs do not have a "runtime" the way components do — they execute at pulumi preview. The E2E equivalents are end-to-end policy-pack integration tests:

File: packages/policies/tests/aws/operations-pack/e2e-policy-pack.test.ts.

E2E Test What It Proves Pass Criteria
policy_pack_runs_against_synthetic_stack_with_violations The pack actually fires when expected Test constructs an in-memory policy-pack instance + synthetic Pulumi stack with each violation type; asserts each rule fires exactly once with the correct severity.
policy_pack_runs_clean_against_compliant_stack The pack doesn't false-positive Test constructs a happy-path stack (M1+M2+M3 components present, all marker tags emitted, ECR with scanOnPush, EC2 with Patch:Group); asserts zero violations.
combined_packs_no_collision H_*, G_*, O_* coexist Test loads all three packs together against a stack that has both AWS account-level + GitHub + Operations resources; asserts each pack's rules fire on their own resources only, no cross-pack interference.
license_boundary_catches_verbatim_in_synthetic_fixture The lint extension is wired Synthetic test fixture file under tests/fixtures/license-boundary-violations/operations-verbatim.ts containing a CIS verbatim sentence; run pnpm run lint:license-boundary --include-fixtures; assert non-zero exit + specific file:line flagged.

Smoke Tests

  • Full static-analysis suite green.
  • Mock-runtime BDD green.
  • In a Pulumi program with HulumiOperationsHardeningPack enabled at tier: StartupHardened: new aws.ec2.Instance("foo", { ... no Patch:Group tag ... }) causes pulumi preview to emit O_PATCH_1 violation.
  • In a Pulumi program: new aws.ecr.Repository("bar", { imageScanningConfiguration: { scanOnPush: false } }) causes pulumi preview to emit O_INSPECTOR_1 violation.
  • git status clean.
  • .gitignore covers any new generated files.

Evidence Log

Step Command / Check Expected Result Actual Result Pass/Fail Notes
Baseline tests pnpm -r build && pnpm -r test green filled during execution pending
BDD tests created (per rule) pnpm --filter @hulumi/policies test -- operations-pack fail for expected reason filled during execution pending
Tier-monotonicity meta-test pnpm --filter @hulumi/policies test -- tier-monotonicity initially fails (no rules registered yet) filled during execution pending
Implementation filesystem source files + re-exports filled during execution pending
Mappings doc cat docs/mappings/operations.md IDs only; framework URLs at file level filled during execution pending
License-boundary glob extension cat scripts/license-boundary-lint.mjs additive glob covers new files filled during execution pending
Formatter pnpm -r format:check clean filled during execution pending
Typecheck pnpm -r typecheck clean filled during execution pending
Static analyzer pnpm -r lint clean filled during execution pending
License-boundary lint pnpm run lint:license-boundary OK on new files; catches synthetic fixture filled during execution pending
Exact-pin guard pnpm run lint:exact-pin-guard OK filled during execution pending
Per-rule BDD pnpm --filter @hulumi/policies test -- operations-pack all rows pass filled during execution pending
Tier-monotonicity meta-test pnpm --filter @hulumi/policies test -- tier-monotonicity green for all five O_* rules filled during execution pending
Suppression-discipline meta-test pnpm --filter @hulumi/policies test -- suppression-discipline green; rejects reason: "" filled during execution pending
Combined packs no-collision test pnpm --filter @hulumi/policies test -- e2e-policy-pack green filled during execution pending
Build/boot pnpm -r build builds cleanly filled during execution pending
Resource-bound verification mock-runtime: 11-rule pack rejected bound = 10; over-cap rejected filled during execution pending
Invariant verification tier-monotonicity meta-test invariant (iii) holds for all five rules filled during execution pending
Debugger / state inspection pulumi preview --policy-pack against synthetic stack if a rule fires unexpectedly rule logic confirmed before code change filled during execution pending
Smoke tests (manual list) all checked filled during execution pending
Test artifact cleanup git status --short only intentional files filled during execution pending
.gitignore review review current filled during execution pending
Compatibility checks (manual list) no regressions filled during execution pending

Definition of Done

  • All BDD scenarios pass.
  • Tier-monotonicity meta-test green for all five O_* rules.
  • Suppression-discipline meta-test green.
  • License-boundary lint green; the synthetic-fixture test confirms the lint catches verbatim text.
  • Static-analysis gates green.
  • Smoke tests checked off.
  • Compatibility checklist complete.
  • Resource bounds (Rule 4: max 10 rules) and invariants (Rule 3: all five enumerated) encoded + tested.
  • No forbidden shortcuts.
  • git status clean.
  • All M1 + M2 + M3 + existing surfaces unchanged.
  • Self-Review Gate answered with yes.
  • Lessons + completion files written.
  • Mappings doc docs/mappings/operations.md written, IDs only.
  • Milestone Tracker updated to done.

Post-Flight

  • docs/slo/completed/RUNBOOK-hulumi-operations.md Milestone Tracker → M4 done.
  • docs/components/hulumi-operations-hardening-pack.md — one-line stub.
  • docs/ARCHITECTURE.md — one paragraph.
  • docs/mappings/README.md — index entry pointing at operations.md.

Notes

  • The M2/M3-marker-tag pattern (hulumi:component=DetectiveServicesEnable, hulumi:component=AuditTrail) is the load-bearing data-flow link between the M2/M3 components and the O_DETECT_1 / O_AUDIT_1 rules. If the marker tag is missed in M2/M3 implementation, the rules can't fire correctly. The lessons file should call this out as the cross-milestone dependency that the reader should verify when reading M4 lessons against M2/M3 source.
  • Five rules is the deliberate ceiling for v1.2. If consumer demand surfaces additional Operations-pack rules (e.g., GuardDuty-Master-Account-required, Cost-Anomaly-Threshold-min), they're v1.3 work — not M4 scope creep.