The capstone submission brings together all three artefacts produced in Lessons 37, 38, and 39 into a single reviewable repository that demonstrates an end-to-end secure, observable GitOps delivery platform on EKS. This is not an exercise with guided steps—it is a project submission evaluated against the five success criteria defined in the project brief. The submitted platform must work holistically: the components must be connected, not just individually functional.
The project evaluates whether you have internalised the course's core discipline: that security, delivery reliability, and observability are not independent concerns to be addressed separately but integrated properties of a single coherent platform. A submission where every component works but the connections between them are broken—the CI pipeline signs an image that Kyverno still rejects, or the AnalysisTemplate queries a metric that does not exist—does not meet the capstone standard.
Submission Checklist
Before submitting, verify every item on the submission checklist. The checklist is not a formality—each item tests a specific integration point between platform components. A Kyverno policy in Audit mode rather than Enforce mode fails the admission control criterion even if the policy YAML is correct. A Cosign verify command that succeeds with unconstrained `--certificate-identity-regexp` does not verify that the signature was produced by your specific pipeline. Work through the checklist item by item against the live cluster.
# Capstone submission checklist — verify each item before submitting.
# ══ ARTEFACT 1: GitHub Actions Pipeline ══════════════════════════════════
#
# File: .github/workflows/capstone-ci.yml
# Required elements:
# [ ] sast job: Semgrep with custom .semgrep/ rules, SARIF upload
# [ ] sca job: Snyk with --fail-on=upgradeable, SARIF upload
# [ ] build-scan-sign job: needs [sast, sca]
# [ ] AWS OIDC authentication (no static keys stored as secrets)
# [ ] Docker build with push: false and load: true before scanning
# [ ] Trivy scan with exit-code: 1 on HIGH/CRITICAL, SARIF upload
# [ ] ECR push after scan passes
# [ ] Cosign sign by digest with --yes flag
# [ ] Cosign verify immediately after signing
# [ ] update-gitops job: needs [build-scan-sign], only on main branch
# [ ] Commits image digest to GitOps repo overlays/production/
# ══ ARTEFACT 2: ArgoCD GitOps Repository ════════════════════════════════
#
# Repository: MY_ORG/india-squad-gitops
# Required files:
# [ ] policies/require-image-signature.yaml: Kyverno ClusterPolicy
# [ ] validationFailureAction: Enforce
# [ ] attestors: keyless with correct GitHub Actions workflow subject
# [ ] mutateDigest: true
# [ ] rollout/india-squad-rollout.yaml: Argo Rollouts Rollout resource
# [ ] canary strategy with canaryService/stableService
# [ ] two analysis steps referencing india-squad-error-rate
# [ ] trafficRouting with ALB ingress
# [ ] rollout/analysis-template.yaml: AnalysisTemplate
# [ ] Prometheus provider querying error rate by pod_template_hash
# [ ] successCondition <= 0.01, failureCondition > 0.05
# [ ] monitoring/prometheus-rule.yaml: PrometheusRule
# [ ] recording rule: job:http_error_ratio:rate5m
# [ ] IndiaSquadHighErrorRate, IndiaSquadHighP99Latency alerts
# [ ] IndiaSquadSLOBudgetBurning (critical)
# [ ] IndiaSquadCanaryRolloutDegraded (critical, for: 0m)
# ══ ARTEFACT 3: Live Grafana Dashboard Evidence ══════════════════════════
#
# Screenshot: grafana-golden-signals-dashboard.png
# Required evidence in the screenshot:
# [ ] Dashboard title: 'India Squad API — Golden Signals'
# [ ] Request Rate panel: non-zero values
# [ ] Error Rate panel: a value (even if 0%)
# [ ] P99 Latency panel: a latency value in seconds
# [ ] At least one deployment annotation visible (vertical marker)
# [ ] Time range: at least 30 minutes of data
# [ ] Dashboard URL confirms it is from a live cluster (not a local mock)Five Success Criteria Verification
The five success criteria from the project brief each require specific evidence. Criterion 1—signed image produced within 10 minutes—is evidenced by the pipeline run timestamp and the `cosign verify` output with the correct identity regexp. Criterion 2—Kyverno admits signed and rejects unsigned—is evidenced by kubectl output showing a successfully deployed signed pod and an admission error for an unsigned pod attempt in squad-prod.
Criterion 3—canary rollout references real Prometheus metrics—is evidenced by a running or completed AnalysisRun in the squad-prod namespace whose Prometheus query returns numeric values. Criterion 4—PrometheusRule alerts evaluated—is evidenced by all four alert rules appearing in the Prometheus Alerts page with correct expression syntax. Criterion 5—Grafana shows 30 minutes of live data—is evidenced by the dashboard screenshot with the time range visible and the request rate panel showing non-zero values.
# Verification commands for all five success criteria.
# ── Criterion 1: Signed image from CI pipeline ────────────────────────
DIGEST=$(aws ecr describe-images \
--repository-name india-squad-api --region ap-south-1 \
--query 'sort_by(imageDetails, &imagePushedAt)[-1].imageDigest' \
--output text)
cosign verify \
--certificate-identity-regexp='https://github.com/MY_ORG/india-squad-helm/.github/workflows/capstone-ci.yml' \
--certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
123456789.dkr.ecr.ap-south-1.amazonaws.com/india-squad-api@${DIGEST}
# Save output to: evidence/signed-image-verification.txt
# ── Criterion 2: Kyverno admits signed, rejects unsigned ──────────────
# Attempt to run an unsigned nginx pod in squad-prod:
kubectl run unsigned-capstone-test --image=nginx:latest -n squad-prod --restart=Never 2>&1
# Save the error output to: evidence/kyverno-enforce-rejection.txt
# Expected: 'was blocked due to the following policies: require-india-squad-signature'
# Confirm the signed india-squad-api pod is running:
kubectl get pods -n squad-prod -l app=india-squad-api
# Expected: Running pods with the signed image
# ── Criterion 3: AnalysisRun with real Prometheus metrics ─────────────
kubectl get analysisrun -n squad-prod
kubectl describe analysisrun -n squad-prod | grep -A5 'Measurements'
# Expected: measurements with numeric values (not 'no data')
# ── Criterion 4: All alert rules in Prometheus ─────────────────────────
# Open http://localhost:9090/alerts
# Verify: all four alerts present
# Take screenshot for evidence
# ── Criterion 5: Grafana dashboard with 30+ minutes of data ──────────
# Open http://localhost:3000/dashboards → India Squad API — Golden Signals
# Set time range to 'Last 1 hour'
# Take screenshot for evidence/grafana-golden-signals-dashboard.pngSubmission Structure
Organise the submission as a GitHub repository named `india-squad-capstone` with the three artefact directories and an evidence directory containing all screenshots and command output files. The README.md is the most important document in the submission—it is the reviewer's entry point and must make the platform's architecture, the connections between components, and the verification evidence immediately clear. A well-written README demonstrates understanding; a minimal README suggests the platform was assembled without full comprehension of how the components integrate.
# Submission structure — final repository layout for review.
india-squad-capstone/
├── README.md # Platform overview and component map
├── ci/
│ └── capstone-ci.yml # GitHub Actions workflow (Artefact 1)
├── gitops/
│ ├── policies/
│ │ └── require-image-signature.yaml # Kyverno ClusterPolicy
│ ├── rollout/
│ │ ├── india-squad-rollout.yaml # Argo Rollouts Rollout
│ │ └── analysis-template.yaml # AnalysisTemplate
│ └── monitoring/
│ └── prometheus-rule.yaml # PrometheusRule (Artefact 2)
└── evidence/
├── grafana-golden-signals-dashboard.png # Artefact 3: screenshot
├── pipeline-run-success.png # Screenshot: all 4 CI jobs green
├── signed-image-verification.txt # cosign verify output
├── kyverno-enforce-rejection.txt # kubectl output showing unsigned pod rejected
└── rollout-degraded-alert.png # Screenshot: Slack critical alert
# README.md must include:
# 1. A one-paragraph description of the platform architecture
# 2. The AWS account ID and ECR repository ARN (for signature verification)
# 3. The Grafana dashboard URL (accessible to the reviewer)
# 4. The commands used to verify each of the five success criteria
# 5. Any deviations from the reference implementation and their justificationREADME Requirements
The README must describe the platform architecture in enough detail that a reviewer who has not taken this course can understand what each component does and how they connect. The architecture section should mirror the diagram from Lesson 36's project brief, adapted to the specific implementation choices you made. The verification section must include the exact commands used to verify each success criterion, with example expected outputs that the reviewer can reproduce.
If you made any deviations from the reference implementation—using Flux CD instead of ArgoCD, Grafana Tempo instead of Jaeger, or implementing SLSA Level 3 provenance in addition to Cosign signing—document these in a 'Design Decisions' section with the rationale. Deviations that improve the platform are valued; deviations that omit required security properties are not. A platform that uses Flux CD but omits Kyverno image signature verification fails the supply chain security criterion regardless of which GitOps tool is used.
Evaluation Criteria
The capstone is evaluated across three dimensions. The first is integration completeness: all five success criteria are met, and the evidence demonstrates the connections between components are live rather than staged. The second is security posture: no security gate is bypassed or weakened—the Kyverno policy is in Enforce mode, OIDC federation is used rather than static credentials, and the Cosign verification uses constrained identity requirements. The third is observability depth: the Grafana dashboard shows all three golden signals, the PrometheusRule alerts include both threshold alerts and the burn rate alert, and the canary degradation alert connects the delivery layer to the alerting layer.
Extra credit is awarded for: adding SBOM generation to the CI pipeline, implementing SLSA Level 3 provenance alongside Cosign signing, adding deployment annotations to Grafana from the CI pipeline, or deploying a second application service and demonstrating that the Kyverno policy and monitoring stack extend to cover it without any central configuration changes.
Warning: Do not take screenshots of dashboards with no data and submit them as evidence. An empty Grafana panel—showing 'No Data' for the request rate—does not demonstrate that the observability stack is working; it demonstrates that either the application is not instrumented, the ServiceMonitor is not scraping, or the dashboard query is wrong. Generate real traffic to the application—using the load generation commands from M5 Lab 35—and confirm that all three panels show meaningful values before taking the submission screenshot.
Final Tip: The most common capstone failure mode is forgetting to connect the CI pipeline to the GitOps repository. A pipeline that builds, scans, and signs an image but does not commit the image digest to the GitOps repository means ArgoCD never deploys the new version, the Rollout never fires, and the AnalysisTemplate never queries Prometheus. Verify the GitOps update step works by checking the GitOps repository for a new commit from the CI bot after running the pipeline. This is the integration point that makes the whole platform work end-to-end.