diff --git a/.github/linters/actionlint.yaml b/.github/linters/actionlint.yaml new file mode 100644 index 00000000..63ed9548 --- /dev/null +++ b/.github/linters/actionlint.yaml @@ -0,0 +1,6 @@ +--- +# Super-Linter loads ActionLint rules from this directory. +# Its bundled label catalog predates GitHub-hosted ubuntu-24.04. +self-hosted-runner: + labels: + - ubuntu-24.04 diff --git a/.github/scripts/p2_classroom_check.py b/.github/scripts/p2_classroom_check.py new file mode 100755 index 00000000..11079928 --- /dev/null +++ b/.github/scripts/p2_classroom_check.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Validate the minimum classroom evidence contract for all active projects.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +MANIFEST = ROOT / "config" / "active-integrity-manifest.json" +REQUIRED = ("P2_CLASSROOM.md", "P2_EVIDENCE.md", "P2_LOCAL_PILOT.md", "START_HERE.md") + + +def main() -> int: + projects = json.loads(MANIFEST.read_text(encoding="utf-8"))["projects"] + failures: list[str] = [] + for entry in projects: + root = ROOT / entry["project"] + for name in REQUIRED: + if not (root / name).is_file(): + failures.append(f"{entry['project']}/{name}") + classroom = root / "P2_CLASSROOM.md" + if ( + classroom.is_file() + and "## Learning and assessment" + not in classroom.read_text(encoding="utf-8") + ): + failures.append( + f"{entry['project']}/P2_CLASSROOM.md missing Learning and assessment" + ) + if failures: + print( + "ERROR: classroom contract failures: " + ", ".join(failures), + file=sys.stderr, + ) + return 1 + print(f"P2 classroom contract: PASS ({len(projects)} projects)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/INSTRUCTOR_SOLUTION_PACK.md b/INSTRUCTOR_SOLUTION_PACK.md new file mode 100644 index 00000000..97f0b342 --- /dev/null +++ b/INSTRUCTOR_SOLUTION_PACK.md @@ -0,0 +1,7 @@ +# Instructor Solution Pack Boundary + +> Complete worked solutions are intentionally stored in the separately distributed instructor pack, not in this student-facing repository. + +Every active project now includes `START_HERE.md`, which provides a local-safe starting action, observable +checkpoints, non-spoiling hints, and expected evidence. Instructors should retain the separate solution pack +and release assistance progressively. diff --git a/config/active-integrity-manifest.json b/config/active-integrity-manifest.json new file mode 100644 index 00000000..edf8cdd4 --- /dev/null +++ b/config/active-integrity-manifest.json @@ -0,0 +1,2802 @@ +{ + "version": 1, + "projects": [ + { + "project": "project-01-java-aws-3tier", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Java-Login-App/.gitignore", + "Java-Login-App/HELP.md", + "Java-Login-App/README.md", + "Java-Login-App/mvnw", + "Java-Login-App/mvnw.cmd", + "Java-Login-App/pom.xml", + "Java-Login-App/settings.xml", + "Java-Login-App/src/main/java/com/dpt/demo/HomeController.java", + "Java-Login-App/src/main/java/com/dpt/demo/MyWebAppApplication.java", + "Java-Login-App/src/main/java/com/dpt/demo/ServletInitializer.java", + "Java-Login-App/src/main/java/com/dpt/demo/login.java", + "Java-Login-App/src/main/java/com/dpt/demo/register.java", + "Java-Login-App/src/main/resources/application.properties", + "Java-Login-App/src/main/webapp/pages/confirm.jsp", + "Java-Login-App/src/main/webapp/pages/fail.jsp", + "Java-Login-App/src/main/webapp/pages/home.jsp", + "Java-Login-App/src/main/webapp/pages/login.jsp", + "Java-Login-App/src/main/webapp/pages/register.jsp", + "Java-Login-App/src/main/webapp/pages/user.jsp", + "Java-Login-App/src/test/java/com/dpt/demo/MyWebAppApplicationTests.java", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "terraform/3tier-nginx.md", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-02-aws-vpc-architecture", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "VPC Architecture/flow-logs-trusted.json", + "VPC Architecture/flow-logs.json", + "VPC Architecture/memory_metrics.json", + "VPC Architecture/s3-policy.json", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "html-web-app/.gitignore", + "html-web-app/README.md", + "html-web-app/WEB-INF/web.xml", + "html-web-app/css/booNavigation.css", + "html-web-app/css/jquery.bxslider.css", + "html-web-app/css/style.css", + "html-web-app/error.htm", + "html-web-app/header.html", + "html-web-app/index.html", + "html-web-app/js/beaverslider-effects.js", + "html-web-app/js/beaverslider.js", + "html-web-app/js/booNavigation.js", + "html-web-app/js/jquery.bxslider.min.js", + "html-web-app/js/jquery.min.js", + "html-web-app/ok.htm", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-03-linux-fundamentals", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-04-django-aws-ecs", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".gitattributes", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "hello_world_django_app/__init__.py", + "hello_world_django_app/asgi.py", + "hello_world_django_app/settings.py", + "hello_world_django_app/urls.py", + "hello_world_django_app/views.py", + "hello_world_django_app/wsgi.py", + "manage.py", + "project.yaml", + "requirements.txt", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-05-docker-jenkins-k8s", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-06-advanced-cicd-pipeline", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-07-azure-devops-aks-terraform", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "labs/1-Initial-Setup/1-Azure-DevOps-Setup.md", + "labs/1-Initial-Setup/2-Azure-Terraform-Remote-Storage.md", + "labs/1-Initial-Setup/3-Create-Azure-AD-AKS-Admins.md", + "labs/1-Initial-Setup/README.md", + "labs/2-AzureDevOps-Terraform-Pipeline/1-Setup-AzureDevOps-Pipeline.md", + "labs/2-AzureDevOps-Terraform-Pipeline/README.md", + "labs/2-AzureDevOps-Terraform-Pipeline/pipelines/lab2pipeline.yaml", + "labs/3-Deploy-App-to-ACR/1-Deploy-App-to-ACR.md", + "labs/3-Deploy-App-to-ACR/README.md", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/About.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/About.cshtml.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Contact.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Contact.cshtml.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Error.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Error.cshtml.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Index.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Index.cshtml.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Privacy.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Privacy.cshtml.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Shared/_CookieConsentPartial.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Shared/_Layout.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/Shared/_ValidationScriptsPartial.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/_ViewImports.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Pages/_ViewStart.cshtml", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Program.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/Startup.cs", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/appsettings.Development.json", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/appsettings.json", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/aspnet-core-dotnet-core.csproj", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/bundleconfig.json", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/charts/sampleapp/.helmignore", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/charts/sampleapp/templates/NOTES.txt", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/charts/sampleapp/templates/_helpers.tpl", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/css/site.css", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/css/site.min.css", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/js/site.js", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/js/site.min.js", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/bootstrap/LICENSE", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/jquery-validation/LICENSE.md", + "labs/3-Deploy-App-to-ACR/aspnet-core-dotnet-core/wwwroot/lib/jquery/LICENSE.txt", + "labs/3-Deploy-App-to-ACR/docker-image-locally.md", + "labs/4-Deploy-App-AKS/1-Add-AKS-ACR-Role-Assignment.md", + "labs/4-Deploy-App-AKS/2-Add-Application-Insights.md", + "labs/4-Deploy-App-AKS/3-Add-KeyVault-to-Terraform.md", + "labs/4-Deploy-App-AKS/4-Update-Pipeline-Deploy-App-AKS.md", + "labs/4-Deploy-App-AKS/README.md", + "labs/5-CICD/1-Introduce-CI-CD-to-your-Pipeline.md", + "labs/5-CICD/2-Automated-Deployment-AKS-Application.md", + "labs/5-CICD/README.md", + "labs/6-Testing-Infrastructure/1-Testing-Infrastructure-using-Inspec.md", + "labs/6-Testing-Infrastructure/2-Run-Inspec-Tests-Using-Azure-DevOps.md", + "labs/6-Testing-Infrastructure/README.md", + "labs/6-Testing-Infrastructure/azure-inspec-tests/README.md", + "labs/6-Testing-Infrastructure/azure-inspec-tests/controls/azure_aks_cluster.rb", + "labs/6-Testing-Infrastructure/azure-inspec-tests/controls/azure_application_gateway.rb", + "labs/6-Testing-Infrastructure/azure-inspec-tests/controls/azure_container_registry.rb", + "labs/6-Testing-Infrastructure/azure-inspec-tests/controls/azure_key_vault.rb", + "labs/6-Testing-Infrastructure/azure-inspec-tests/controls/azure_virtual_network.rb", + "labs/6-Testing-Infrastructure/azure-inspec-tests/inspec.yml", + "labs/7-Monitoring-and-Alerting/1-Application-Insights.md", + "labs/7-Monitoring-and-Alerting/2-Application-Insights-Configure-Availability-Test.md", + "labs/7-Monitoring-and-Alerting/3-Log-Analytics-Container-Insights.md", + "labs/7-Monitoring-and-Alerting/README.md", + "prerequisites.md", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-08-2048-game-eks", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "EVIDENCE_TEMPLATE.md", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "project.yaml", + "reset-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-09-devsecops-netflix-clone", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-10-dotnet-azure-devops", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-11-aws-2tier-terraform", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "modules/aws-iam/iam-policy.json", + "modules/aws-iam/iam-role.json", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-12-super-mario-k8s", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "EVIDENCE_TEMPLATE.md", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "project.yaml", + "reset-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-13-zomato-clone-devsecops", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".env.example", + "EVIDENCE_TEMPLATE.md", + "Makefile", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "app.py", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "optional-cloud/README.md", + "project.yaml", + "scripts/negative.sh", + "scripts/reset.sh", + "scripts/smoke.sh", + "validate-p0.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-14-github-actions-android", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "EVIDENCE_TEMPLATE.md", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "active-path-manifest.tsv", + "android-demo-app/.github/workflows/android.yml", + "android-demo-app/.gradle/7.0.2/fileChanges/last-build.bin", + "android-demo-app/.gradle/7.0.2/fileHashes/fileHashes.lock", + "android-demo-app/.gradle/7.0.2/gc.properties", + "android-demo-app/.gradle/8.9/checksums/checksums.lock", + "android-demo-app/.gradle/8.9/checksums/md5-checksums.bin", + "android-demo-app/.gradle/8.9/checksums/sha1-checksums.bin", + "android-demo-app/.gradle/8.9/dependencies-accessors/gc.properties", + "android-demo-app/.gradle/8.9/executionHistory/executionHistory.lock", + "android-demo-app/.gradle/8.9/fileChanges/last-build.bin", + "android-demo-app/.gradle/8.9/fileHashes/fileHashes.lock", + "android-demo-app/.gradle/8.9/gc.properties", + "android-demo-app/.gradle/buildOutputCleanup/buildOutputCleanup.lock", + "android-demo-app/.gradle/buildOutputCleanup/cache.properties", + "android-demo-app/.gradle/checksums/checksums.lock", + "android-demo-app/.gradle/vcs-1/gc.properties", + "android-demo-app/app/.gitignore", + "android-demo-app/app/build.gradle", + "android-demo-app/app/proguard-rules.pro", + "android-demo-app/app/src/androidTest/java/com/gradleplayground/ExampleInstrumentedTest.kt", + "android-demo-app/app/src/main/AndroidManifest.xml", + "android-demo-app/app/src/main/java/com/gradleplayground/MyApplication.kt", + "android-demo-app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml", + "android-demo-app/app/src/main/res/drawable/ic_launcher_background.xml", + "android-demo-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml", + "android-demo-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml", + "android-demo-app/app/src/main/res/values-night/themes.xml", + "android-demo-app/app/src/main/res/values/colors.xml", + "android-demo-app/app/src/main/res/values/strings.xml", + "android-demo-app/app/src/main/res/values/themes.xml", + "android-demo-app/app/src/test/java/com/gradleplayground/ExampleUnitTest.kt", + "android-demo-app/build.gradle", + "android-demo-app/first/.gitignore", + "android-demo-app/first/build.gradle", + "android-demo-app/first/consumer-rules.pro", + "android-demo-app/first/proguard-rules.pro", + "android-demo-app/first/src/androidTest/java/com/first/ExampleInstrumentedTest.kt", + "android-demo-app/first/src/main/AndroidManifest.xml", + "android-demo-app/first/src/main/java/com/first/HelperFIrst.kt", + "android-demo-app/first/src/test/java/com/first/ExampleUnitTest.kt", + "android-demo-app/gradle.properties", + "android-demo-app/gradle/wrapper/gradle-wrapper.properties", + "android-demo-app/gradlew", + "android-demo-app/gradlew.bat", + "android-demo-app/local.properties", + "android-demo-app/scripts/email-commit.gradle", + "android-demo-app/scripts/move-apk.gradle", + "android-demo-app/scripts/my-logger.gradle", + "android-demo-app/scripts/root.gradle", + "android-demo-app/scripts/version.gradle", + "android-demo-app/second/.gitignore", + "android-demo-app/second/build.gradle", + "android-demo-app/second/consumer-rules.pro", + "android-demo-app/second/proguard-rules.pro", + "android-demo-app/second/src/androidTest/java/com/second/ExampleInstrumentedTest.kt", + "android-demo-app/second/src/main/AndroidManifest.xml", + "android-demo-app/second/src/main/java/com/second/HelperSecond.kt", + "android-demo-app/second/src/test/java/com/second/ExampleUnitTest.kt", + "android-demo-app/settings.gradle", + "ci-contract.yaml", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "fixtures/signing-fixture.properties", + "negative-quarantine-probe.sh", + "project.yaml", + "reset-local.sh", + "tools/test_verify_ci_contract.py", + "tools/verify_ci_contract.py", + "validate-local.sh", + "validate-p2-local.sh", + "validate-quarantine.sh" + ], + "static_assets": [] + }, + { + "project": "project-15-ecommerce-eks-helm", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".env.example", + "EVIDENCE_TEMPLATE.md", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "local/web.conf", + "project.yaml", + "reset-local.sh", + "validate-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-16-jenkins-argocd-k8s", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "EVIDENCE_TEMPLATE.md", + "LOCAL_GITOPS_LAB.md", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "active-path-manifest.tsv", + "fixtures/clean-contract.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative-contract.txt", + "local-fixture/desired-state.json", + "local-fixture/manifests/app.json", + "local_delivery.py", + "negative-quarantine-probe.sh", + "project.yaml", + "reset-local.sh", + "test_local_delivery.py", + "validate-p2-local.sh", + "validate-quarantine.sh" + ], + "static_assets": [] + }, + { + "project": "project-17-aks-azure-devops", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-18-jenkins-java-full-cicd", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-19-eks-jenkins-terraform", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "INSTRUCTOR_BOUNDARY.md", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "QUARANTINE.md", + "README.md", + "START_HERE.md", + "ci/local-ci.sh", + "fixtures/clean/pipeline.yml", + "fixtures/evidence-local-result.txt", + "manifest/kubectl_commands.md", + "project.yaml", + "tests/test_policy.py", + "validate-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-20-azure-terraform-pipeline", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-21-aws-codepipeline", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-22-aws-serverless", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".gitignore", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "serverless-api/.gitignore", + "serverless-api/api/controllers/controller.js", + "serverless-api/api/controllers/delete.js", + "serverless-api/api/controllers/get.js", + "serverless-api/api/controllers/post.js", + "serverless-api/api/controllers/put.js", + "serverless-api/api/models/Product.js", + "serverless-api/api/models/ProductImage.js", + "serverless-api/api/models/User.js", + "serverless-api/api/routes/routes.js", + "serverless-api/api/services/service.js", + "serverless-api/index.js", + "serverless-api/package-lock.json", + "serverless-api/package.json", + "validate-local.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-23-swiggy-clone-ecs", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-24-dotnet-devsecops", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "DotNet-monitoring/.devcontainer/devcontainer.json", + "DotNet-monitoring/.dockerignore", + "DotNet-monitoring/.github/scripts/url-check.sh", + "DotNet-monitoring/.gitignore", + "DotNet-monitoring/.gitmodules", + "DotNet-monitoring/CONTRIBUTING.md", + "DotNet-monitoring/LICENSE", + "DotNet-monitoring/Properties/launchSettings.json", + "DotNet-monitoring/README.md", + "DotNet-monitoring/deploy/kubernetes/readme.md", + "DotNet-monitoring/deploy/readme.md", + "DotNet-monitoring/src/ApiHelper.cs", + "DotNet-monitoring/src/Pages/Error.cshtml", + "DotNet-monitoring/src/Pages/Error.cshtml.cs", + "DotNet-monitoring/src/Pages/Index.cshtml", + "DotNet-monitoring/src/Pages/Info.cshtml", + "DotNet-monitoring/src/Pages/Info.cshtml.cs", + "DotNet-monitoring/src/Pages/Monitor.cshtml", + "DotNet-monitoring/src/Pages/Shared/_Layout.cshtml", + "DotNet-monitoring/src/Pages/Shared/_UserPartial.cshtml", + "DotNet-monitoring/src/Pages/Tools.cshtml", + "DotNet-monitoring/src/Pages/Tools.cshtml.cs", + "DotNet-monitoring/src/Pages/User.cshtml", + "DotNet-monitoring/src/Pages/User.cshtml.cs", + "DotNet-monitoring/src/Pages/Weather.cshtml", + "DotNet-monitoring/src/Pages/_ViewImports.cshtml", + "DotNet-monitoring/src/Pages/_ViewStart.cshtml", + "DotNet-monitoring/src/Program.cs", + "DotNet-monitoring/src/appsettings.Development.sample.json", + "DotNet-monitoring/src/appsettings.json", + "DotNet-monitoring/src/dotnet-demoapp.csproj", + "DotNet-monitoring/src/wwwroot/css/site.css", + "DotNet-monitoring/src/wwwroot/js/monitoring.js", + "DotNet-monitoring/src/wwwroot/js/weather.js", + "DotNet-monitoring/src/wwwroot/js/weather.jso", + "DotNet-monitoring/src/wwwroot/open-weather-icons/css/open-weather-icons.css", + "DotNet-monitoring/tests/UnitTest.cs", + "DotNet-monitoring/tests/postman_collection.json", + "DotNet-monitoring/tests/tests.csproj", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "validate-local.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-25-petshop-devsecops", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-26-terraform-gitlab-cicd", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".gitignore", + ".gitlab-ci.yml", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "tfstate.config", + "validate-local.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-27-reddit-eks-argocd", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-28-openai-chatbot-eks", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Chatbot-UI/.env.example", + "Chatbot-UI/.eslintrc.json", + "Chatbot-UI/CONTRIBUTING.md", + "Chatbot-UI/EKS-TF/terraform.tfvars.example", + "Chatbot-UI/JenkinsFile/Chatbot-Jenkinsfile", + "Chatbot-UI/JenkinsFile/EKS-Jenkinsfile", + "Chatbot-UI/README.md", + "Chatbot-UI/__tests__/utils/app/importExports.test.ts", + "Chatbot-UI/__tests__/utils/server/google.test.ts", + "Chatbot-UI/__tests__/utils/server/request.test.ts", + "Chatbot-UI/components/Chat/Chat.tsx", + "Chatbot-UI/components/Chat/ChatInput.tsx", + "Chatbot-UI/components/Chat/ChatLoader.tsx", + "Chatbot-UI/components/Chat/ChatMessage.tsx", + "Chatbot-UI/components/Chat/ErrorMessageDiv.tsx", + "Chatbot-UI/components/Chat/ModelSelect.tsx", + "Chatbot-UI/components/Chat/PluginSelect.tsx", + "Chatbot-UI/components/Chat/PromptList.tsx", + "Chatbot-UI/components/Chat/Regenerate.tsx", + "Chatbot-UI/components/Chat/SystemPrompt.tsx", + "Chatbot-UI/components/Chat/VariableModal.tsx", + "Chatbot-UI/components/Chatbar/Chatbar.tsx", + "Chatbot-UI/components/Chatbar/ChatbarSettings.tsx", + "Chatbot-UI/components/Chatbar/ClearConversations.tsx", + "Chatbot-UI/components/Chatbar/Conversation.tsx", + "Chatbot-UI/components/Chatbar/Conversations.tsx", + "Chatbot-UI/components/Chatbar/PluginKeys.tsx", + "Chatbot-UI/components/Folders/Chat/ChatFolder.tsx", + "Chatbot-UI/components/Folders/Chat/ChatFolders.tsx", + "Chatbot-UI/components/Folders/Prompt/PromptFolder.tsx", + "Chatbot-UI/components/Folders/Prompt/PromptFolders.tsx", + "Chatbot-UI/components/Global/Spinner.tsx", + "Chatbot-UI/components/Markdown/CodeBlock.tsx", + "Chatbot-UI/components/Markdown/MemoizedReactMarkdown.tsx", + "Chatbot-UI/components/Mobile/Navbar.tsx", + "Chatbot-UI/components/Promptbar/Prompt.tsx", + "Chatbot-UI/components/Promptbar/PromptModal.tsx", + "Chatbot-UI/components/Promptbar/Promptbar.tsx", + "Chatbot-UI/components/Promptbar/PromptbarSettings.tsx", + "Chatbot-UI/components/Promptbar/Prompts.tsx", + "Chatbot-UI/components/Settings/Import.tsx", + "Chatbot-UI/components/Settings/Key.tsx", + "Chatbot-UI/components/Sidebar/Search.tsx", + "Chatbot-UI/components/Sidebar/SidebarButton.tsx", + "Chatbot-UI/docs/google_search.md", + "Chatbot-UI/license", + "Chatbot-UI/next-env.d.ts", + "Chatbot-UI/next-i18next.config.js", + "Chatbot-UI/next.config.js", + "Chatbot-UI/package-lock.json", + "Chatbot-UI/package.json", + "Chatbot-UI/pages/_app.tsx", + "Chatbot-UI/pages/_document.tsx", + "Chatbot-UI/pages/api/chat.ts", + "Chatbot-UI/pages/api/google.ts", + "Chatbot-UI/pages/api/health.ts", + "Chatbot-UI/pages/api/models.ts", + "Chatbot-UI/pages/index.tsx", + "Chatbot-UI/postcss.config.js", + "Chatbot-UI/prettier.config.js", + "Chatbot-UI/public/locales/ar/chat.json", + "Chatbot-UI/public/locales/ar/common.json", + "Chatbot-UI/public/locales/ar/markdown.json", + "Chatbot-UI/public/locales/ar/promptbar.json", + "Chatbot-UI/public/locales/ar/sidebar.json", + "Chatbot-UI/public/locales/bn/chat.json", + "Chatbot-UI/public/locales/bn/common.json", + "Chatbot-UI/public/locales/bn/markdown.json", + "Chatbot-UI/public/locales/bn/promptbar.json", + "Chatbot-UI/public/locales/bn/sidebar.json", + "Chatbot-UI/public/locales/de/chat.json", + "Chatbot-UI/public/locales/de/common.json", + "Chatbot-UI/public/locales/de/markdown.json", + "Chatbot-UI/public/locales/de/promptbar.json", + "Chatbot-UI/public/locales/de/sidebar.json", + "Chatbot-UI/public/locales/en/common.json", + "Chatbot-UI/public/locales/es/chat.json", + "Chatbot-UI/public/locales/es/common.json", + "Chatbot-UI/public/locales/es/markdown.json", + "Chatbot-UI/public/locales/es/promptbar.json", + "Chatbot-UI/public/locales/es/sidebar.json", + "Chatbot-UI/public/locales/fr/chat.json", + "Chatbot-UI/public/locales/fr/common.json", + "Chatbot-UI/public/locales/fr/markdown.json", + "Chatbot-UI/public/locales/fr/promptbar.json", + "Chatbot-UI/public/locales/fr/sidebar.json", + "Chatbot-UI/public/locales/he/chat.json", + "Chatbot-UI/public/locales/he/common.json", + "Chatbot-UI/public/locales/he/markdown.json", + "Chatbot-UI/public/locales/he/promptbar.json", + "Chatbot-UI/public/locales/he/sidebar.json", + "Chatbot-UI/public/locales/id/chat.json", + "Chatbot-UI/public/locales/id/common.json", + "Chatbot-UI/public/locales/id/markdown.json", + "Chatbot-UI/public/locales/id/promptbar.json", + "Chatbot-UI/public/locales/id/sidebar.json", + "Chatbot-UI/public/locales/it/chat.json", + "Chatbot-UI/public/locales/it/common.json", + "Chatbot-UI/public/locales/it/markdown.json", + "Chatbot-UI/public/locales/it/promptbar.json", + "Chatbot-UI/public/locales/it/sidebar.json", + "Chatbot-UI/public/locales/ja/chat.json", + "Chatbot-UI/public/locales/ja/common.json", + "Chatbot-UI/public/locales/ja/markdown.json", + "Chatbot-UI/public/locales/ja/promptbar.json", + "Chatbot-UI/public/locales/ja/sidebar.json", + "Chatbot-UI/public/locales/ko/chat.json", + "Chatbot-UI/public/locales/ko/common.json", + "Chatbot-UI/public/locales/ko/markdown.json", + "Chatbot-UI/public/locales/ko/promptbar.json", + "Chatbot-UI/public/locales/ko/sidebar.json", + "Chatbot-UI/public/locales/pt/chat.json", + "Chatbot-UI/public/locales/pt/common.json", + "Chatbot-UI/public/locales/pt/markdown.json", + "Chatbot-UI/public/locales/pt/promptbar.json", + "Chatbot-UI/public/locales/pt/sidebar.json", + "Chatbot-UI/public/locales/ru/chat.json", + "Chatbot-UI/public/locales/ru/common.json", + "Chatbot-UI/public/locales/ru/markdown.json", + "Chatbot-UI/public/locales/ru/promptbar.json", + "Chatbot-UI/public/locales/ru/sidebar.json", + "Chatbot-UI/public/locales/si/chat.json", + "Chatbot-UI/public/locales/si/common.json", + "Chatbot-UI/public/locales/si/markdown.json", + "Chatbot-UI/public/locales/si/promptbar.json", + "Chatbot-UI/public/locales/si/sidebar.json", + "Chatbot-UI/public/locales/sv/chat.json", + "Chatbot-UI/public/locales/sv/common.json", + "Chatbot-UI/public/locales/sv/markdown.json", + "Chatbot-UI/public/locales/sv/promptbar.json", + "Chatbot-UI/public/locales/sv/sidebar.json", + "Chatbot-UI/public/locales/te/chat.json", + "Chatbot-UI/public/locales/te/common.json", + "Chatbot-UI/public/locales/te/markdown.json", + "Chatbot-UI/public/locales/te/promptbar.json", + "Chatbot-UI/public/locales/te/sidebar.json", + "Chatbot-UI/public/locales/vi/chat.json", + "Chatbot-UI/public/locales/vi/common.json", + "Chatbot-UI/public/locales/vi/markdown.json", + "Chatbot-UI/public/locales/vi/promptbar.json", + "Chatbot-UI/public/locales/vi/sidebar.json", + "Chatbot-UI/public/locales/zh/chat.json", + "Chatbot-UI/public/locales/zh/common.json", + "Chatbot-UI/public/locales/zh/markdown.json", + "Chatbot-UI/public/locales/zh/promptbar.json", + "Chatbot-UI/public/locales/zh/sidebar.json", + "Chatbot-UI/styles/globals.css", + "Chatbot-UI/tailwind.config.js", + "Chatbot-UI/tsconfig.json", + "Chatbot-UI/types/chat.ts", + "Chatbot-UI/types/data.ts", + "Chatbot-UI/types/env.ts", + "Chatbot-UI/types/error.ts", + "Chatbot-UI/types/export.ts", + "Chatbot-UI/types/folder.ts", + "Chatbot-UI/types/google.ts", + "Chatbot-UI/types/index.ts", + "Chatbot-UI/types/openai.ts", + "Chatbot-UI/types/plugin.ts", + "Chatbot-UI/types/prompt.ts", + "Chatbot-UI/types/storage.ts", + "Chatbot-UI/utils/app/api.ts", + "Chatbot-UI/utils/app/clean.ts", + "Chatbot-UI/utils/app/codeblock.ts", + "Chatbot-UI/utils/app/const.ts", + "Chatbot-UI/utils/app/conversation.ts", + "Chatbot-UI/utils/app/folders.ts", + "Chatbot-UI/utils/app/importExport.ts", + "Chatbot-UI/utils/app/prompts.ts", + "Chatbot-UI/utils/index.ts", + "Chatbot-UI/utils/server/google.ts", + "Chatbot-UI/utils/server/index.ts", + "Chatbot-UI/utils/server/request.ts", + "Chatbot-UI/vitest.config.ts", + "INSTRUCTOR_BOUNDARY.md", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "QUARANTINE.md", + "README.md", + "START_HERE.md", + "chatbot.py", + "docs/portfolio-runbook.md", + "fixtures/evidence-local-result.txt", + "main.py", + "project.yaml", + "test_chatbot.py", + "validate-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-29-voting-app-argocd", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-30-blog-app-eks", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "INSTRUCTOR_BOUNDARY.md", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "app/Jenkinsfile1", + "app/RBAC.md", + "app/README.md", + "app/email_notification.md", + "app/emtpy.txt", + "app/install_docker.sh", + "app/issue.md", + "app/jen1.txt", + "app/mvnw", + "app/mvnw.cmd", + "app/pom.xml", + "app/src/main/java/com/example/twitterapp/TwitterAppApplication.java", + "app/src/main/java/com/example/twitterapp/config/CustomUserDetails.java", + "app/src/main/java/com/example/twitterapp/config/CustomUserDetailsService.java", + "app/src/main/java/com/example/twitterapp/config/SecurityConfig.java", + "app/src/main/java/com/example/twitterapp/controller/PostController.java", + "app/src/main/java/com/example/twitterapp/controller/UserController.java", + "app/src/main/java/com/example/twitterapp/model/Post.java", + "app/src/main/java/com/example/twitterapp/model/User.java", + "app/src/main/java/com/example/twitterapp/repository/PostRepository.java", + "app/src/main/java/com/example/twitterapp/repository/UserRepository.java", + "app/src/main/java/com/example/twitterapp/service/PostService.java", + "app/src/main/java/com/example/twitterapp/service/UserService.java", + "app/src/main/java/com/example/twitterapp/service/UserServiceImpl.java", + "app/src/main/resources/application.properties", + "app/src/main/resources/templates/add.html", + "app/src/main/resources/templates/home.html", + "app/src/main/resources/templates/login.html", + "app/src/main/resources/templates/register.html", + "app/src/test/java/com/example/twitterapp/TwitterAppApplicationTests.java", + "fixtures/evidence-local-result.txt", + "project.yaml", + "validate-local.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh", + "validate_p1_manifest.py" + ], + "static_assets": [] + }, + { + "project": "project-31-cloud-native-monitoring", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-32-tetris-devsecops-k8s", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-33-node-cicd-eks-gha", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".github/workflows/e2ecicd.yaml.blocked", + ".gitignore", + "Makefile", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "VERSION", + "app/.dockerignore", + "app/Dockerfile-python", + "app/app.py", + "app/calculator.js", + "app/calculator.test.js", + "app/index.js", + "app/index.test.js", + "app/package-lock.json", + "app/package.json", + "fixtures/evidence-local-result.txt", + "project.yaml", + "validate-local.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-34-node-cicd-ecs-terraform-gha", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-35-devsecops-pipeline-series", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".gitignore", + "INSTRUCTOR_BOUNDARY.md", + "P0_REMEDIATION.md", + "P1_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/evidence-local-result.txt", + "fixtures/intentionally-vulnerable/README.md", + "pipeline_security.py", + "policy.json", + "project.yaml", + "reset-local.sh", + "step-1-infra-creation/README.md", + "step-1-infra-creation/install_jenkins.sh", + "step-2-sast-sonarcloud/LICENSE", + "step-2-sast-sonarcloud/README.md", + "step-2-sast-sonarcloud/catalina.policy", + "step-2-sast-sonarcloud/pom.xml", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/model/User.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/AdminsMainServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLoginServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLogoutServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/ExitServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/PingServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/servlets/TestServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/utils/ApplicationUtils.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/utils/Closer.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/utils/DeleteClassWhileMavenBuild.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/utils/EmailUtils.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/core/utils/MultiPartFileUtils.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/AssertionErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/ExceptionInInitializerErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/FactoryConfigurationErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/NoClassDefFoundErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet2.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet3.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet4.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet5.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet6.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/StackOverflowErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/TransformerFactoryConfigurationErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/errors/UnsatisfiedLinkErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ArithmeticExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayIndexOutOfBoundsExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayStoreExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/BufferOverflowExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/BufferUnderflowExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/CannotRedoExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/CannotUndoExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ClassCastExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ConcurrentModificationExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/EmptyStackExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalArgumentExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalMonitorStateExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalPathStateExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalStateExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalThreadStateExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/ImagingOpExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/IndexOutOfBoundsExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/InputMismatchExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/MalformedParameterizedTypeExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/MissingResourceExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/NegativeArraySizeExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/NoSuchElementExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/NullPointerExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/NumberFormatExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/SecurityExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedCharsetExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedOperationExceptionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/performance/CreatingUnnecessaryObjectsServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/performance/SlowRegularExpressionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/performance/StringPlusOperationServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/DBConnectionLeakServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet2.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/EndlessWaitingServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/FileDescriptorLeakServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/ForwardLoopServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/InfiniteLoopServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/IntegerOverflowServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/JVMCrashByEAVServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/LossOfTrailingDigitsServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet2.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet3.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/MojibakeServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/NetworkSocketLeakServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/RedirectLoopServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/RoundOffErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/ThreadLeakServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/troubles/TruncationErrorServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/BruteForceServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CSRFServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/ClickJackingServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CodeInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/LDAPInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/MailHeaderInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/NullByteInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OpenRedirectServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SQLInjectionServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SessionFixationServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedExtensionUploadServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedSizeUploadServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/VerboseErrorMessageServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java", + "step-2-sast-sonarcloud/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XSSServlet.java", + "step-2-sast-sonarcloud/src/main/resources/ESAPI.properties", + "step-2-sast-sonarcloud/src/main/resources/application.properties", + "step-2-sast-sonarcloud/src/main/resources/indexpage_en.properties", + "step-2-sast-sonarcloud/src/main/resources/indexpage_ja.properties", + "step-2-sast-sonarcloud/src/main/resources/log4j.xml", + "step-2-sast-sonarcloud/src/main/resources/messages_en.properties", + "step-2-sast-sonarcloud/src/main/resources/messages_ja.properties", + "step-2-sast-sonarcloud/src/main/webapp/WEB-INF/web.xml", + "step-2-sast-sonarcloud/src/main/webapp/dfi/includable.jsp", + "step-2-sast-sonarcloud/src/main/webapp/dfi/style_bootstrap.html", + "step-2-sast-sonarcloud/src/main/webapp/dfi/style_google_mdl.html", + "step-2-sast-sonarcloud/src/main/webapp/dfi/style_materialize.html", + "step-2-sast-sonarcloud/src/main/webapp/dt/basic_footer.html", + "step-2-sast-sonarcloud/src/main/webapp/dt/basic_header.html", + "step-2-sast-sonarcloud/src/main/webapp/dt/includable.jsp", + "step-2-sast-sonarcloud/src/main/webapp/dt/monochro_footer.html", + "step-2-sast-sonarcloud/src/main/webapp/dt/monochro_header.html", + "step-2-sast-sonarcloud/src/main/webapp/index.jsp", + "step-2-sast-sonarcloud/src/main/webapp/uid/adminpassword.txt", + "step-2-sast-sonarcloud/src/main/webapp/uid/clientinfo.jsp", + "step-2-sast-sonarcloud/src/main/webapp/uid/serverinfo.jsp", + "step-3-sca-snyk/LICENSE", + "step-3-sca-snyk/README.md", + "step-3-sca-snyk/catalina.policy", + "step-3-sca-snyk/pom.xml", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/model/User.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/AdminsMainServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLoginServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLogoutServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/ExitServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/PingServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/servlets/TestServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/utils/ApplicationUtils.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/utils/Closer.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/utils/DeleteClassWhileMavenBuild.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/utils/EmailUtils.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/core/utils/MultiPartFileUtils.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/AssertionErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/ExceptionInInitializerErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/FactoryConfigurationErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/NoClassDefFoundErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet2.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet3.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet4.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet5.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet6.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/StackOverflowErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/TransformerFactoryConfigurationErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/errors/UnsatisfiedLinkErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ArithmeticExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayIndexOutOfBoundsExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayStoreExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/BufferOverflowExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/BufferUnderflowExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/CannotRedoExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/CannotUndoExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ClassCastExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ConcurrentModificationExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/EmptyStackExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalArgumentExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalMonitorStateExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalPathStateExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalStateExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalThreadStateExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/ImagingOpExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/IndexOutOfBoundsExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/InputMismatchExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/MalformedParameterizedTypeExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/MissingResourceExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/NegativeArraySizeExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/NoSuchElementExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/NullPointerExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/NumberFormatExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/SecurityExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedCharsetExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedOperationExceptionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/performance/CreatingUnnecessaryObjectsServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/performance/SlowRegularExpressionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/performance/StringPlusOperationServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/DBConnectionLeakServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet2.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/EndlessWaitingServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/FileDescriptorLeakServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/ForwardLoopServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/InfiniteLoopServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/IntegerOverflowServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/JVMCrashByEAVServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/LossOfTrailingDigitsServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet2.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet3.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/MojibakeServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/NetworkSocketLeakServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/RedirectLoopServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/RoundOffErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/ThreadLeakServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/troubles/TruncationErrorServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/BruteForceServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CSRFServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/ClickJackingServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CodeInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/LDAPInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/MailHeaderInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/NullByteInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OpenRedirectServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SQLInjectionServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SessionFixationServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedExtensionUploadServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedSizeUploadServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/VerboseErrorMessageServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java", + "step-3-sca-snyk/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XSSServlet.java", + "step-3-sca-snyk/src/main/resources/ESAPI.properties", + "step-3-sca-snyk/src/main/resources/application.properties", + "step-3-sca-snyk/src/main/resources/indexpage_en.properties", + "step-3-sca-snyk/src/main/resources/indexpage_ja.properties", + "step-3-sca-snyk/src/main/resources/log4j.xml", + "step-3-sca-snyk/src/main/resources/messages_en.properties", + "step-3-sca-snyk/src/main/resources/messages_ja.properties", + "step-3-sca-snyk/src/main/webapp/WEB-INF/web.xml", + "step-3-sca-snyk/src/main/webapp/dfi/includable.jsp", + "step-3-sca-snyk/src/main/webapp/dfi/style_bootstrap.html", + "step-3-sca-snyk/src/main/webapp/dfi/style_google_mdl.html", + "step-3-sca-snyk/src/main/webapp/dfi/style_materialize.html", + "step-3-sca-snyk/src/main/webapp/dt/basic_footer.html", + "step-3-sca-snyk/src/main/webapp/dt/basic_header.html", + "step-3-sca-snyk/src/main/webapp/dt/includable.jsp", + "step-3-sca-snyk/src/main/webapp/dt/monochro_footer.html", + "step-3-sca-snyk/src/main/webapp/dt/monochro_header.html", + "step-3-sca-snyk/src/main/webapp/index.jsp", + "step-3-sca-snyk/src/main/webapp/uid/adminpassword.txt", + "step-3-sca-snyk/src/main/webapp/uid/clientinfo.jsp", + "step-3-sca-snyk/src/main/webapp/uid/serverinfo.jsp", + "step-4-docker-ecr/LICENSE", + "step-4-docker-ecr/README.md", + "step-4-docker-ecr/catalina.policy", + "step-4-docker-ecr/deployment.yaml", + "step-4-docker-ecr/pom.xml", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/model/User.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/AdminsMainServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLoginServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLogoutServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/ExitServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/PingServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/servlets/TestServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/utils/ApplicationUtils.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/utils/Closer.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/utils/DeleteClassWhileMavenBuild.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/utils/EmailUtils.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/core/utils/MultiPartFileUtils.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/AssertionErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/ExceptionInInitializerErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/FactoryConfigurationErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/NoClassDefFoundErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet2.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet3.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet4.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet5.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet6.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/StackOverflowErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/TransformerFactoryConfigurationErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/errors/UnsatisfiedLinkErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ArithmeticExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayIndexOutOfBoundsExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayStoreExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/BufferOverflowExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/BufferUnderflowExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/CannotRedoExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/CannotUndoExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ClassCastExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ConcurrentModificationExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/EmptyStackExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalArgumentExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalMonitorStateExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalPathStateExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalStateExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalThreadStateExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/ImagingOpExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/IndexOutOfBoundsExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/InputMismatchExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/MalformedParameterizedTypeExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/MissingResourceExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/NegativeArraySizeExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/NoSuchElementExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/NullPointerExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/NumberFormatExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/SecurityExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedCharsetExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedOperationExceptionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/performance/CreatingUnnecessaryObjectsServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/performance/SlowRegularExpressionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/performance/StringPlusOperationServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/DBConnectionLeakServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet2.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/EndlessWaitingServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/FileDescriptorLeakServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/ForwardLoopServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/InfiniteLoopServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/IntegerOverflowServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/JVMCrashByEAVServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/LossOfTrailingDigitsServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet2.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet3.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/MojibakeServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/NetworkSocketLeakServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/RedirectLoopServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/RoundOffErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/ThreadLeakServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/troubles/TruncationErrorServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/BruteForceServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CSRFServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/ClickJackingServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CodeInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/LDAPInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/MailHeaderInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/NullByteInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OpenRedirectServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SQLInjectionServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SessionFixationServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedExtensionUploadServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedSizeUploadServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/VerboseErrorMessageServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java", + "step-4-docker-ecr/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XSSServlet.java", + "step-4-docker-ecr/src/main/resources/ESAPI.properties", + "step-4-docker-ecr/src/main/resources/application.properties", + "step-4-docker-ecr/src/main/resources/indexpage_en.properties", + "step-4-docker-ecr/src/main/resources/indexpage_ja.properties", + "step-4-docker-ecr/src/main/resources/log4j.xml", + "step-4-docker-ecr/src/main/resources/messages_en.properties", + "step-4-docker-ecr/src/main/resources/messages_ja.properties", + "step-4-docker-ecr/src/main/webapp/WEB-INF/web.xml", + "step-4-docker-ecr/src/main/webapp/dfi/includable.jsp", + "step-4-docker-ecr/src/main/webapp/dfi/style_bootstrap.html", + "step-4-docker-ecr/src/main/webapp/dfi/style_google_mdl.html", + "step-4-docker-ecr/src/main/webapp/dfi/style_materialize.html", + "step-4-docker-ecr/src/main/webapp/dt/basic_footer.html", + "step-4-docker-ecr/src/main/webapp/dt/basic_header.html", + "step-4-docker-ecr/src/main/webapp/dt/includable.jsp", + "step-4-docker-ecr/src/main/webapp/dt/monochro_footer.html", + "step-4-docker-ecr/src/main/webapp/dt/monochro_header.html", + "step-4-docker-ecr/src/main/webapp/index.jsp", + "step-4-docker-ecr/src/main/webapp/uid/adminpassword.txt", + "step-4-docker-ecr/src/main/webapp/uid/clientinfo.jsp", + "step-4-docker-ecr/src/main/webapp/uid/serverinfo.jsp", + "step-5-deploy-k8s/LICENSE", + "step-5-deploy-k8s/README.md", + "step-5-deploy-k8s/catalina.policy", + "step-5-deploy-k8s/deployment.yaml", + "step-5-deploy-k8s/pom.xml", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/model/User.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/AdminsMainServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLoginServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLogoutServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/ExitServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/PingServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/servlets/TestServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/utils/ApplicationUtils.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/utils/Closer.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/utils/DeleteClassWhileMavenBuild.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/utils/EmailUtils.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/core/utils/MultiPartFileUtils.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/AssertionErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/ExceptionInInitializerErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/FactoryConfigurationErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/NoClassDefFoundErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet2.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet3.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet4.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet5.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet6.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/StackOverflowErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/TransformerFactoryConfigurationErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/errors/UnsatisfiedLinkErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ArithmeticExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayIndexOutOfBoundsExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayStoreExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/BufferOverflowExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/BufferUnderflowExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/CannotRedoExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/CannotUndoExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ClassCastExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ConcurrentModificationExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/EmptyStackExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalArgumentExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalMonitorStateExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalPathStateExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalStateExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalThreadStateExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/ImagingOpExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/IndexOutOfBoundsExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/InputMismatchExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/MalformedParameterizedTypeExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/MissingResourceExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/NegativeArraySizeExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/NoSuchElementExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/NullPointerExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/NumberFormatExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/SecurityExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedCharsetExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedOperationExceptionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/performance/CreatingUnnecessaryObjectsServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/performance/SlowRegularExpressionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/performance/StringPlusOperationServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/DBConnectionLeakServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet2.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/EndlessWaitingServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/FileDescriptorLeakServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/ForwardLoopServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/InfiniteLoopServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/IntegerOverflowServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/JVMCrashByEAVServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/LossOfTrailingDigitsServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet2.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet3.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/MojibakeServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/NetworkSocketLeakServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/RedirectLoopServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/RoundOffErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/ThreadLeakServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/troubles/TruncationErrorServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/BruteForceServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CSRFServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/ClickJackingServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CodeInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/LDAPInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/MailHeaderInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/NullByteInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OpenRedirectServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SQLInjectionServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SessionFixationServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedExtensionUploadServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedSizeUploadServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/VerboseErrorMessageServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java", + "step-5-deploy-k8s/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XSSServlet.java", + "step-5-deploy-k8s/src/main/resources/ESAPI.properties", + "step-5-deploy-k8s/src/main/resources/application.properties", + "step-5-deploy-k8s/src/main/resources/indexpage_en.properties", + "step-5-deploy-k8s/src/main/resources/indexpage_ja.properties", + "step-5-deploy-k8s/src/main/resources/log4j.xml", + "step-5-deploy-k8s/src/main/resources/messages_en.properties", + "step-5-deploy-k8s/src/main/resources/messages_ja.properties", + "step-5-deploy-k8s/src/main/webapp/WEB-INF/web.xml", + "step-5-deploy-k8s/src/main/webapp/dfi/includable.jsp", + "step-5-deploy-k8s/src/main/webapp/dfi/style_bootstrap.html", + "step-5-deploy-k8s/src/main/webapp/dfi/style_google_mdl.html", + "step-5-deploy-k8s/src/main/webapp/dfi/style_materialize.html", + "step-5-deploy-k8s/src/main/webapp/dt/basic_footer.html", + "step-5-deploy-k8s/src/main/webapp/dt/basic_header.html", + "step-5-deploy-k8s/src/main/webapp/dt/includable.jsp", + "step-5-deploy-k8s/src/main/webapp/dt/monochro_footer.html", + "step-5-deploy-k8s/src/main/webapp/dt/monochro_header.html", + "step-5-deploy-k8s/src/main/webapp/index.jsp", + "step-5-deploy-k8s/src/main/webapp/uid/adminpassword.txt", + "step-5-deploy-k8s/src/main/webapp/uid/clientinfo.jsp", + "step-5-deploy-k8s/src/main/webapp/uid/serverinfo.jsp", + "step-6-dast-zap-e2e/LICENSE", + "step-6-dast-zap-e2e/README.md", + "step-6-dast-zap-e2e/catalina.policy", + "step-6-dast-zap-e2e/deployment.yaml", + "step-6-dast-zap-e2e/pom.xml", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/model/User.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/AdminsMainServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLoginServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/DefaultLogoutServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/ExitServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/PingServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/servlets/TestServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/utils/ApplicationUtils.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/utils/Closer.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/utils/DeleteClassWhileMavenBuild.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/utils/EmailUtils.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/core/utils/MultiPartFileUtils.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/AssertionErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/ExceptionInInitializerErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/FactoryConfigurationErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/NoClassDefFoundErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet2.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet3.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet4.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet5.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/OutOfMemoryErrorServlet6.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/StackOverflowErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/TransformerFactoryConfigurationErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/errors/UnsatisfiedLinkErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ArithmeticExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayIndexOutOfBoundsExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ArrayStoreExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/BufferOverflowExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/BufferUnderflowExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/CannotRedoExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/CannotUndoExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ClassCastExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ConcurrentModificationExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/EmptyStackExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalArgumentExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalMonitorStateExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalPathStateExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalStateExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IllegalThreadStateExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/ImagingOpExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/IndexOutOfBoundsExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/InputMismatchExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/MalformedParameterizedTypeExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/MissingResourceExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/NegativeArraySizeExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/NoSuchElementExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/NullPointerExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/NumberFormatExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/SecurityExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedCharsetExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/exceptions/UnsupportedOperationExceptionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/performance/CreatingUnnecessaryObjectsServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/performance/SlowRegularExpressionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/performance/StringPlusOperationServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/DBConnectionLeakServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/DeadlockServlet2.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/EndlessWaitingServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/FileDescriptorLeakServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/ForwardLoopServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/InfiniteLoopServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/IntegerOverflowServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/JVMCrashByEAVServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/LossOfTrailingDigitsServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet2.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/MemoryLeakServlet3.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/MojibakeServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/NetworkSocketLeakServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/RedirectLoopServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/RoundOffErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/ThreadLeakServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/troubles/TruncationErrorServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/BruteForceServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CSRFServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/ClickJackingServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/CodeInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/LDAPInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/MailHeaderInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/NullByteInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OpenRedirectServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SQLInjectionServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/SessionFixationServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedExtensionUploadServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/UnrestrictedSizeUploadServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/VerboseErrorMessageServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XEEandXXEServlet.java", + "step-6-dast-zap-e2e/src/main/java/org/t246osslab/easybuggy/vulnerabilities/XSSServlet.java", + "step-6-dast-zap-e2e/src/main/resources/ESAPI.properties", + "step-6-dast-zap-e2e/src/main/resources/application.properties", + "step-6-dast-zap-e2e/src/main/resources/indexpage_en.properties", + "step-6-dast-zap-e2e/src/main/resources/indexpage_ja.properties", + "step-6-dast-zap-e2e/src/main/resources/log4j.xml", + "step-6-dast-zap-e2e/src/main/resources/messages_en.properties", + "step-6-dast-zap-e2e/src/main/resources/messages_ja.properties", + "step-6-dast-zap-e2e/src/main/webapp/WEB-INF/web.xml", + "step-6-dast-zap-e2e/src/main/webapp/dfi/includable.jsp", + "step-6-dast-zap-e2e/src/main/webapp/dfi/style_bootstrap.html", + "step-6-dast-zap-e2e/src/main/webapp/dfi/style_google_mdl.html", + "step-6-dast-zap-e2e/src/main/webapp/dfi/style_materialize.html", + "step-6-dast-zap-e2e/src/main/webapp/dt/basic_footer.html", + "step-6-dast-zap-e2e/src/main/webapp/dt/basic_header.html", + "step-6-dast-zap-e2e/src/main/webapp/dt/includable.jsp", + "step-6-dast-zap-e2e/src/main/webapp/dt/monochro_footer.html", + "step-6-dast-zap-e2e/src/main/webapp/dt/monochro_header.html", + "step-6-dast-zap-e2e/src/main/webapp/index.jsp", + "step-6-dast-zap-e2e/src/main/webapp/uid/adminpassword.txt", + "step-6-dast-zap-e2e/src/main/webapp/uid/clientinfo.jsp", + "step-6-dast-zap-e2e/src/main/webapp/uid/serverinfo.jsp", + "test_pipeline_security.py", + "validate-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-36-aws-realtime-deployment", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-37-eks-terraform-provision", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "tests/test_policy.sh", + "validate-local.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-38-docker-terraform-3tier", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "LICENSE", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "backend/index.js", + "backend/package-lock.json", + "backend/package.json", + "fixtures/evidence-local-result.txt", + "frontend/index.js", + "frontend/package-lock.json", + "frontend/package.json", + "init_sql_scripts/init.sql", + "project.yaml", + "terraform-configs/README.md", + "terraform-configs/data.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-39-gha-aws-terraform", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".github/dependabot.yml", + ".github/workflows/local-plan.yml", + "LICENSE", + "P0_REMEDIATION.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "app.json.tpl", + "ci/check-local-policy.sh", + "ci/plan-only.sh", + "ci/test-local-policy.sh", + "fixtures/clean/plan-policy.json", + "fixtures/evidence-local-result.txt", + "fixtures/negative/mutation.yml", + "index.js", + "package.json", + "project.yaml", + "project/index.js", + "project/package.json", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-40-k8s-dashboard-trivy", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-41-online-boutique-microservices", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "SOLUTION.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "test/loadgenerator-output.txt", + "test/loadgenerator.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-42-serverless-api-dynamodb", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean_local.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative_cloud_command.txt", + "project.yaml", + "validate-p2-local.sh", + "validate_local.py" + ], + "static_assets": [] + }, + { + "project": "project-43-ecs-fargate-terraform", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-44-devsecops-101", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-45-jenkins-cicd-argocd-vault", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".p1_active_paths", + "P1_LOCAL_CONTRACT.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/clean/contract.txt", + "fixtures/clean/p2-clean.txt", + "fixtures/evidence-local-result.txt", + "fixtures/negative/credential.txt", + "fixtures/negative/mutation.txt", + "fixtures/negative/p2-source-shaped.txt", + "fixtures/negative/public_bind.txt", + "local-lab/contract.json", + "project.yaml", + "reset-p2-local.sh", + "validate-p1-stream3.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-46-eks-cluster-terraform-advanced", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".gitignore", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "kubectl.sha256", + "project.yaml", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-47-django-saas-ecommerce", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + ".dockerignore", + ".env.example", + ".github/workflows/autoPull.sh", + ".github/workflows/autoPush.sh", + ".gitignore", + ".terraformignore", + "INSTRUCTOR_BOUNDARY.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "Procfile", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "apps/__init__.py", + "apps/analytics/__init__.py", + "apps/app/__init__.py", + "apps/app/admin.py", + "apps/app/apps.py", + "apps/app/migrations/0001_initial.py", + "apps/app/migrations/__init__.py", + "apps/app/models.py", + "apps/app/tests.py", + "apps/app/urls.py", + "apps/app/views.py", + "apps/cart/__init__.py", + "apps/client_app/__init__.py", + "apps/client_app/admin.py", + "apps/client_app/apps.py", + "apps/client_app/migrations/0001_initial.py", + "apps/client_app/migrations/__init__.py", + "apps/client_app/models.py", + "apps/client_app/tests.py", + "apps/client_app/urls.py", + "apps/client_app/views.py", + "apps/config.py", + "apps/customers/__init__.py", + "apps/finances/__init__.py", + "apps/finances/admin.py", + "apps/finances/apps.py", + "apps/finances/migrations/0001_initial.py", + "apps/finances/migrations/0002_restaurant.py", + "apps/finances/migrations/0003_delete_restaurant_alter_account_initial_balance.py", + "apps/finances/migrations/__init__.py", + "apps/finances/models.py", + "apps/finances/schema.py", + "apps/finances/serializer.py", + "apps/finances/tests.py", + "apps/finances/transaction.py", + "apps/finances/urls.py", + "apps/finances/views.py", + "apps/home/__init__.py", + "apps/home/admin.py", + "apps/home/apps.py", + "apps/home/migrations/__init__.py", + "apps/home/models.py", + "apps/home/tests.py", + "apps/home/urls.py", + "apps/home/views.py", + "apps/orders/__init__.py", + "apps/payments/__init__.py", + "apps/payments/admin.py", + "apps/payments/apps.py", + "apps/payments/models.py", + "apps/payments/tests.py", + "apps/payments/urls.py", + "apps/payments/views.py", + "apps/products/__init__.py", + "apps/products/admin.py", + "apps/products/apps.py", + "apps/products/forms.py", + "apps/products/migrations/0001_initial.py", + "apps/products/migrations/0002_paymenthistory.py", + "apps/products/migrations/0003_billingaddress_category_coupon_item_order_slide_and_more.py", + "apps/products/migrations/__init__.py", + "apps/products/models.py", + "apps/products/serializer.py", + "apps/products/tests.py", + "apps/products/urls.py", + "apps/products/views.py", + "apps/shipping/__init__.py", + "apps/snippets/__init__.py", + "apps/snippets/admin.py", + "apps/snippets/apps.py", + "apps/snippets/filters.py", + "apps/snippets/managers.py", + "apps/snippets/migrations/0001_initial.py", + "apps/snippets/migrations/0002_alter_snippet_language.py", + "apps/snippets/migrations/0003_alter_snippet_language.py", + "apps/snippets/migrations/__init__.py", + "apps/snippets/models.py", + "apps/snippets/serializers.py", + "apps/snippets/urls.py", + "apps/snippets/views.py", + "apps/static/assets/css/nucleo-icons.css", + "apps/static/assets/css/nucleo-svg.css", + "apps/static/assets/css/soft-ui-dashboard.css", + "apps/static/assets/css/soft-ui-dashboard.min.css", + "apps/static/assets/gulpfile.js", + "apps/static/assets/js/core/bootstrap.min.js", + "apps/static/assets/js/core/popper.min.js", + "apps/static/assets/js/plugins/Chart.extension.js", + "apps/static/assets/js/plugins/bootstrap-notify.js", + "apps/static/assets/js/plugins/chartjs.min.js", + "apps/static/assets/js/plugins/perfect-scrollbar.min.js", + "apps/static/assets/js/plugins/smooth-scrollbar.min.js", + "apps/static/assets/js/soft-ui-dashboard.js", + "apps/static/assets/js/soft-ui-dashboard.min.js", + "apps/static/assets/package.json", + "apps/static/assets/scss/soft-ui-dashboard.scss", + "apps/static/assets/scss/soft-ui-dashboard/_alert.scss", + "apps/static/assets/scss/soft-ui-dashboard/_badge.scss", + "apps/static/assets/scss/soft-ui-dashboard/_buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/_cards.scss", + "apps/static/assets/scss/soft-ui-dashboard/_dropdown.scss", + "apps/static/assets/scss/soft-ui-dashboard/_dropup.scss", + "apps/static/assets/scss/soft-ui-dashboard/_fixed-plugin.scss", + "apps/static/assets/scss/soft-ui-dashboard/_footer.scss", + "apps/static/assets/scss/soft-ui-dashboard/_forms.scss", + "apps/static/assets/scss/soft-ui-dashboard/_gradients.scss", + "apps/static/assets/scss/soft-ui-dashboard/_header.scss", + "apps/static/assets/scss/soft-ui-dashboard/_info-areas.scss", + "apps/static/assets/scss/soft-ui-dashboard/_misc.scss", + "apps/static/assets/scss/soft-ui-dashboard/_nav.scss", + "apps/static/assets/scss/soft-ui-dashboard/_navbar-vertical.scss", + "apps/static/assets/scss/soft-ui-dashboard/_navbar.scss", + "apps/static/assets/scss/soft-ui-dashboard/_pagination.scss", + "apps/static/assets/scss/soft-ui-dashboard/_popovers.scss", + "apps/static/assets/scss/soft-ui-dashboard/_progress.scss", + "apps/static/assets/scss/soft-ui-dashboard/_rtl.scss", + "apps/static/assets/scss/soft-ui-dashboard/_social-buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/_tables.scss", + "apps/static/assets/scss/soft-ui-dashboard/_timeline.scss", + "apps/static/assets/scss/soft-ui-dashboard/_tooltips.scss", + "apps/static/assets/scss/soft-ui-dashboard/_typography.scss", + "apps/static/assets/scss/soft-ui-dashboard/_utilities.scss", + "apps/static/assets/scss/soft-ui-dashboard/_variables.scss", + "apps/static/assets/scss/soft-ui-dashboard/avatars/_avatar-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/avatars/_avatar.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_accordion.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_alert.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_badge.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_breadcrumb.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_button-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_card.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_carousel.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_close.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_containers.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_dropdown.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_forms.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_functions.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_grid.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_helpers.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_images.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_list-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_mixins.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_modal.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_nav.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_navbar.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_offcanvas.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_pagination.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_popover.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_progress.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_reboot.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_root.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_spinners.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_tables.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_toasts.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_tooltip.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_transitions.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_type.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_utilities.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/_variables.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/bootstrap-grid.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/bootstrap-reboot.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/bootstrap-utilities.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/bootstrap.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_floating-labels.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_form-check.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_form-control.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_form-range.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_form-select.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_form-text.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_input-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_labels.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/forms/_validation.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_clearfix.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_colored-links.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_position.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_ratio.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_stretched-link.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_text-truncation.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/helpers/_visually-hidden.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_alert.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_border-radius.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_box-shadow.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_breakpoints.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_caret.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_clearfix.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_container.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_deprecate.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_forms.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_gradients.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_grid.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_image.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_list-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_lists.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_pagination.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_reset-text.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_resize.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_table-variants.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_text-truncate.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_transition.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_utilities.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/mixins/_visually-hidden.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/utilities/_api.scss", + "apps/static/assets/scss/soft-ui-dashboard/bootstrap/vendor/_rfs.scss", + "apps/static/assets/scss/soft-ui-dashboard/breadcrumbs/_breadcrumb.scss", + "apps/static/assets/scss/soft-ui-dashboard/cards/card-background.scss", + "apps/static/assets/scss/soft-ui-dashboard/custom/_styles.scss", + "apps/static/assets/scss/soft-ui-dashboard/custom/_variables.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_form-check.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_form-select.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_form-switch.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_forms.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_input-group.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_inputs.scss", + "apps/static/assets/scss/soft-ui-dashboard/forms/_labels.scss", + "apps/static/assets/scss/soft-ui-dashboard/mixins/_hover.scss", + "apps/static/assets/scss/soft-ui-dashboard/mixins/_social-buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/mixins/mixins.scss", + "apps/static/assets/scss/soft-ui-dashboard/theme.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_animations.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_avatars.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_breadcrumb.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_cards.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_dropdowns.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_fixed-plugin.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_form-switch.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_header.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_info-areas.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_misc.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_navbar-vertical.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_navbar.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_pagination.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_rtl.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_social-buttons.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_table.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_timeline.scss", + "apps/static/assets/scss/soft-ui-dashboard/variables/_utilities.scss", + "apps/static/sitemap.xml", + "apps/stores/__init__.py", + "apps/templates/base.html", + "apps/templates/client_app/client_index.html", + "apps/templates/finances/home.html", + "apps/templates/home/index.html", + "apps/templates/payments/users.html", + "apps/templates/products/cancel.html", + "apps/templates/products/product_detail.html", + "apps/templates/products/product_list.html", + "apps/templates/products/success.html", + "apps/tenant_manegment/__init__.py", + "apps/user_management/__init__.py", + "apps/user_registration/__init.py", + "apps/users/__init__.py", + "apps/users/admin.py", + "apps/users/apps.py", + "apps/users/migrations/0001_initial.py", + "apps/users/migrations/__init__.py", + "apps/users/models.py", + "apps/users/serializers.py", + "apps/users/tests.py", + "apps/users/urls.py", + "apps/users/utils.py", + "apps/users/views.py", + "database.ini", + "docker-compose-nginx.yaml", + "docs/portfolio-runbook.md", + "fixtures/evidence-local-result.txt", + "fixtures/negative-git-lifecycle.txt", + "fixtures/offline-read-only-status.txt", + "gunicorn_config.py", + "manage.py", + "media/images/download.jfif", + "media/products/dfgdfgdfgdfg-images.jfif", + "media/products/gianvito-rossi-images.jfif", + "media/products/nike-images.jfif", + "multitenantsaas/__init__.py", + "multitenantsaas/asgi.py", + "multitenantsaas/settings.py", + "multitenantsaas/staticfiles/.gitkeep", + "multitenantsaas/tests.py", + "multitenantsaas/urls.py", + "multitenantsaas/wsgi.py", + "nginx.conf", + "nginx/appsee-app.conf", + "nginx/conf.d/nginx.conf", + "nginx/default.conf", + "nginx/nginx-default.conf", + "project.yaml", + "pytest.ini", + "requirements.txt", + "run.sh", + "runtime.txt", + "server-entrypoint.sh", + "tests/test_healthcheck.py", + "tests/test_models.py", + "tests/unit/area.py", + "tests/unit/test_area.py", + "validate-git-lifecycle.sh", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-48-terraform-aws-eks", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "LICENSE", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "docs/portfolio-runbook.md", + "fixtures/evidence-local-result.txt", + "project.yaml", + "terraform.tfvars.example", + "validate-p1-stream2.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-49-text-encryption-cybersecurity", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "RELEASE_EVIDENCE.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "fixtures/release-evidence/negative.txt", + "fixtures/release-evidence/positive.txt", + "main.js", + "package.json", + "project.yaml", + "test.cjs", + "validate-p2-local.sh", + "validate-release-evidence.py" + ], + "static_assets": [] + }, + { + "project": "project-50-argocd-gitops-home-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Makefile", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "RELEASE_EVIDENCE.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "fixtures/release-evidence/negative.txt", + "fixtures/release-evidence/positive.txt", + "project.yaml", + "validate-p2-local.sh", + "validate-release-evidence.py" + ], + "static_assets": [] + }, + { + "project": "project-51-opentelemetry-observability-home-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Makefile", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "RELEASE_EVIDENCE.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "app/app.py", + "app/requirements.txt", + "fixtures/evidence-local-result.txt", + "fixtures/release-evidence/negative.txt", + "fixtures/release-evidence/positive.txt", + "otel-collector.yaml", + "project.yaml", + "prometheus.yml", + "tempo.yaml", + "validate-p2-local.sh", + "validate-release-evidence.py" + ], + "static_assets": [] + }, + { + "project": "project-52-opentofu-aws-free-tier-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Makefile", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "RELEASE_EVIDENCE.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "fixtures/release-evidence/negative.txt", + "fixtures/release-evidence/positive.txt", + "project.yaml", + "terraform.tfvars.example", + "validate-p2-local.sh", + "validate-release-evidence.py" + ], + "static_assets": [] + }, + { + "project": "project-53-supply-chain-security-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "CONSUMER_CONTRACT.md", + "Makefile", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "app/package.json", + "app/server.js", + "fixtures/artifact.txt", + "fixtures/evidence-local-result.txt", + "fixtures/expiry.json", + "fixtures/identity.json", + "fixtures/positive.json", + "fixtures/tamper.json", + "project.yaml", + "scripts/local-scan.sh", + "validate-offline.py", + "validate-offline.sh", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-54-progressive-delivery-home-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "Makefile", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_HARDENING.md", + "P2_LOCAL_PILOT.md", + "README.md", + "RELEASE_EVIDENCE.md", + "START_HERE.md", + "SUPPORTED_VERSIONS.md", + "fixtures/evidence-local-result.txt", + "fixtures/release-evidence/negative.txt", + "fixtures/release-evidence/positive.txt", + "project.yaml", + "validate-p2-local.sh", + "validate-release-evidence.py" + ], + "static_assets": [] + }, + { + "project": "project-55-local-model-risk-and-provenance-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "ATTRIBUTIONS.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/approval.json", + "fixtures/dataset-manifest.json", + "fixtures/evaluation.json", + "fixtures/model-card.json", + "fixtures/model.bin", + "fixtures/provenance.json", + "fixtures/risk-register.json", + "fixtures/sbom.json", + "fixtures/verification-result.json", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-56-platform-golden-path-catalog-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "ATTRIBUTIONS.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/safe-batch-ml.json", + "fixtures/static-inference.json", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-57-policy-driven-workload-cost-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "ATTRIBUTIONS.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/plan-00.json", + "fixtures/plan-01.json", + "fixtures/plan-02.json", + "fixtures/plan-03.json", + "fixtures/plan-04.json", + "fixtures/plan-05.json", + "fixtures/plan-06.json", + "fixtures/plan-07.json", + "fixtures/plan-08.json", + "fixtures/plan-09.json", + "fixtures/plan-10.json", + "fixtures/plan-11.json", + "fixtures/plan-12.json", + "fixtures/plan-13.json", + "fixtures/plan-14.json", + "fixtures/plan-15.json", + "fixtures/plan-16.json", + "fixtures/plan-17.json", + "fixtures/plan-18.json", + "fixtures/plan-19.json", + "fixtures/policy-diff.md", + "validate-p2-local.sh" + ], + "static_assets": [] + }, + { + "project": "project-58-finops-evidence-and-unit-economics-lab", + "active_root": ".", + "quarantine_root": "quarantine", + "active_files": [ + "ATTRIBUTIONS.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", + "README.md", + "START_HERE.md", + "fixtures/budget-report.json", + "fixtures/daily-costs.csv", + "fixtures/forecast.json", + "fixtures/mapping.json", + "fixtures/recommendations.json", + "fixtures/residual-cost-closure.json", + "validate-p2-local.sh" + ], + "static_assets": [] + } + ], + "portable_static_asset_extensions": [ + ".eot", + ".gif", + ".gz", + ".ico", + ".jpeg", + ".jpg", + ".mp3", + ".mp4", + ".pdf", + ".png", + ".svg", + ".tar", + ".tgz", + ".ttf", + ".webm", + ".webp", + ".woff", + ".woff2", + ".zip" + ] +} diff --git a/docs/live-pilot-execution-pack/ACCEPTANCE_CRITERIA.md b/docs/live-pilot-execution-pack/ACCEPTANCE_CRITERIA.md new file mode 100644 index 00000000..d27c6eba --- /dev/null +++ b/docs/live-pilot-execution-pack/ACCEPTANCE_CRITERIA.md @@ -0,0 +1,17 @@ +# Acceptance Criteria — Project 53 + +**Status:** Source-only criteria; not authorization. + +The source pack is ready for human review only when local validation passes, the +exact Project 53 ref is identified, Project 52 remains unselected, and no +credential, account identifier, endpoint, executable provider command, or live +completion claim is checked in. + +A future external pilot may be considered only when the authorization record is +signed and independent review confirms the target, identity, budget, window, +monitoring, rollback, teardown, and residual-cost controls. The acceptance +record must include evidence IDs for every critical gate. + +The pilot is not accepted when authorization is incomplete, scope differs from +Project 53, an external control cannot be evidenced, teardown is unverified, or +residual resources or costs remain unresolved. diff --git a/docs/live-pilot-execution-pack/AUTHORIZATION_RECORD.md b/docs/live-pilot-execution-pack/AUTHORIZATION_RECORD.md new file mode 100644 index 00000000..0ddeb390 --- /dev/null +++ b/docs/live-pilot-execution-pack/AUTHORIZATION_RECORD.md @@ -0,0 +1,69 @@ +# Authorization Record — Project 53 + +**Document version:** 1.0.0 + +**Owner:** [enter name] + +**Pilot ID:** `project-53-supply-chain-security-lab` + +**Project 53 commit SHA:** [enter commit SHA] + +**Created:** [enter timestamp] + +**Updated:** [enter timestamp] + +**Reviewer:** [enter name] + +**Approval state:** DRAFT / IN REVIEW / APPROVED / REJECTED + +> **NOT AUTHORIZATION UNTIL SIGNED.** Blank required fields, missing independent +> review, or an external prerequisite marked unverified means **DO NOT START**. +> This record does not itself configure or grant access. + +## Required authorization facts + +| Field | Required entry | Complete? | +| --- | --- | --- | +| Repository and exact ref | [enter value] | [ ] | +| Exact Project 53 commit SHA | [enter value] | [ ] | +| Provider | [enter value] | [ ] | +| Disposable account/project/subscription name and non-secret reference | [enter value] | [ ] | +| Approved region(s) | [enter value] | [ ] | +| Disposable target boundary and intended resources | [enter value] | [ ] | +| Data classification and allowed test data | [enter value] | [ ] | +| Pilot owner | [enter name] | [ ] | +| Human operator | [enter name] | [ ] | +| Security reviewer | [enter name] | [ ] | +| Cost owner | [enter name] | [ ] | +| Approver (independent of operator) | [enter name] | [ ] | +| Start/end window and timezone | [enter value] | [ ] | +| Maximum budget | [enter value] | [ ] | +| Alert thresholds and notification route | [enter value] | [ ] | +| Short-lived identity/role and reviewed trust boundary | [enter value] | [ ] | +| Rollback trigger and last-known-good state | [enter value] | [ ] | +| Teardown deadline | [enter value] | [ ] | +| Residual-scan owner and deadline | [enter value] | [ ] | +| Exceptions and disposition | None / [enter value] | [ ] | + +## Conditions and sign-off + +The approver confirms that scope is Project 53 only, Project 52 remains +source-only, the external prerequisites are evidenced, rollback has been +source-shaped rehearsed, and teardown is separately authorized. The cost owner +acknowledges that alerts are not a hard spending guarantee. No static credential +may be stored in the repository or evidence. + +| Role | Name | Signature | Timestamp with timezone | +| --- | --- | --- | --- | +| Pilot owner | [enter name] | [enter signature] | [enter timestamp] | +| Operator | [enter name] | [enter signature] | [enter timestamp] | +| Security reviewer | [enter name] | [enter signature] | [enter timestamp] | +| Cost owner | [enter name] | [enter signature] | [enter timestamp] | +| Independent approver | [enter name] | [enter signature] | [enter timestamp] | +| Independent readiness reviewer | [enter name] | [enter signature] | [enter timestamp] | + +**Decision:** [ ] APPROVED for stated window and scope; [ ] BLOCKED; [ ] REJECTED + +**Approval evidence IDs:** [enter value] + +**Authorization expiry:** [enter timestamp] diff --git a/docs/live-pilot-execution-pack/CLOSURE_RECORD.md b/docs/live-pilot-execution-pack/CLOSURE_RECORD.md new file mode 100644 index 00000000..6b063ca8 --- /dev/null +++ b/docs/live-pilot-execution-pack/CLOSURE_RECORD.md @@ -0,0 +1,29 @@ +# Closure Record — Project 53 + +**Status:** Source-only template; not authorization and not evidence of a +completed live pilot. + +**Authorization reference:** [enter signed-record reference] + +**Pilot window:** [enter approved window] + +**Operator:** [enter name] + +**Independent closure reviewer:** [enter name] + +## Closure checks + +| Check | Evidence record ID | Reviewer outcome | +| --- | --- | --- | +| Approved scope remained unchanged | [enter ID] | [ ] | +| Stop or rollback events documented | [enter ID or N/A] | [ ] | +| Teardown completion reviewed | [enter ID] | [ ] | +| Residual inventory reviewed | [enter ID] | [ ] | +| Residual cost review scheduled or complete | [enter ID] | [ ] | +| Exceptions resolved or accepted by accountable owner | [enter ID] | [ ] | + +**Closure decision:** [ ] READY FOR ARCHIVAL; [ ] BLOCKED; [ ] ESCALATED + +The independent reviewer must not mark closure when any critical evidence is +missing, stale, unredacted, or inconsistent with authorization. This source file +does not prove execution, teardown, or closure of an external pilot. diff --git a/docs/live-pilot-execution-pack/EVIDENCE_INDEX.md b/docs/live-pilot-execution-pack/EVIDENCE_INDEX.md new file mode 100644 index 00000000..7a4690a1 --- /dev/null +++ b/docs/live-pilot-execution-pack/EVIDENCE_INDEX.md @@ -0,0 +1,19 @@ +# Evidence Index — Project 53 + +**Status:** Source-only template; no evidence is populated by this repository. + +Use one redacted record per approved checkpoint. Do not store secrets, tokens, +account identifiers, endpoints, or provider command output. + +| Checkpoint | Evidence record ID | Reviewer | Timestamp with timezone | Status | +| --- | --- | --- | --- | --- | +| Authorization verified | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Preflight completed | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Baseline inventory captured | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Approved activity observed | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Teardown verified | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Residual inventory reviewed | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Residual cost reviewed | [enter ID] | [enter name] | [enter timestamp] | [ ] | +| Closure independently reviewed | [enter ID] | [enter name] | [enter timestamp] | [ ] | + +A missing, stale, unverifiable, or unredacted record blocks closure. diff --git a/docs/live-pilot-execution-pack/EVIDENCE_RECORD_TEMPLATE.md b/docs/live-pilot-execution-pack/EVIDENCE_RECORD_TEMPLATE.md new file mode 100644 index 00000000..72a3dd23 --- /dev/null +++ b/docs/live-pilot-execution-pack/EVIDENCE_RECORD_TEMPLATE.md @@ -0,0 +1,31 @@ +# Evidence Record Template — Project 53 + +**Record ID:** [enter ID] + +**Checkpoint:** [enter approved checkpoint] + +**Timestamp with timezone:** [enter timestamp] + +**Operator:** [enter name] + +**Independent reviewer:** [enter name] + +**Authorization reference:** [enter signed-record reference] + +## Redacted observation + +Describe the approved observation without including a credential, token, account +identifier, endpoint, command transcript, or unapproved resource detail. + +[enter redacted observation] + +## Provenance and disposition + +Record the source of the observation, integrity method, redaction method, and +review outcome. Link the record from [EVIDENCE_INDEX.md](EVIDENCE_INDEX.md). + +**Provenance:** [enter value] + +**Redaction reviewed:** [ ] + +**Reviewer outcome:** [ ] ACCEPTED; [ ] BLOCKED; [ ] ESCALATED diff --git a/docs/live-pilot-execution-pack/EXTERNAL_PREREQUISITES.md b/docs/live-pilot-execution-pack/EXTERNAL_PREREQUISITES.md new file mode 100644 index 00000000..5a475dee --- /dev/null +++ b/docs/live-pilot-execution-pack/EXTERNAL_PREREQUISITES.md @@ -0,0 +1,25 @@ +# External Prerequisites — Project 53 + +**Status:** Source-only checklist; not authorization. + +A live pilot may not start until accountable humans verify every item below outside +this repository. GitHub and cloud controls remain external human verifications. +Record evidence IDs and reviewers in +[AUTHORIZATION_RECORD.md](AUTHORIZATION_RECORD.md). + +## Required external controls + +| Control | Required human evidence | +| --- | --- | +| Source protection | Protected branch, required checks, and review rule verified. | +| Environment protection | Approved environment, named approvers, and audit visibility verified. | +| Identity | Short-lived least-privilege identity and trust policy independently reviewed. | +| Target | Disposable account, project, subscription, region, and resource scope approved. | +| Cost | Budget ceiling, alerts, notifications, and cost owner approved. | +| Window | Start/end window, operator, reviewer, and escalation route approved. | +| Observability | Logs, health signals, alerts, and evidence retention route verified. | +| Teardown | Teardown owner, deadline, residual inventory, and cost review assigned. | + +If any control is missing, stale, disputed, or not independently reviewable, +mark the authorization record **BLOCKED**. This document does not configure, +grant, or verify any external control. diff --git a/docs/live-pilot-execution-pack/PILOT_RUNBOOK.md b/docs/live-pilot-execution-pack/PILOT_RUNBOOK.md new file mode 100644 index 00000000..bb84012e --- /dev/null +++ b/docs/live-pilot-execution-pack/PILOT_RUNBOOK.md @@ -0,0 +1,28 @@ +# Pilot Runbook — Project 53 + +**Status:** Human-operated template; not a deployment script. + +Use this runbook only after every external prerequisite and authorization field is +approved. Record evidence metadata, not credentials, commands, endpoints, or +account identifiers. + +## Human sequence + +1. Confirm the exact repository ref, Project 53 commit, approved target, and + approved time window match the signed authorization record. +2. Confirm the operator has the approved short-lived identity and that the + independent reviewer can observe the evidence route. +3. Capture baseline evidence for identity, cost, target inventory, and + observability before any external activity. +4. Perform only the separately approved external procedure. Stop immediately if + scope, cost, identity, target, or evidence differs from authorization. +5. Capture evidence metadata for each approved lifecycle checkpoint. +6. Follow the teardown and residual-cost checklist before the authorization + expires. +7. Complete the closure record with an independent reviewer. + +## Stop conditions + +Stop and escalate for a missing approval, changed commit, unexpected resource, +identity error, target mismatch, budget alert, missing evidence, or inability to +complete teardown. This source-only runbook contains no provider command. diff --git a/docs/live-pilot-execution-pack/PREFLIGHT_CHECKLIST.md b/docs/live-pilot-execution-pack/PREFLIGHT_CHECKLIST.md new file mode 100644 index 00000000..17792160 --- /dev/null +++ b/docs/live-pilot-execution-pack/PREFLIGHT_CHECKLIST.md @@ -0,0 +1,49 @@ +# Pre-flight Checklist — Fail-Closed Gate + +**Document version:** 1.0.0 + +**Owner:** [enter name] + +**Pilot ID:** `project-53-supply-chain-security-lab` + +**Commit:** [enter commit SHA] + +**Created/updated:** [enter created timestamp] / [enter updated timestamp] + +**Reviewer:** [enter name] + +**Approval state:** NOT AUTHORIZATION UNTIL SIGNED + +Mark `[x]` only with evidence ID and reviewer initials. **One unchecked critical +item blocks START.** All GitHub, provider, identity, budget, and monitoring +gates are **external** human verifications; this source-only checklist neither +configures nor proves them. + +| Gate | Critical check | Evidence ID | [x]/Initials | +| --- | --- | --- | --- | +| Governance | Signed authorization, independent approver, named owners, approved window/timezone | | | +| Source integrity | Project 53 exact SHA/ref frozen; Project 52 explicitly not selected | | | +| GitHub | Narrow token permissions, immutable action references, branch/environment protections, audit access | | | +| Identity | Short-lived least-privilege identity, reviewed trust, operator/approver separation, no static key | | | +| Network/data | Provider/region/target, exposure, encryption/logging, allowed data, retention decision | | | +| Cost | Maximum budget, alert thresholds/routes, tags/labels, spending authority and monitoring | | | +| Safety | Disposable target, quotas, incident contact, no unapproved scope or command | | | +| Observability | Health/log/permission/alert access tested and baseline recorded | | | +| Rollback | Last-known-good state and human sequence source-shaped rehearsed; trigger and owner named | | | +| Teardown | Teardown owner, deadline, inventory procedure, residual-scan owner, billing review timing | | | + +**Two-person review:** Reviewer 1 [enter name] [enter date/time]; Reviewer 2 +[enter name] [enter date/time] + +**Gate decision:** [ ] PASS; [ ] BLOCKED; [ ] EXCEPTION (must be approved and +linked) + +**START authorization signature:** [enter signature] + +**Timestamp:** [enter timestamp] + +## Mandatory stop rule + +If any critical check is unchecked, disputed, stale, or not independently +reviewable, do not start, do not widen scope, and escalate to the approver. This +checklist proves document review only; it does not prove live controls. diff --git a/docs/live-pilot-execution-pack/RACI.md b/docs/live-pilot-execution-pack/RACI.md new file mode 100644 index 00000000..9313b793 --- /dev/null +++ b/docs/live-pilot-execution-pack/RACI.md @@ -0,0 +1,16 @@ +# RACI — Project 53 L2 Pilot + +**Status:** Source-only accountability template. + +| Activity | Responsible | Accountable | Consulted | Informed | +| --- | --- | --- | --- | --- | +| Authorize scope, target, budget, and window | [enter name] | [enter name] | Security and cost owners | Stakeholders | +| Verify source ref and preflight evidence | [enter name] | [enter name] | Independent reviewer | Stakeholders | +| Operate approved external procedure | [enter name] | [enter name] | Security reviewer | Cost owner | +| Observe and retain redacted evidence | [enter name] | [enter name] | Independent reviewer | Stakeholders | +| Stop or roll back on a trigger | [enter name] | [enter name] | Security and cost owners | Stakeholders | +| Verify teardown and residual state | [enter name] | [enter name] | Independent reviewer | Stakeholders | +| Approve closure | [enter name] | [enter name] | Security and cost owners | Stakeholders | + +No person may mark themselves independent when acting as the operator for the +same pilot decision. diff --git a/docs/live-pilot-execution-pack/README.md b/docs/live-pilot-execution-pack/README.md new file mode 100644 index 00000000..b7d6b4c3 --- /dev/null +++ b/docs/live-pilot-execution-pack/README.md @@ -0,0 +1,56 @@ +# Project 53 L2 Live Pilot Execution Pack + +**Document version:** 1.0.0 + +**Owner:** [enter name] + +**Pilot ID:** `project-53-supply-chain-security-lab` + +**Project 53 commit SHA:** [enter commit SHA] + +**Created (ISO 8601 with timezone):** [enter timestamp] + +**Updated (ISO 8601 with timezone):** [enter timestamp] + +**Reviewer:** [enter name] + +**Approval state:** DRAFT — NOT AUTHORIZATION UNTIL SIGNED + +> **Boundary:** This is a source-only governance pack. It does not establish +> authorization, GitHub configuration, cloud access, deployment, rollback, +> teardown, or residual-cost clearance. No live operation may begin from this +> repository alone. + +## Scope + +Project 53 is the sole selected pilot. Project 52 +(`project-52-opentofu-aws-free-tier-lab`) is retained as a reusable source-only +pattern. It must not be selected, deployed, or treated as evidence for this +pilot. Any drift in project, repository, ref, commit, +provider, region, account, identity, or resource scope is a stop condition. + +## Use sequence + +Complete [EXTERNAL_PREREQUISITES.md](EXTERNAL_PREREQUISITES.md), then +[AUTHORIZATION_RECORD.md](AUTHORIZATION_RECORD.md), +[ACCEPTANCE_CRITERIA.md](ACCEPTANCE_CRITERIA.md), and +[PREFLIGHT_CHECKLIST.md](PREFLIGHT_CHECKLIST.md). During a separately approved +window, a human operator follows [PILOT_RUNBOOK.md](PILOT_RUNBOOK.md) and +records lifecycle evidence using [EVIDENCE_INDEX.md](EVIDENCE_INDEX.md) and +[EVIDENCE_RECORD_TEMPLATE.md](EVIDENCE_RECORD_TEMPLATE.md). Use +[RISK_ROLLBACK_GUIDANCE.md](RISK_ROLLBACK_GUIDANCE.md) for decisions, +[TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md](TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md) +for closure, [RACI.md](RACI.md) for accountability, and +[CLOSURE_RECORD.md](CLOSURE_RECORD.md) for final review. + +## Source-only operating rules + +Do not add credentials, account identifiers, real endpoints, tokens, secrets, +executable provider commands, deployment scripts, teardown scripts, containers, +or network-dependent validators to this pack. Record a human-executed provider +or GitHub path as evidence metadata only. A screenshot without date, target, +reviewer, and provenance is insufficient. Local validation proves only the +checked-in source contract; it cannot prove external controls. + +Provider-specific behavior, pricing, quotas, and policy must be reverified by +accountable owners immediately before any future pilot. diff --git a/docs/live-pilot-execution-pack/RISK_ROLLBACK_GUIDANCE.md b/docs/live-pilot-execution-pack/RISK_ROLLBACK_GUIDANCE.md new file mode 100644 index 00000000..b7ed39aa --- /dev/null +++ b/docs/live-pilot-execution-pack/RISK_ROLLBACK_GUIDANCE.md @@ -0,0 +1,25 @@ +# Risk and Rollback Guidance — Project 53 + +**Status:** Human decision guide; not a rollback script. + +## Stop and escalate immediately + +Stop the approved activity and escalate to the accountable approver if the +identity, target, region, commit, resource scope, budget signal, evidence route, +or teardown feasibility differs from authorization. The escalation procedure must +record the accountable owner and follow-up decision. Also stop for unexpected +public exposure, persistent data, shared dependency, or missing reviewer access. + +## Human rollback decision + +The named operator follows the separately approved external rollback procedure. +The operator records only redacted evidence metadata. The independent reviewer +confirms the target inventory and residual-cost checklist are complete before +closure. + +## Required decision record + +Record the trigger, timestamp, accountable decision-maker, reviewer, redacted +observation, rollback or stop disposition, and follow-up owner in the +[Closure Record](CLOSURE_RECORD.md). This repository provides no provider +command and cannot prove that external rollback occurred. diff --git a/docs/live-pilot-execution-pack/TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md b/docs/live-pilot-execution-pack/TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md new file mode 100644 index 00000000..2aac0253 --- /dev/null +++ b/docs/live-pilot-execution-pack/TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md @@ -0,0 +1,17 @@ +# Teardown and Residual Cost Checklist — Project 53 + +**Status:** Human-operated closure template; not an executable teardown script. + +| Closure check | Owner | Evidence record ID | Complete? | +| --- | --- | --- | --- | +| Approved activity stopped before authorization expiry | [enter name] | [enter ID] | [ ] | +| Teardown verification within the approved boundary | [enter name] | [enter ID] | [ ] | +| Independent target inventory completed | [enter name] | [enter ID] | [ ] | +| Shared, persistent, public, or unapproved resources absent | [enter name] | [enter ID] | [ ] | +| Budget and cost data reviewed after teardown | [enter name] | [enter ID] | [ ] | +| Residual charge review date assigned | [enter name] | [enter ID] | [ ] | +| Any exception escalated and closed | [enter name] | [enter ID] | [ ] | + +Do not close the pilot when teardown, inventory, residual-resource review, or +cost review is missing. This checklist neither executes teardown nor proves +external billing state. diff --git a/docs/reviews/classroom-evidence/2026-08-24_classroom-evidence-RE-REVIEW-READY.md b/docs/reviews/classroom-evidence/2026-08-24_classroom-evidence-RE-REVIEW-READY.md new file mode 100644 index 00000000..46842b4d --- /dev/null +++ b/docs/reviews/classroom-evidence/2026-08-24_classroom-evidence-RE-REVIEW-READY.md @@ -0,0 +1,34 @@ +# Classroom Evidence Blind Re-Review — READY + +## Decision + +The frozen post-implementation packet is **ready** for the classroom-evidence re-review. The review +covered the 54 evidence-bearing project roots listed in the canonical matrix. + +## Offline verification + +| Check | Result | +| --- | --- | +| Evidence-bearing project roots | 54 found, numbered project-01 through project-54 | +| Per-project worksheet, evidence contract, and local-pilot record | 54 of 54 present | +| Active Markdown/document relative links | 0 unresolved links | +| Active links entering `quarantine/` | 0 | +| Project-local fixture and validator references | No missing referenced paths found | +| Per-project `validate-p2-local.sh` checks | 54 of 54 passed | +| Canonical evidence matrix | 54 rows resolved | +| Matrix/source-record checker | Passed: canonical 54-row matrix and 54 source-only records | +| Stream B regression check | Passed; negative fixture rejected by contract | + +## Evidence and boundary review + +The classroom packet consistently identifies project-local active paths and fixture-backed, local- +first validation. The reviewed records distinguish student-facing local work from instructor-only or +quarantined historical material, and they state that cloud deployment or mutation is not established +by the local evidence. Validators and fixtures substantiate the claimed local result for every +matrix row. No active document link, classroom record, evidence contract, or local-pilot record was +found to route students into `quarantine/` or to claim a cloud result from a local-only check. + +## Conclusion + +No remaining critical or high classroom-evidence blockers were identified in the frozen post-implementation +packet. diff --git a/docs/reviews/devsecops-mlops-modernization/2026-08-24_devsecops-mlops-modernization-RE-REVIEW-READY.md b/docs/reviews/devsecops-mlops-modernization/2026-08-24_devsecops-mlops-modernization-RE-REVIEW-READY.md new file mode 100644 index 00000000..6c2510b3 --- /dev/null +++ b/docs/reviews/devsecops-mlops-modernization/2026-08-24_devsecops-mlops-modernization-RE-REVIEW-READY.md @@ -0,0 +1,112 @@ +# DevSecOps–MLOps Modernization Blind Re-Review + +**Review date:** 2026-08-24 UTC +**Scope:** Frozen post-implementation source packet only: +`devsecops_mlops_modernization_rereviewer_packet.tar.gz` +**Decision:** **READY** + +## Executive decision + +The packet is ready for retention as an active, local-first DevSecOps–MLOps portfolio repository. +The independent re-review found all **54 canonical project roots** present and covered by the +packet’s active contract. Every root has the required project metadata, classroom boundary, evidence +record, hardening record, local-pilot record, and executable local validator. Legacy or hosted-only +material is retained behind explicit `quarantine/` boundaries and was excluded from the active +assessment. + +No material modernization blocker remains. The packet does not claim that offline validation proves +cloud deployment, production approval, runtime capacity, or successful external integrations; that +limitation is explicit and is appropriate because cloud deployment is an optional demonstration +rather than a prerequisite for the student-safe route. + +| Decision dimension | Blind re-review result | Basis | +| --- | ---: | --- | +| Canonical roots | Pass: 54/54 | Root inventory and packet baseline | +| Required project contracts | Pass: 54/54 | Deterministic baseline validator | +| Executable local validators | Pass: 54/54 | Deterministic baseline validator | +| Quarantine boundaries | Pass | Active scan excludes `quarantine/`; retention boundary verified | +| Offline release checks | Pass: 6/6 | Canonical required-check dispatcher | +| P0 policy fixtures | Pass | Positive and negative fixture behavior verified | +| Classroom contracts | Pass: 54/54 | Source paths, sections, validators, and blocked-release boundaries verified | +| Evidence-bearing release inventory | Pass: 17 projects | Release inventory check | +| P1 document consistency | Pass: 8/8 | Referenced validators resolve | +| Parking decisions | None | No active project met the packet’s parking condition | +| Critical findings | **0** | No release-blocking gap found | +| High findings | **0** | No material high-severity gap found | + +## Evidence reviewed + +The re-review was performed without relying on prior reviews, action plans, implementation reports, +or conversation history. The frozen packet was extracted into a disposable review workspace and +independently inventoried. The root-level inventory returned exactly 54 directories named +`project-*`, matching the stated scope. Active files were scanned while pruning project-local +`quarantine/` directories. The packet-level readme, local-first baseline, security baseline index, +CI/CD, Dockerfile, Kubernetes, Terraform, and secrets guidance, release manifest, workflows, +validators, and project-facing P2 documents were inspected. + +The deterministic offline checks completed successfully: + +```text +LOCAL-FIRST BASELINE PASS: 54 active project roots, required contracts, executable validators, and retention boundaries verified +P0 FIXTURE TEST PASS: clean passes and negative fails as expected +P2 CLASSROOM CONTRACT PASS: 54 project contracts have resolved source paths, required sections, validators, and blocked-release boundaries. +RELEASE INVENTORY PASS: 17 evidence-bearing projects covered +P1 CONSISTENCY PASS: 8 documents reference existing validators +Quality gate passed: no failures found. +CANONICAL VALIDATION PASS: scope=all checks=6 +``` + +The quality gate correctly reported that optional PyYAML and test modules were not required by the +deterministic offline route. This is fail-closed behavior rather than a hidden dependency: the +preflight reports unavailable optional modules, skips only checks that require them, and still +produced a passing source-quality result. No cloud, container, registry, package-index, credential, +or destructive command was used for this re-review. + +## Standards cross-check + +The active design is consistent with current authoritative practice. NIST SSDF provides the secure- +development baseline for reducing vulnerabilities and protecting software integrity [1]. NIST’s SBOM +guidance treats software inventories as a mechanism for transparency, provenance, and faster +vulnerability response [2]. SLSA’s current provenance requirements emphasize trusted build-generated +provenance and verification rather than provenance production alone [3] [4]. OWASP’s CI/CD risk +guidance supports treating pipeline identity, dependencies, secrets, and artifact integrity as +explicit controls [5]. + +The packet’s local route is also consistent with contemporary platform and operations practice: +declarative project metadata and Git-controlled desired state align with OpenGitOps principles [6], +while the repository’s dedicated observability project and telemetry guidance provide an appropriate +topic-specific path rather than pretending that every beginner project needs a production monitoring +stack. For AI-relevant material, the packet’s chatbot boundary, evaluation-oriented evidence, secret +hygiene, and explicit limitations are compatible with NIST’s Generative AI Profile, which frames +risk management across the AI lifecycle and calls for trustworthy design, development, use, and +evaluation [7]. + +| Practice area | Active packet treatment | Re-review judgment | +| --- | --- | --- | +| Secure development | Shared security baselines, source checks, syntax checks, local quality gate, and explicit release contract | Adequate for a local-first educational portfolio | +| Secrets | Secret-pattern detection, example-config conventions, and student guidance to keep credentials local | Adequate; hosted credentials are not required for acceptance | +| IaC and policy | Terraform/OpenTofu project coverage, validation contracts, hardening guidance, and fail-closed boundaries | Adequate and appropriately scoped | +| Containers and Kubernetes | Dockerfile/Kubernetes baselines, project-specific hardening, scanning-oriented labs, and local pilots | Adequate; cloud readiness is explicitly out of scope for offline acceptance | +| Supply chain | Release inventory, policy fixtures, provenance-oriented guidance, and explicit blocked-release status | Adequate for source-packet maturity; no unjustified production claim | +| GitOps and delivery | Argo CD/GitOps projects, declarative manifests, CI/CD boundaries, and local validation | Adequate across the project portfolio | +| Observability | Dedicated monitoring/OpenTelemetry projects and documented limits of local evidence | Adequate and topic-appropriate | +| MLOps/LLMOps and responsible AI | AI project boundary, local evidence path, evaluation and safety-oriented documentation, and no claim of production model assurance | Adequate for the relevant scope; no AI project requires cloud access to pass local acceptance | +| Local-first acceptance | Committed fixtures/mocks, path-safe validators, no credentials, no network requirement, and explicit non-claims | Strong; this is the packet’s principal maturity improvement | + +## Retention and parking + +All 54 project roots remain retained as active projects. No project is parked. This is not a blanket +exemption: the active packet demonstrates a concrete retention basis for each root through the +common contract and validator matrix, while legacy material remains quarantined and excluded. The +decision also respects the stated rule that absence of cloud deployment is not a defect. + +## Final assessment + +The source packet now achieves practical local-first DevSecOps–MLOps maturity for its stated +educational and portfolio purpose. It provides safe and valid bridges to hosted technologies without +making those technologies prerequisites, deterministic acceptance without credentials or network +access, fail-closed release boundaries, explicit supply-chain and secrets treatment, project- +appropriate policy and observability coverage, and responsible handling of the AI-relevant project. +The result is **READY**, with zero critical and zero high remaining modernization findings. + +## References diff --git a/docs/reviews/emerging-tracks/2026-08-24_emerging-tracks-mlops-platform-finops-RE-REVIEW-READY.md b/docs/reviews/emerging-tracks/2026-08-24_emerging-tracks-mlops-platform-finops-RE-REVIEW-READY.md new file mode 100644 index 00000000..4c9e774f --- /dev/null +++ b/docs/reviews/emerging-tracks/2026-08-24_emerging-tracks-mlops-platform-finops-RE-REVIEW-READY.md @@ -0,0 +1,96 @@ +# Emerging Tracks (MLOps–Platform–FinOps) — Final Blind Re-Review + +**Review date:** 2026-08-24 + +**Decision:** **READY** + +**Scope:** Frozen post-remediation packet `emerging_tracks_final_rereviewer_packet.tar.gz`, assessed +without prior plans, handoffs, or reviews. + +## Decision basis + +The packet provides meaningful, independently usable, local-first, synthetic, non-production +additions for Projects 55–58. Each project has a readme, classroom and local-rehearsal records, +attribution record, deterministic fixtures, a documented shell validator, and machine-readable +evidence. The project materials explicitly prohibit live pilots, deployment, cloud access, +production changes, provider CLIs and SDKs, credentials, network access, containers, teardown, and +live-service behavior. The top-level validator passed the manifest-root and L2/source-only boundary +checks. + +## Validation results + +All four documented project validators were executed locally with `sh validate-p2-local.sh`; the +packet-level validator was executed with `python3 scripts/validate-emerging-tracks-packet.py`. Every +validator returned exit code 0 and `PASS`. + +### Project 55 — Local model risk and provenance + +The validator covers provenance, model cards, dataset manifests, evaluation, risk +registers, SBOMs, approvals, and verification. It computed accuracy `0.91` and +recomputed SHA-256 as `bc0cedf681bcc6cd384c7a73c917f7c91b45f705957995b970fd3d90a85d82ab`. +A tampered model hash and incomplete approval were rejected. Machine-readable +evidence is present at `evidence/validator-result.json` with the command, +interpreter, fixtures, outcome, computed values, and negative coverage. + +### Project 56 — Platform golden-path catalog + +The validator covers two synthetic catalog templates with owner, dependencies, +version/lifecycle, TTL, and deployment-prohibition controls. It computed `2` +templates and `0` unsafe templates. Unsafe templates and templates without an +owner were rejected. Evidence records include the command, interpreter, fixture +set, outcome, computed counts, and negative coverage. + +### Project 57 — Policy-driven workload cost + +The validator evaluates twenty deterministic workload plans for ownership, +request metadata, expiry/lifetime, resource, cost-center, budget, and prohibited +dependency flags. It computed `20` plans, with `12` allowed and `8` denied. +Public, persistent, expired or over-lifetime, and missing-owner plans were +denied. Evidence records include the command, interpreter, fixture set, outcome, +computed counts, and negative coverage. + +### Project 58 — FinOps evidence and unit economics + +The validator covers ledger reconciliation, allocation gaps, forecast/budget +variance, unit-economics support, recommendation ownership/dates, and closure +evidence. It computed ledger total `63.0`, `1` unallocated row, budget variance +`1937.0`, and `1` recommendation. Allocation gaps, budget overruns, missing +owner/due dates, and unclosed evidence fail closed. Evidence records include the +command, interpreter, fixture set, outcome, computed metrics, and negative +coverage. + +The validators compute outcomes from checked-in JSON and CSV fixtures rather than merely checking +static expected strings. Their assertions fail closed on malformed, missing, contradictory, unsafe, +incomplete, or invalid records as documented by the project readmes. The captured evidence records +identify the interpreter as `/usr/bin/python3` and retain the fixture sets used for each run. + +## Manifest and project-selection integrity + +The active integrity manifest explicitly includes Projects 55, 56, 57, and 58 with their exact +active file lists and no static assets. It retains Project 53 as the sole selected L2 pilot and +Project 52 as unselected reusable material. Project 54 remains distinct and no project-number +collision exists with Project 55–58. The packet-level validator reported: `PASS emerging packet: +manifest roots and L2/source-only boundaries verified`. + +The active manifest includes the expected project roots and separates the new projects from the +existing L2/source-only material. The attribution records also state that Project 53 policy is not +used as code or text in Projects 55–58 and that the new project text, schemas, code, fixtures, and +evidence formats are locally authored synthetic material. + +## Attribution and source-only safety + +Each new project includes `ATTRIBUTIONS.md` with the access date `2026-08-24`, primary source URLs, +terms/license notes, adapted-material statements, and local-modification declarations. The records +distinguish consulted ideas from copied expressive material and conclude that no upstream code, +schema, text, sample data, icon, or fixture was copied. The packet contains no live +cloud/provider/container/credential execution path; prohibited technologies and operational actions +appear only in explicit safety boundaries or synthetic fixture fields such as +`deployment_prohibited`, not as runnable integrations. + +## Final finding + +No critical or high-severity blocker remains within the frozen packet. The required Emerging Tracks +re-review is **READY**. + +This review is based solely on the frozen packet supplied for this blind re-review; no external +sources or cloud accounts were accessed. diff --git a/docs/reviews/l2-cloud-pilot/2026-08-24_l2-cloud-pilot-RE-REVIEW-READY.md b/docs/reviews/l2-cloud-pilot/2026-08-24_l2-cloud-pilot-RE-REVIEW-READY.md new file mode 100644 index 00000000..5cac27f9 --- /dev/null +++ b/docs/reviews/l2-cloud-pilot/2026-08-24_l2-cloud-pilot-RE-REVIEW-READY.md @@ -0,0 +1,58 @@ +# L2 Cloud-Pilot Source Readiness Re-Review + +**Review date:** 2026-08-24 +**Decision:** **READY** +**Scope:** Frozen post-remediation source packet only. This is an L2 source-readiness decision, not +live cloud readiness or approval for a cloud rehearsal. + +## Independent decision + +The frozen packet is **READY for L2 source readiness**. The repository contains the complete +54-project portfolio and its local validators pass. Project 53 (`project-53-supply-chain-security- +lab`) is the sole selected pilot; Project 52 (`project-52-opentofu-aws-free-tier-lab`) is retained +as reusable source-only material and is not selected as the pilot. + +The active optional pilot workflows are explicit source-only contracts. They use immutable commit- +pinned checkout actions, pinned `ubuntu-24.04` runners, and only `contents: read` permissions. The +workflow contracts invoke deterministic local fixture/source validators and contain no OIDC token +permission. The packet’s active-path checks exclude quarantine and fixture-only negative material +from active execution surfaces. + +## Review coverage and results + +| Control area | Independent result | Basis in frozen packet | +| --- | --- | --- | +| Portfolio scope | Pass | Canonical portfolio manifest and validator cover exactly 54 project roots. | +| Pilot selection | Pass | Project 53 is designated as the sole selected pilot; Project 52 is documented as reusable source-only material. | +| Optional workflow contract | Pass | Active pilot workflows declare source-only/fixture-only behavior, use `ubuntu-24.04`, pin checkout by commit, and grant `contents: read` only. | +| OIDC and permissions | Pass | No `id-token` permission is present; no write permissions are granted by the pilot workflows. | +| Provider and remote execution | Pass | Validators reject provider/cloud login, remote endpoints, registry login, and cloud execution surfaces. | +| Mutation and teardown | Pass | Validators reject IaC apply/destroy, Kubernetes mutation, teardown, and related release operations in active contract surfaces. | +| Secrets and literals | Pass | Validators reject static credential patterns, account identifiers, endpoint literals, and unbounded references. | +| Authorization fixtures | Pass | Valid authorization fixtures pass; malformed, expired, unauthorized, tampered, and incomplete negative fixtures are exercised and rejected. | +| Evidence fixtures | Pass | Valid evidence fixtures pass; malformed, expired, tampered, and incomplete negative fixtures are exercised and rejected. | +| External-control claims | Pass | Governance documentation distinguishes local source evidence from external GitHub/cloud controls and does not claim those controls are configured. | +| Live rehearsal boundary | Pass | Documentation and workflow text state that validation is local/offline and does not establish live cloud readiness. | + +## Validator execution + +The packet’s two canonical local checks completed successfully without provider CLIs, cloud-account +access, credentials, containers, or network-dependent execution: + +```text +L2 cloud-pilot source validation: PASS +L2 cloud-pilot source validation: PASS +L2 source contract validation: PASS +``` + +The source inspection also confirmed that Project 53’s active cloud-pilot workflow uses +`workflow_dispatch` and `pull_request`, `permissions: contents: read`, `runs-on: ubuntu-24.04`, an +immutable checkout reference, and local Python validation only. Project 52 contains the same source- +only contract pattern while remaining reusable material rather than the selected pilot. + +## Residual findings + +No critical or high L2 source-readiness blockers remain. No live cloud rehearsal was attempted or +required, because it is outside this review scope. + +## References diff --git a/docs/reviews/l2-live-pilot-execution-pack/2026-08-24_l2-live-pilot-execution-pack-RE-REVIEW-READY.md b/docs/reviews/l2-live-pilot-execution-pack/2026-08-24_l2-live-pilot-execution-pack-RE-REVIEW-READY.md new file mode 100644 index 00000000..4973e5bd --- /dev/null +++ b/docs/reviews/l2-live-pilot-execution-pack/2026-08-24_l2-live-pilot-execution-pack-RE-REVIEW-READY.md @@ -0,0 +1,61 @@ +# L2 Live Pilot Execution Pack — Blind Re-Review Ready Report + +**Review date:** 2026-08-24 +**Scope:** Frozen final post-remediation packet only +**Decision:** **READY** for source-only human operation +**Selected pilot:** Project 53 — `project-53-supply-chain-security-lab` +**Reusable source material only:** Project 52 — `project-52-opentofu-aws-free-tier-lab` + +## Executive decision + +The L2 Live Pilot Execution Pack is ready as a **complete, human-operable, source-only pack** for +Project 53 as the sole selected pilot. Project 52 is explicitly bounded as reusable source material +and is not presented as a second selected pilot. No live execution is expected or claimed by this +review. + +The pack is suitable for a human operator to prepare, independently review, authorize through the +documented gates, and later record evidence for a live pilot without treating source inspection as +proof that any provider-side action occurred. Its controls are fail-closed: missing authorization, +identity evidence, external prerequisites, expected-resource review, runtime evidence, or +teardown/cost closure stops progression. + +## Blind review coverage and results + +| Control area | Result | Basis in frozen packet | +| --- | --- | --- | +| Required document set | Pass | All twelve required Markdown documents are present and non-empty. | +| Document integrity | Pass | Each required document has exactly one top-level H1 and one complete body; no trailing whitespace was detected. | +| Navigation | Pass | The dedicated validator resolved all relative internal Markdown links. | +| Ownership and state | Pass | Authorization, ownership, revision, approval, reviewer, budget, and window fields are represented in the pack templates and records. | +| Sequential runbook | Pass | The runbook specifies actors, inputs, evidence, decision/stop conditions, and teardown. | +| Fail-closed preflight | Pass | Preflight explicitly requires fail-closed handling and checks external prerequisites and identity boundaries. | +| Evidence and provenance | Pass | Evidence index and record template cover authorization, provenance, reviewer, redaction, teardown, and residual-cost records. | +| Teardown and residual cost | Pass | The dedicated checklist requires inventory reconciliation, residual-cost review, and closure. | +| Governance | Pass | RACI identifies accountable, operator, and reviewer responsibilities; risk/rollback guidance covers rollback, stop, and escalation. | +| External gates | Pass | External prerequisites consolidate GitHub, cloud, and other external gates without asserting that they are configured or passed. | +| Source-only acceptance and closure | Pass | Acceptance and closure documents distinguish readiness from authorization and live completion. | +| Safety boundary | Pass | Pack text contains no real credential, account identifier, endpoint, executable cloud command, unsupported external-configuration claim, or claim that a live action occurred. | +| Project boundary | Pass | Project 53 is the sole selected pilot; Project 52 is retained only as reusable source-only material. | +| Official references | Pass | The packet includes current official references for secure development, protected branches, OIDC/deployment hardening, provenance, GitOps, and AI risk governance. | + +## Verification performed + +The repository’s dedicated offline validator completed successfully with `L2 Live Pilot Execution +Pack validation: PASS`. The validator checked the required twelve files, required semantic markers, +one-H1/body integrity, trailing whitespace, relative internal links, the Project 52 reusable-pattern +boundary, and unsupported authorization/completion claims. + +A separate blind inspection of the frozen packet and its supporting qualification material confirmed +that the pack’s source-only posture is consistent with the qualification guidance: local/source +validation does not prove provider success, and a deployment is incomplete until teardown or an +explicitly governed retention decision is documented. The absence of live execution evidence is +therefore treated as expected rather than as a defect. + +## Final operating boundary + +This decision approves **pack readiness only**. It does not authorize cloud activity, establish +provider configuration, provide credentials or account data, or claim deployment, runtime success, +teardown success, or cost closure. Any future live pilot must begin at the documented preflight and +authorization gates and must stop when a required condition or evidence item is absent. + +## References diff --git a/docs/reviews/portfolio-status/2026-08-24_portfolio-source-level-final-status.md b/docs/reviews/portfolio-status/2026-08-24_portfolio-source-level-final-status.md new file mode 100644 index 00000000..1f1d07a1 --- /dev/null +++ b/docs/reviews/portfolio-status/2026-08-24_portfolio-source-level-final-status.md @@ -0,0 +1,80 @@ +# Final Source-Level Status Decision + +**Portfolio:** DevCloudNinjas / DevOps-Projects +**Decision date:** 24 August 2026 +**Decision scope:** Checked-in source, local validation contracts, and retained readiness evidence only +**Decision:** **All planned source-level work is complete.** + +> This decision records the portfolio’s intended local-first educational state. It covers the original modernization, the L2 governed cloud-pilot source preparation, the L2 Live Pilot Execution Pack, and the Emerging Tracks for MLOps, Platform Engineering, and FinOps. It does **not** authorize or claim a live cloud execution. + +## Executive summary + +| Level or track | Status | Source-level meaning | +| --- | --- | --- | +| **L1 — Local classroom-ready** | **READY** | The original 54-project curriculum plus Projects 55–58 provides local, validated teaching material. | +| **L2 — Governed cloud-pilot source readiness** | **READY** | Project 53 remains the sole selected future pilot; source contracts and safety boundaries are retained. | +| **L2 — Live Pilot Execution Pack** | **READY** | A complete human-operable, source-only execution pack exists for Project 53. | +| **Emerging Tracks** | **READY** | Projects 55–58 add validated local MLOps, Platform Engineering, policy-driven cost control, and FinOps coverage. | +| **Live cloud pilot** | **Not started** | Correctly blocked pending external controls, named human approval, controlled execution, and post-run closure evidence. | + +The portfolio is ready for its intended educational use as a local-first DevSecOps curriculum. No +additional source-modernization or content-addition loop is required for the current approved scope. +A new source loop should begin only when teaching requirements, the selected pilot, applicable +standards, or public site structure materially changes. + +## Completed source work + +The core portfolio has been modernized as a local-first DevSecOps curriculum. Its active teaching +path is separated from quarantined material, local validation is deterministic, and classroom +evidence plus student/instructor separation are retained in the source packet. + +The L2 preparation preserves **Project 53** as the sole selected future pilot and **Project 52** as +reusable source-only material. The associated execution pack is documentation and source-contract +based; it creates no provider state and grants no authorization for an operator to deploy. + +| Project | Emerging-track focus | Readiness basis | +| --- | --- | --- | +| **55** | Local model risk and provenance | Synthetic model, dataset, evaluation, risk, SBOM, approval, provenance, and hash-verification evidence. | +| **56** | Platform golden-path catalog | Local workload metadata and catalog contracts without a hosted platform service. | +| **57** | Policy-driven workload cost control | Deterministic provider-neutral safety, ownership, TTL, and cost-intent evaluation. | +| **58** | FinOps evidence and unit economics | Synthetic allocation, budget variance, recommendations, unit economics, and residual-closure evidence. | + +Each emerging-track root includes classroom, evidence, and local-pilot records; a deterministic +local validator with negative/fail-closed coverage; attribution; and machine-readable validator +evidence. The implementation is strictly local-first and source-only. + +## Current public description + +> **A classroom-ready, local-first DevSecOps portfolio with validated offline labs, modern security boundaries, Emerging MLOps, Platform Engineering, and FinOps tracks, and optional cloud extensions that require separate approval.** + +This description must not be shortened to “production ready,” “cloud-release ready,” or “live-pilot +approved.” Those claims require evidence that is deliberately outside the repository’s source-level +scope. + +## Human and external work remaining + +A live cloud pilot is optional. It may proceed only after accountable humans complete the external +prerequisites below. + +| External gate | Required evidence before any live action | +| --- | --- | +| Disposable target | Approved cloud account or subscription, bounded region, and resource allow-list. | +| Source-control governance | Protected branches, required checks, environment controls, and named reviewers. | +| Identity | Short-lived OIDC federation with least privilege; no long-lived repository secret. | +| Financial governance | Named budget owner, approved ceiling, alert route, and cost-control plan. | +| Authorization | Signed Cloud Pilot Authorization Record with named approver, operator, and teardown owner. | +| Run control | Approved run window, monitoring route, stop conditions, and rollback decision authority. | +| Closure | Verified teardown plus residual-resource and residual-cost evidence after the controlled run. | + +These gates are not source-code tasks. They must not be represented as completed until real external evidence +exists. + +## Maintenance decision + +No additional source-code content loop is required at this time. A new review or addition loop is +appropriate only when a materially new teaching requirement appears, another live pilot is selected, +a relevant standard changes significantly, or the public site reveals a clear structural gap. + +**Approved source-level state as of 24 August 2026:** the portfolio is ready for packaging and +presentation on a public site. Any live-cloud pilot remains a separately governed external +activity. diff --git a/docs/reviews/student-instructor-separation/2026-08-24_student-instructor-separation-REVIEW-READY.md b/docs/reviews/student-instructor-separation/2026-08-24_student-instructor-separation-REVIEW-READY.md new file mode 100644 index 00000000..410c82e7 --- /dev/null +++ b/docs/reviews/student-instructor-separation/2026-08-24_student-instructor-separation-REVIEW-READY.md @@ -0,0 +1,55 @@ +# Student/Instructor Separation Review — READY + +## Decision + +**Verdict: READY.** The frozen source packet supports a clear student/instructor +boundary across all 54 project roots. Active student-facing materials route +learners to local-first, offline, read-only, or plan-only workflows. They do not +provide actionable paths into instructor-only or quarantined material. + +## Scope and offline evidence + +| Check | Result | +| --- | ---: | +| Project roots inventoried | 54 / 54 | +| Active `P2_CLASSROOM.md` documents | 54 / 54 | +| Active `P2_EVIDENCE.md` documents | 54 / 54 | +| Active `P2_LOCAL_PILOT.md` documents | 54 / 54 | +| Active local P2 validators passing | 54 / 54 | +| Active symlinks reaching privileged or quarantined content | 0 | +| Student-facing contract files with actionable `quarantine/` references | 0 | +| Student-facing contract files with answer-key, staff-only, or teacher-only leakage | 0 | + +The review was performed against the extracted packet only. No cloud activity, +credentials, deployment, remote installation, or destructive operation was used. + +## Boundary findings + +The active readmes, classroom contracts, evidence contracts, and local-pilot +documents consistently identify the student route as local-first and offline. +Instructor-only material is described as non-student reference material rather +than as a learner execution path. Where an active `INSTRUCTOR_BOUNDARY.md` +exists, it places historical deployment, CI, provider, registry, and +remote-repository material below `quarantine/legacy-source/`. It instructs the +student path not to execute or reconstruct that material. + +The student-facing contract scan found no actionable links to `quarantine/`, no +answer keys, and no staff-only or teacher-only instructions. References to +quarantine or instructor-only material in active documents are boundary +statements that prohibit student access or explain the exclusion. They do not +direct learners to use those materials. The five active instructor-boundary +documents were likewise explicit about their intended audience and the +offline/read-only student route. + +All 54 active `validate-p2-local.sh` validators passed when exercised from their +active project roots. Validators and containment checks make the separation +testable locally, including active-path scope, manifest-backed files, quarantine +exclusion, unsafe mutation/provider/remote-target rejection, and local evidence +requirements. Legacy validators located inside quarantine were not treated as +active student validators. Their expected missing-root failures therefore do not +weaken the active boundary result. + +## Conclusion + +No critical or high student/instructor-separation blockers were found. The +packet is ready for this blind review dimension. diff --git a/project-01-java-aws-3tier/P0_REMEDIATION.md b/project-01-java-aws-3tier/P0_REMEDIATION.md new file mode 100644 index 00000000..dacceeff --- /dev/null +++ b/project-01-java-aws-3tier/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Deploy Java Application on AWS 3-Tier Architecture + +## Scope + +This record defines the active classroom path for `project-01-java-aws-3tier`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-01-java-aws-3tier/P2_CLASSROOM.md b/project-01-java-aws-3tier/P2_CLASSROOM.md new file mode 100644 index 00000000..09753041 --- /dev/null +++ b/project-01-java-aws-3tier/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploy Java Application on AWS 3-Tier Architecture + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-01-java-aws-3tier/P2_EVIDENCE.md b/project-01-java-aws-3tier/P2_EVIDENCE.md new file mode 100644 index 00000000..c4f178c8 --- /dev/null +++ b/project-01-java-aws-3tier/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploy Java Application on AWS 3-Tier Architecture + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-01-java-aws-3tier/P2_HARDENING.md b/project-01-java-aws-3tier/P2_HARDENING.md new file mode 100644 index 00000000..0fa2b6d5 --- /dev/null +++ b/project-01-java-aws-3tier/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploy Java Application on AWS 3-Tier Architecture + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-01-java-aws-3tier/P2_LOCAL_PILOT.md b/project-01-java-aws-3tier/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..5850ab9f --- /dev/null +++ b/project-01-java-aws-3tier/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploy Java Application on AWS 3-Tier Architecture + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-01-java-aws-3tier/START_HERE.md b/project-01-java-aws-3tier/START_HERE.md new file mode 100644 index 00000000..16d575b2 --- /dev/null +++ b/project-01-java-aws-3tier/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-01-java-aws-3tier + +**Learning focus:** Java/Spring Boot application delivery on AWS 3-tier infrastructure with Terraform, Maven, +Tomcat, Nginx, and MySQL + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect the readme headings and the Terraform files locally, then run only the recorded +formatting check `terraform -chdir=terraform fmt -check` without provisioning anything. + +## Checkpoints + +1. 1. The learner can map the packet's components into frontend Nginx, backend Tomcat, and private MySQL tiers and identify the relevant Terraform files +2. 1. The learner can trace the Java Login App's Maven configuration, JDBC property, JSP pages, and Employee-table schema without changing or deploying them +3. 1. The learner can explain the intended request path from the public Nginx load balancer through the private Tomcat load balancer to the RDS database and cite the packet's validation targets and security boundaries. + +## Hints if you are stuck + +1. 1. If the local formatting check fails, compare whitespace and Terraform block structure before investigating AWS resources +2. 1. For an application-flow question, follow the `proxy_pass`, target-group, listener, and security-group declarations across the Nginx and Tomcat sections +3. 1. For database-related behavior, compare the JDBC settings, the `UserDB`/`Employee` schema, and the stated private-subnet access sources rather than guessing credentials or network routes. + +## Evidence to capture + +Annotated local architecture map, formatting-check result, traced Java-to-database configuration, and a short +validation checklist + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-01-java-aws-3tier/SUPPORTED_VERSIONS.md b/project-01-java-aws-3tier/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..c074c846 --- /dev/null +++ b/project-01-java-aws-3tier/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Deploy Java Application on AWS 3-Tier Architecture + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-01-java-aws-3tier/fixtures/clean_local.txt b/project-01-java-aws-3tier/fixtures/clean_local.txt new file mode 100644 index 00000000..0a1be00e --- /dev/null +++ b/project-01-java-aws-3tier/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-01-java-aws-3tier +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-01-java-aws-3tier/fixtures/evidence-local-result.txt b/project-01-java-aws-3tier/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..1351a7a8 --- /dev/null +++ b/project-01-java-aws-3tier/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-01-java-aws-3tier +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-01-java-aws-3tier/fixtures/negative_cloud_command.txt b/project-01-java-aws-3tier/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..6b951c00 --- /dev/null +++ b/project-01-java-aws-3tier/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-01-java-aws-3tier +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-01-java-aws-3tier/validate-p1-stream2.sh b/project-01-java-aws-3tier/validate-p1-stream2.sh new file mode 100755 index 00000000..f66d321d --- /dev/null +++ b/project-01-java-aws-3tier/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-01-java-aws-3tier" ]; then + printf '%s +' "ERROR: expected project-01-java-aws-3tier; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-01-java-aws-3tier' diff --git a/project-01-java-aws-3tier/validate-p2-local.sh b/project-01-java-aws-3tier/validate-p2-local.sh new file mode 100755 index 00000000..2adcf19a --- /dev/null +++ b/project-01-java-aws-3tier/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-01-java-aws-3tier" ]; then + printf '%s +' "ERROR: expected project-01-java-aws-3tier; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-01-java-aws-3tier' diff --git a/project-02-aws-vpc-architecture/P2_CLASSROOM.md b/project-02-aws-vpc-architecture/P2_CLASSROOM.md new file mode 100644 index 00000000..bc716081 --- /dev/null +++ b/project-02-aws-vpc-architecture/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploy Scalable VPC Architecture on AWS Cloud + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-02-aws-vpc-architecture/P2_EVIDENCE.md b/project-02-aws-vpc-architecture/P2_EVIDENCE.md new file mode 100644 index 00000000..5e4fe8e6 --- /dev/null +++ b/project-02-aws-vpc-architecture/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploy Scalable VPC Architecture on AWS Cloud + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-02-aws-vpc-architecture/P2_HARDENING.md b/project-02-aws-vpc-architecture/P2_HARDENING.md new file mode 100644 index 00000000..853ee871 --- /dev/null +++ b/project-02-aws-vpc-architecture/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploy Scalable VPC Architecture on AWS Cloud + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-02-aws-vpc-architecture/P2_LOCAL_PILOT.md b/project-02-aws-vpc-architecture/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..62b20c3f --- /dev/null +++ b/project-02-aws-vpc-architecture/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploy Scalable VPC Architecture on AWS Cloud + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-02-aws-vpc-architecture/START_HERE.md b/project-02-aws-vpc-architecture/START_HERE.md new file mode 100644 index 00000000..720caf8e --- /dev/null +++ b/project-02-aws-vpc-architecture/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-02-aws-vpc-architecture + +**Learning focus:** AWS VPC network architecture and secure cloud application delivery + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +On a local copy, read the main readme and sketch the two CIDR blocks, public/private subnet roles, gateways, +Transit Gateway, load balancer, and validation stages without creating AWS resources. + +## Checkpoints + +1. 1. Produce a local architecture sketch that distinguishes the 192.168.0.0/16 bastion VPC from the 172.32.0.0/16 private application VPC and labels the stated gateway and subnet relationships +2. 1. Create a local dependency checklist mapping flow logs, S3 policy/configuration, IAM permissions, launch configuration, Auto Scaling, target group, NLB, and Route 53 to their prerequisite components +3. 1. Assemble a local validation record template covering private-instance access conceptually, Session Manager access, and public web page verification, leaving all live execution for instructor-controlled infrastructure. + +## Hints if you are stuck + +1. 1. If the architecture sketch is confusing, first separate internet-facing bastion responsibilities from private application-server responsibilities before tracing traffic +2. 1. When a dependency seems missing, compare the requested component with the README's preceding network, identity, logging, and load-balancing steps +3. 1. For a validation mismatch, check whether the evidence corresponds to the stated path—public entry through the NLB, private placement for application instances, and Session Manager rather than SSH to private nodes. + +## Evidence to capture + +Local two-VPC architecture diagram, dependency checklist, and validation-plan notes tied to the README's +stated components + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-02-aws-vpc-architecture/SUPPORTED_VERSIONS.md b/project-02-aws-vpc-architecture/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..cd8e5f94 --- /dev/null +++ b/project-02-aws-vpc-architecture/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Deploy Scalable VPC Architecture on AWS Cloud + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-02-aws-vpc-architecture/fixtures/clean_local.txt b/project-02-aws-vpc-architecture/fixtures/clean_local.txt new file mode 100644 index 00000000..aeccfefd --- /dev/null +++ b/project-02-aws-vpc-architecture/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-02-aws-vpc-architecture +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-02-aws-vpc-architecture/fixtures/evidence-local-result.txt b/project-02-aws-vpc-architecture/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..fe863fd2 --- /dev/null +++ b/project-02-aws-vpc-architecture/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-02-aws-vpc-architecture +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-02-aws-vpc-architecture/fixtures/negative_cloud_command.txt b/project-02-aws-vpc-architecture/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..f00a883d --- /dev/null +++ b/project-02-aws-vpc-architecture/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-02-aws-vpc-architecture +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-02-aws-vpc-architecture/validate-p1-stream2.sh b/project-02-aws-vpc-architecture/validate-p1-stream2.sh new file mode 100755 index 00000000..40457327 --- /dev/null +++ b/project-02-aws-vpc-architecture/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-02-aws-vpc-architecture" ]; then + printf '%s +' "ERROR: expected project-02-aws-vpc-architecture; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-02-aws-vpc-architecture' diff --git a/project-02-aws-vpc-architecture/validate-p2-local.sh b/project-02-aws-vpc-architecture/validate-p2-local.sh new file mode 100755 index 00000000..0c29b268 --- /dev/null +++ b/project-02-aws-vpc-architecture/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-02-aws-vpc-architecture" ]; then + printf '%s +' "ERROR: expected project-02-aws-vpc-architecture; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-02-aws-vpc-architecture' diff --git a/project-03-linux-fundamentals/P2_CLASSROOM.md b/project-03-linux-fundamentals/P2_CLASSROOM.md new file mode 100644 index 00000000..6857dd1e --- /dev/null +++ b/project-03-linux-fundamentals/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Fun with Linux for Cloud & DevOps Engineers + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-03-linux-fundamentals/P2_EVIDENCE.md b/project-03-linux-fundamentals/P2_EVIDENCE.md new file mode 100644 index 00000000..3a5f6196 --- /dev/null +++ b/project-03-linux-fundamentals/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Fun with Linux for Cloud & DevOps Engineers + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-03-linux-fundamentals/P2_HARDENING.md b/project-03-linux-fundamentals/P2_HARDENING.md new file mode 100644 index 00000000..19575b94 --- /dev/null +++ b/project-03-linux-fundamentals/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Fun with Linux for Cloud & DevOps Engineers + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-03-linux-fundamentals/P2_LOCAL_PILOT.md b/project-03-linux-fundamentals/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..83dea3e6 --- /dev/null +++ b/project-03-linux-fundamentals/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Fun with Linux for Cloud & DevOps Engineers + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-03-linux-fundamentals/START_HERE.md b/project-03-linux-fundamentals/START_HERE.md new file mode 100644 index 00000000..f19bcdcc --- /dev/null +++ b/project-03-linux-fundamentals/START_HERE.md @@ -0,0 +1,41 @@ +# Start Here: project-03-linux-fundamentals + +**Learning focus:** Linux administration fundamentals: users, groups, permissions, filesystem navigation, file +management, and mounting + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +On a disposable local Linux environment, make a temporary practice directory and record the starting user and +current working directory before attempting any account, ownership, or deletion exercise. + +## Checkpoints + +1. 1. The learner can show the intended users and groups in a local practice setup and explain which accounts use primary versus secondary group membership +2. 1. The learner can reproduce the specified /dir* and /opt/dir14 paths and demonstrate file creation, movement, renaming, and relative-path use without touching real system data +3. 1. The learner can provide command output showing the requested text substitutions/searches, filesystem listing checks, and a simulated /data mount-verification plan, while reserving actual EBS, mount, and cleanup operations for instructor-controlled material. + +## Hints if you are stuck + +1. 1. Before each step, verify the active account, working directory, and target path +2. many failures here come from confusing an absolute path such as /f3 with a path relative to the current directory +3. 1. When an operation is denied, inspect the target's owner, group, and permission bits and compare them with the account currently logged in rather than immediately escalating privileges +4. 1. For move, delete, and text-edit tasks, first confirm the source exists and preview the affected names or lines, then use a reversible copy or disposable workspace to isolate whether the issue is path selection, permissions, or command syntax. + +## Evidence to capture + +A local command transcript plus a before/after directory tree, account/group membership summary, file-content +transformation evidence, search/count outputs, and a clearly labeled instructor-only plan for the +EBS/filesystem portion + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-03-linux-fundamentals/SUPPORTED_VERSIONS.md b/project-03-linux-fundamentals/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..224e189c --- /dev/null +++ b/project-03-linux-fundamentals/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Fun with Linux for Cloud & DevOps Engineers + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-03-linux-fundamentals/fixtures/clean_local.txt b/project-03-linux-fundamentals/fixtures/clean_local.txt new file mode 100644 index 00000000..b43ad334 --- /dev/null +++ b/project-03-linux-fundamentals/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-03-linux-fundamentals +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-03-linux-fundamentals/fixtures/evidence-local-result.txt b/project-03-linux-fundamentals/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..2d8ced37 --- /dev/null +++ b/project-03-linux-fundamentals/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-03-linux-fundamentals +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-03-linux-fundamentals/fixtures/negative_cloud_command.txt b/project-03-linux-fundamentals/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..79fe2de4 --- /dev/null +++ b/project-03-linux-fundamentals/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-03-linux-fundamentals +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-03-linux-fundamentals/validate-p1-stream2.sh b/project-03-linux-fundamentals/validate-p1-stream2.sh new file mode 100755 index 00000000..cdb6be97 --- /dev/null +++ b/project-03-linux-fundamentals/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-03-linux-fundamentals" ]; then + printf '%s +' "ERROR: expected project-03-linux-fundamentals; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-03-linux-fundamentals' diff --git a/project-03-linux-fundamentals/validate-p2-local.sh b/project-03-linux-fundamentals/validate-p2-local.sh new file mode 100755 index 00000000..123e5bae --- /dev/null +++ b/project-03-linux-fundamentals/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-03-linux-fundamentals" ]; then + printf '%s +' "ERROR: expected project-03-linux-fundamentals; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-03-linux-fundamentals' diff --git a/project-04-django-aws-ecs/P2_CLASSROOM.md b/project-04-django-aws-ecs/P2_CLASSROOM.md new file mode 100644 index 00000000..beb1cb90 --- /dev/null +++ b/project-04-django-aws-ecs/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploy Django Application on AWS using ECS and ECR + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-04-django-aws-ecs/P2_EVIDENCE.md b/project-04-django-aws-ecs/P2_EVIDENCE.md new file mode 100644 index 00000000..ae3f76c2 --- /dev/null +++ b/project-04-django-aws-ecs/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploy Django Application on AWS using ECS and ECR + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-04-django-aws-ecs/P2_HARDENING.md b/project-04-django-aws-ecs/P2_HARDENING.md new file mode 100644 index 00000000..87eba25c --- /dev/null +++ b/project-04-django-aws-ecs/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploy Django Application on AWS using ECS and ECR + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-04-django-aws-ecs/P2_LOCAL_PILOT.md b/project-04-django-aws-ecs/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..9155cefc --- /dev/null +++ b/project-04-django-aws-ecs/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploy Django Application on AWS using ECS and ECR + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-04-django-aws-ecs/START_HERE.md b/project-04-django-aws-ecs/START_HERE.md new file mode 100644 index 00000000..57d18f8a --- /dev/null +++ b/project-04-django-aws-ecs/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-04-django-aws-ecs + +**Learning focus:** Containerizing a Django application and understanding its ECS/ECR deployment architecture + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `python3 -m compileall .` and record whether the Django source files compile +without errors. + +## Checkpoints + +1. 1. `python3 -m compileall .` completes successfully and produces bytecode-cache output for the Django package +2. 1. The learner can trace, from `manage.py`, `hello_world_django_app/settings.py`, and `urls.py`, how the local Django application is configured and routed +3. 1. The learner can annotate the `Dockerfile` and `project.yaml` to identify the image-build inputs, non-root container execution, exposed application port, and the separate ECR-to-ECS concepts without attempting cloud access. + +## Hints if you are stuck + +1. 1. If compilation fails, start with the filename and line number in the error, then check syntax and indentation in that file +2. 1. If the application flow is unclear, follow the imports from `manage.py` into the project package and then inspect the URL pattern's target view +3. 1. If the container configuration is confusing, compare each Dockerfile instruction with the files it copies or installs and distinguish image construction from runtime configuration. + +## Evidence to capture + +Successful local compileall output, a short annotated request/configuration flow, and a +Dockerfile/project.yaml mapping that identifies build, runtime-user, port, and ECS/ECR roles + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-04-django-aws-ecs/SUPPORTED_VERSIONS.md b/project-04-django-aws-ecs/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..598f6899 --- /dev/null +++ b/project-04-django-aws-ecs/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Deploy Django Application on AWS using ECS and ECR + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-04-django-aws-ecs/fixtures/clean_local.txt b/project-04-django-aws-ecs/fixtures/clean_local.txt new file mode 100644 index 00000000..5c35d405 --- /dev/null +++ b/project-04-django-aws-ecs/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-04-django-aws-ecs +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-04-django-aws-ecs/fixtures/evidence-local-result.txt b/project-04-django-aws-ecs/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..e4fddf33 --- /dev/null +++ b/project-04-django-aws-ecs/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-04-django-aws-ecs +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-04-django-aws-ecs/fixtures/negative_cloud_command.txt b/project-04-django-aws-ecs/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..bbcd7e87 --- /dev/null +++ b/project-04-django-aws-ecs/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-04-django-aws-ecs +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-04-django-aws-ecs/validate-p1-stream2.sh b/project-04-django-aws-ecs/validate-p1-stream2.sh new file mode 100755 index 00000000..f4f3f005 --- /dev/null +++ b/project-04-django-aws-ecs/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-04-django-aws-ecs" ]; then + printf '%s +' "ERROR: expected project-04-django-aws-ecs; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-04-django-aws-ecs' diff --git a/project-04-django-aws-ecs/validate-p2-local.sh b/project-04-django-aws-ecs/validate-p2-local.sh new file mode 100755 index 00000000..08c63de5 --- /dev/null +++ b/project-04-django-aws-ecs/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-04-django-aws-ecs" ]; then + printf '%s +' "ERROR: expected project-04-django-aws-ecs; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-04-django-aws-ecs' diff --git a/project-05-docker-jenkins-k8s/.p1_active_paths b/project-05-docker-jenkins-k8s/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-05-docker-jenkins-k8s/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-05-docker-jenkins-k8s/P1_LOCAL_CONTRACT.md b/project-05-docker-jenkins-k8s/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..47c0e652 --- /dev/null +++ b/project-05-docker-jenkins-k8s/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — Deploy your code on a Docker Container using Jenkins on AWS + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-05-docker-jenkins-k8s/P2_CLASSROOM.md b/project-05-docker-jenkins-k8s/P2_CLASSROOM.md new file mode 100644 index 00000000..7adc875c --- /dev/null +++ b/project-05-docker-jenkins-k8s/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploy your code on a Docker Container using Jenkins on AWS + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-05-docker-jenkins-k8s/P2_EVIDENCE.md b/project-05-docker-jenkins-k8s/P2_EVIDENCE.md new file mode 100644 index 00000000..923eacbb --- /dev/null +++ b/project-05-docker-jenkins-k8s/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploy your code on a Docker Container using Jenkins on AWS + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-05-docker-jenkins-k8s/P2_HARDENING.md b/project-05-docker-jenkins-k8s/P2_HARDENING.md new file mode 100644 index 00000000..26f2f972 --- /dev/null +++ b/project-05-docker-jenkins-k8s/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploy your code on a Docker Container using Jenkins on AWS + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-05-docker-jenkins-k8s/P2_LOCAL_PILOT.md b/project-05-docker-jenkins-k8s/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..ecd9bf8d --- /dev/null +++ b/project-05-docker-jenkins-k8s/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploy your code on a Docker Container using Jenkins on AWS + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-05-docker-jenkins-k8s/START_HERE.md b/project-05-docker-jenkins-k8s/START_HERE.md new file mode 100644 index 00000000..4067bf9f --- /dev/null +++ b/project-05-docker-jenkins-k8s/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-05-docker-jenkins-k8s + +**Learning focus:** Java web application containerization and CI/CD with Docker, Jenkins, Maven, and +Kubernetes + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +In the local project copy, inspect `hello-world/Dockerfile`, `hello-world/pom.xml`, and the two Kubernetes +manifests, then write down how the Maven artifact, container image, deployment, and service connect before +running anything. + +## Checkpoints + +1. 1. The student can identify the Java/Maven modules and the expected WAR artifact, and explain the Dockerfile's base image, restricted user, and artifact-copy steps +2. 1. A local, non-cloud validation shows the Kubernetes deployment and service YAML parses successfully with the stated CPU and memory bounds +3. 1. The student can trace the intended Jenkins flow from source checkout through Maven build and Docker image publication to Kubernetes deployment, with evidence mapped to the relevant files and without changing the supplied materials. + +## Hints if you are stuck + +1. 1. If the project structure is unclear, start with the two `pom.xml` files and follow which module produces the web application artifact +2. 1. If a manifest validation fails, compare its names, selectors, ports, image reference, and resource fields with the labels and container definition rather than changing several fields at once +3. 1. If the CI/CD flow does not line up, distinguish Jenkins build steps, Docker image contents, and Kubernetes runtime settings, and inspect one boundary at a time. + +## Evidence to capture + +Annotated local file map plus a dry-run validation result for both Kubernetes manifests and a concise +Jenkins-to-Docker-to-Kubernetes flow trace + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-05-docker-jenkins-k8s/fixtures/clean/contract.txt b/project-05-docker-jenkins-k8s/fixtures/clean/contract.txt new file mode 100644 index 00000000..ea9feac7 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/clean/p2-clean.txt b/project-05-docker-jenkins-k8s/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..31c25960 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/evidence-local-result.txt b/project-05-docker-jenkins-k8s/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..b1303729 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/negative/credential.txt b/project-05-docker-jenkins-k8s/fixtures/negative/credential.txt new file mode 100644 index 00000000..a1ada497 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/negative/mutation.txt b/project-05-docker-jenkins-k8s/fixtures/negative/mutation.txt new file mode 100644 index 00000000..d8a7cd35 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/negative/p2-source-shaped.txt b/project-05-docker-jenkins-k8s/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..a66a0c94 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/fixtures/negative/public_bind.txt b/project-05-docker-jenkins-k8s/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..c0252434 --- /dev/null +++ b/project-05-docker-jenkins-k8s/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-05-docker-jenkins-k8s +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-05-docker-jenkins-k8s/local-lab/contract.json b/project-05-docker-jenkins-k8s/local-lab/contract.json new file mode 100644 index 00000000..38769e57 --- /dev/null +++ b/project-05-docker-jenkins-k8s/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-05-docker-jenkins-k8s", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-05-docker-jenkins-k8s/reset-p2-local.sh b/project-05-docker-jenkins-k8s/reset-p2-local.sh new file mode 100755 index 00000000..f8f96f64 --- /dev/null +++ b/project-05-docker-jenkins-k8s/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-05-docker-jenkins-k8s" ]; then + printf '%s +' "ERROR: expected project-05-docker-jenkins-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-05-docker-jenkins-k8s' diff --git a/project-05-docker-jenkins-k8s/validate-p1-stream3.sh b/project-05-docker-jenkins-k8s/validate-p1-stream3.sh new file mode 100755 index 00000000..dceee2f6 --- /dev/null +++ b/project-05-docker-jenkins-k8s/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-05-docker-jenkins-k8s" ]; then + printf '%s +' "ERROR: expected project-05-docker-jenkins-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-05-docker-jenkins-k8s' diff --git a/project-05-docker-jenkins-k8s/validate-p2-local.sh b/project-05-docker-jenkins-k8s/validate-p2-local.sh new file mode 100755 index 00000000..f8f96f64 --- /dev/null +++ b/project-05-docker-jenkins-k8s/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-05-docker-jenkins-k8s" ]; then + printf '%s +' "ERROR: expected project-05-docker-jenkins-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-05-docker-jenkins-k8s' diff --git a/project-06-advanced-cicd-pipeline/.p1_active_paths b/project-06-advanced-cicd-pipeline/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-06-advanced-cicd-pipeline/P1_LOCAL_CONTRACT.md b/project-06-advanced-cicd-pipeline/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..340b3289 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — Implementation of the Entire Advanced CI/CD Pipeline with Major DevOps Tools + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-06-advanced-cicd-pipeline/P2_CLASSROOM.md b/project-06-advanced-cicd-pipeline/P2_CLASSROOM.md new file mode 100644 index 00000000..b2f46a99 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Implementation of the Entire Advanced CI/CD Pipeline with Major DevOps Tools + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-06-advanced-cicd-pipeline/P2_EVIDENCE.md b/project-06-advanced-cicd-pipeline/P2_EVIDENCE.md new file mode 100644 index 00000000..6867f41c --- /dev/null +++ b/project-06-advanced-cicd-pipeline/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Implementation of the Entire Advanced CI/CD Pipeline with Major DevOps Tools + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-06-advanced-cicd-pipeline/P2_HARDENING.md b/project-06-advanced-cicd-pipeline/P2_HARDENING.md new file mode 100644 index 00000000..8dc97d50 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Implementation of the Entire Advanced CI/CD Pipeline with Major DevOps Tools + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-06-advanced-cicd-pipeline/P2_LOCAL_PILOT.md b/project-06-advanced-cicd-pipeline/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..4d1e16a8 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Implementation of the Entire Advanced CI/CD Pipeline with Major DevOps Tools + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-06-advanced-cicd-pipeline/START_HERE.md b/project-06-advanced-cicd-pipeline/START_HERE.md new file mode 100644 index 00000000..ddea953a --- /dev/null +++ b/project-06-advanced-cicd-pipeline/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-06-advanced-cicd-pipeline + +**Learning focus:** Advanced DevSecOps CI/CD pipeline integration + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read README.md and map the twelve numbered Steps documents to the local Dockerfile, Jenkinsfile, Java tests, +Kubernetes manifests, and monitoring configuration without running any provisioning or deployment command. + +## Checkpoints + +1. 1. Produce a local component map showing how Maven tests and the Jenkinsfile stages relate to the Dockerfile and SonarQube/JFrog configuration +2. 1. Trace the artifact path on paper from the Java application and tests through the uniquely tagged container image and the Kubernetes deployment, namespace, and service manifests +3. 1. Verify that the final review checklist accounts for the Prometheus/Grafana monitoring files and the README's unprivileged-container and immutable-tag security claims. + +## Hints if you are stuck + +1. 1. If the component map feels unclear, start at the Jenkinsfile stage names and match each stage to the adjacent project file before examining the numbered Step notes +2. 1. If the artifact path breaks, compare the image name/tag and registry references across the Jenkinsfile, Dockerfile, and deployment manifest rather than changing credentials +3. 1. If monitoring evidence is missing, inspect the Step-12 description and the service type stated in the readme, then record the discrepancy or confirmation without attempting cluster access. + +## Evidence to capture + +Local annotated pipeline/component map, artifact-flow trace, and a checklist of test, security, +deployment-manifest, and monitoring claims + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-06-advanced-cicd-pipeline/fixtures/clean/contract.txt b/project-06-advanced-cicd-pipeline/fixtures/clean/contract.txt new file mode 100644 index 00000000..58353d99 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/clean/p2-clean.txt b/project-06-advanced-cicd-pipeline/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..012cb005 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/evidence-local-result.txt b/project-06-advanced-cicd-pipeline/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..bb2595b4 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/negative/credential.txt b/project-06-advanced-cicd-pipeline/fixtures/negative/credential.txt new file mode 100644 index 00000000..46730394 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/negative/mutation.txt b/project-06-advanced-cicd-pipeline/fixtures/negative/mutation.txt new file mode 100644 index 00000000..f1643358 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/negative/p2-source-shaped.txt b/project-06-advanced-cicd-pipeline/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..fe1fd30a --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/fixtures/negative/public_bind.txt b/project-06-advanced-cicd-pipeline/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..747a0192 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-06-advanced-cicd-pipeline +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-06-advanced-cicd-pipeline/local-lab/contract.json b/project-06-advanced-cicd-pipeline/local-lab/contract.json new file mode 100644 index 00000000..73408445 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-06-advanced-cicd-pipeline", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-06-advanced-cicd-pipeline/reset-p2-local.sh b/project-06-advanced-cicd-pipeline/reset-p2-local.sh new file mode 100755 index 00000000..1ccfc3f0 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-06-advanced-cicd-pipeline" ]; then + printf '%s +' "ERROR: expected project-06-advanced-cicd-pipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-06-advanced-cicd-pipeline' diff --git a/project-06-advanced-cicd-pipeline/validate-p1-stream3.sh b/project-06-advanced-cicd-pipeline/validate-p1-stream3.sh new file mode 100755 index 00000000..0e895d27 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-06-advanced-cicd-pipeline" ]; then + printf '%s +' "ERROR: expected project-06-advanced-cicd-pipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-06-advanced-cicd-pipeline' diff --git a/project-06-advanced-cicd-pipeline/validate-p2-local.sh b/project-06-advanced-cicd-pipeline/validate-p2-local.sh new file mode 100755 index 00000000..1ccfc3f0 --- /dev/null +++ b/project-06-advanced-cicd-pipeline/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-06-advanced-cicd-pipeline" ]; then + printf '%s +' "ERROR: expected project-06-advanced-cicd-pipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-06-advanced-cicd-pipeline' diff --git a/project-07-azure-devops-aks-terraform/P2_CLASSROOM.md b/project-07-azure-devops-aks-terraform/P2_CLASSROOM.md new file mode 100644 index 00000000..2c6d4840 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevOps-Journey-Using-Azure-DevOps + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-07-azure-devops-aks-terraform/P2_EVIDENCE.md b/project-07-azure-devops-aks-terraform/P2_EVIDENCE.md new file mode 100644 index 00000000..d434c893 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevOps-Journey-Using-Azure-DevOps + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-07-azure-devops-aks-terraform/P2_HARDENING.md b/project-07-azure-devops-aks-terraform/P2_HARDENING.md new file mode 100644 index 00000000..14debe29 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevOps-Journey-Using-Azure-DevOps + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-07-azure-devops-aks-terraform/P2_LOCAL_PILOT.md b/project-07-azure-devops-aks-terraform/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..361338b0 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevOps-Journey-Using-Azure-DevOps + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-07-azure-devops-aks-terraform/START_HERE.md b/project-07-azure-devops-aks-terraform/START_HERE.md new file mode 100644 index 00000000..9a207b7a --- /dev/null +++ b/project-07-azure-devops-aks-terraform/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-07-azure-devops-aks-terraform + +**Learning focus:** Azure DevOps CI/CD, Terraform infrastructure as code, Docker/AKS delivery, testing, and +monitoring + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Start locally by reading `README.md` and `prerequisites.md`, then trace the numbered lab sequence and open +`labs/1-Initial-Setup/README.md` without running any Azure, Terraform, or deployment command. + +## Checkpoints + +1. 1. Produce a one-page local map linking labs 1–7 to their stated outputs, including remote Terraform state, AKS/ACR infrastructure, application delivery, CI/CD, Inspec tests, and monitoring +2. 1. Annotate the provided `lab2pipeline.yaml`, Terraform modules, and later pipeline/manifests to identify inputs, module boundaries, and hand-offs without changing them +3. 1. Build and run the sample ASP.NET application only through the packet’s local Docker exercise and record the resulting image/container observations as a dry-run readiness artifact, stopping before any provider-backed action. + +## Hints if you are stuck + +1. 1. If the lab sequence feels unclear, compare each numbered lab’s readme with the root README’s learning objectives and named prerequisites +2. 1. If a pipeline or Terraform file is difficult to follow, first mark where variables, modules, service connections, and output values cross file boundaries +3. 1. If the local Docker check does not behave as expected, verify that the command is being run from the directory containing the referenced `Dockerfile` and distinguish image creation from container execution. + +## Evidence to capture + +Local lab-sequence map, annotated dependency/data-flow notes, and a local Docker image/container observation +log + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-07-azure-devops-aks-terraform/SUPPORTED_VERSIONS.md b/project-07-azure-devops-aks-terraform/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..54a9ae68 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — DevOps-Journey-Using-Azure-DevOps + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-07-azure-devops-aks-terraform/fixtures/clean_local.txt b/project-07-azure-devops-aks-terraform/fixtures/clean_local.txt new file mode 100644 index 00000000..22dd8b5a --- /dev/null +++ b/project-07-azure-devops-aks-terraform/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-07-azure-devops-aks-terraform +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-07-azure-devops-aks-terraform/fixtures/evidence-local-result.txt b/project-07-azure-devops-aks-terraform/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..8bbd412d --- /dev/null +++ b/project-07-azure-devops-aks-terraform/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-07-azure-devops-aks-terraform +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-07-azure-devops-aks-terraform/fixtures/negative_cloud_command.txt b/project-07-azure-devops-aks-terraform/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..2a4efa48 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-07-azure-devops-aks-terraform +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-07-azure-devops-aks-terraform/validate-p1-stream2.sh b/project-07-azure-devops-aks-terraform/validate-p1-stream2.sh new file mode 100755 index 00000000..075d3a76 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-07-azure-devops-aks-terraform" ]; then + printf '%s +' "ERROR: expected project-07-azure-devops-aks-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-07-azure-devops-aks-terraform' diff --git a/project-07-azure-devops-aks-terraform/validate-p2-local.sh b/project-07-azure-devops-aks-terraform/validate-p2-local.sh new file mode 100755 index 00000000..4721fd26 --- /dev/null +++ b/project-07-azure-devops-aks-terraform/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-07-azure-devops-aks-terraform" ]; then + printf '%s +' "ERROR: expected project-07-azure-devops-aks-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-07-azure-devops-aks-terraform' diff --git a/project-08-2048-game-eks/EVIDENCE_TEMPLATE.md b/project-08-2048-game-eks/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..6645e14f --- /dev/null +++ b/project-08-2048-game-eks/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +| Field | Record | +| --- | --- | +| Project | `project-08-2048-game-eks` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-08-2048-game-eks/P0_REMEDIATION.md b/project-08-2048-game-eks/P0_REMEDIATION.md new file mode 100644 index 00000000..4800e5b3 --- /dev/null +++ b/project-08-2048-game-eks/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +## Scope + +This record defines the active classroom path for `project-08-2048-game-eks`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-08-2048-game-eks/P2_CLASSROOM.md b/project-08-2048-game-eks/P2_CLASSROOM.md new file mode 100644 index 00000000..8349cb00 --- /dev/null +++ b/project-08-2048-game-eks/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-08-2048-game-eks/P2_EVIDENCE.md b/project-08-2048-game-eks/P2_EVIDENCE.md new file mode 100644 index 00000000..b7f543b6 --- /dev/null +++ b/project-08-2048-game-eks/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-08-2048-game-eks/P2_HARDENING.md b/project-08-2048-game-eks/P2_HARDENING.md new file mode 100644 index 00000000..eef093c6 --- /dev/null +++ b/project-08-2048-game-eks/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-08-2048-game-eks/P2_LOCAL_PILOT.md b/project-08-2048-game-eks/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..f65268a1 --- /dev/null +++ b/project-08-2048-game-eks/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Kubernetes end-to-end Project on EKS(Amazon Kubernetes Service) + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-08-2048-game-eks/START_HERE.md b/project-08-2048-game-eks/START_HERE.md new file mode 100644 index 00000000..8aa05646 --- /dev/null +++ b/project-08-2048-game-eks/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-08-2048-game-eks + +**Learning focus:** Kubernetes workload deployment and service exposure for a 2048 web app + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project directory, inspect README.md, 2048-deployment.yaml, and mygame-svc.yaml, then run the listed +client-side validation command `kubectl apply --dry-run=client -f 2048-deployment.yaml -f mygame-svc.yaml` +without contacting a cluster. + +## Checkpoints + +1. 1. The dry-run completes without manifest or schema errors for both the Deployment and Service +2. 1. The Deployment manifest visibly defines one `deployment-2048` replica with matching `app: 2048-ws` selector/template labels and container port 80 +3. 1. The Service manifest visibly selects `app: 2048-ws`, maps port 80 to targetPort 80, and declares type `LoadBalancer`. + +## Hints if you are stuck + +1. 1. If the dry-run reports a YAML problem, compare indentation and key nesting against the nearby manifest examples in README.md +2. 1. If the workload and Service do not connect conceptually, check that the Service selector exactly matches the Pod-template label rather than only the resource names +3. 1. If validation cannot run locally, first verify that `kubectl` is installed and that both referenced YAML files are in the current directory, without switching to cluster creation. + +## Evidence to capture + +Terminal output showing a successful client-side dry run plus annotated excerpts or screenshots of the +Deployment labels/port and Service selector/port/type + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-08-2048-game-eks/fixtures/clean-contract.txt b/project-08-2048-game-eks/fixtures/clean-contract.txt new file mode 100644 index 00000000..47619734 --- /dev/null +++ b/project-08-2048-game-eks/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-08-2048-game-eks +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-08-2048-game-eks/fixtures/evidence-local-result.txt b/project-08-2048-game-eks/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a8d540a9 --- /dev/null +++ b/project-08-2048-game-eks/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-08-2048-game-eks +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-08-2048-game-eks/fixtures/negative-contract.txt b/project-08-2048-game-eks/fixtures/negative-contract.txt new file mode 100644 index 00000000..23c8af91 --- /dev/null +++ b/project-08-2048-game-eks/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-08-2048-game-eks +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-08-2048-game-eks/reset-local.sh b/project-08-2048-game-eks/reset-local.sh new file mode 100755 index 00000000..2c56724c --- /dev/null +++ b/project-08-2048-game-eks/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-08-2048-game-eks" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-08-2048-game-eks' diff --git a/project-08-2048-game-eks/validate-p2-local.sh b/project-08-2048-game-eks/validate-p2-local.sh new file mode 100755 index 00000000..2737242b --- /dev/null +++ b/project-08-2048-game-eks/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-08-2048-game-eks" ]; then + printf '%s +' "ERROR: expected project-08-2048-game-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-08-2048-game-eks' diff --git a/project-09-devsecops-netflix-clone/.p1_active_paths b/project-09-devsecops-netflix-clone/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-09-devsecops-netflix-clone/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-09-devsecops-netflix-clone/P1_LOCAL_CONTRACT.md b/project-09-devsecops-netflix-clone/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..5436e16b --- /dev/null +++ b/project-09-devsecops-netflix-clone/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — DevSecOps : Netflix Clone CI-CD with Monitoring | Email + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-09-devsecops-netflix-clone/P2_CLASSROOM.md b/project-09-devsecops-netflix-clone/P2_CLASSROOM.md new file mode 100644 index 00000000..b8ad2258 --- /dev/null +++ b/project-09-devsecops-netflix-clone/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps : Netflix Clone CI-CD with Monitoring | Email + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-09-devsecops-netflix-clone/P2_EVIDENCE.md b/project-09-devsecops-netflix-clone/P2_EVIDENCE.md new file mode 100644 index 00000000..7db95e2a --- /dev/null +++ b/project-09-devsecops-netflix-clone/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps : Netflix Clone CI-CD with Monitoring | Email + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-09-devsecops-netflix-clone/P2_HARDENING.md b/project-09-devsecops-netflix-clone/P2_HARDENING.md new file mode 100644 index 00000000..45ae4be5 --- /dev/null +++ b/project-09-devsecops-netflix-clone/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps : Netflix Clone CI-CD with Monitoring | Email + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-09-devsecops-netflix-clone/P2_LOCAL_PILOT.md b/project-09-devsecops-netflix-clone/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..c0782bb1 --- /dev/null +++ b/project-09-devsecops-netflix-clone/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps : Netflix Clone CI-CD with Monitoring | Email + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-09-devsecops-netflix-clone/START_HERE.md b/project-09-devsecops-netflix-clone/START_HERE.md new file mode 100644 index 00000000..88c2fa0d --- /dev/null +++ b/project-09-devsecops-netflix-clone/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-09-devsecops-netflix-clone + +**Learning focus:** DevSecOps CI/CD pipeline security and observability for a containerized Netflix clone + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read the local README’s Project Overview and 2026 DevSecOps Enhancements, then make a short checklist of the +Jenkins credentials, build-number image tag, and Trivy gate that the lab is meant to demonstrate. + +## Checkpoints + +1. 1. Produce a local architecture/checklist showing how Jenkins, Docker, the clone app, Kubernetes, Prometheus, Grafana, Node Exporter, SonarQube, and Trivy fit together +2. 1. Trace the README’s pipeline sequence and identify where the `tmdb-api-key` credential, `${BUILD_NUMBER}` image tag, and mandatory Trivy scan belong without using real credentials or cloud services +3. 1. Validate the intended monitoring evidence locally by documenting the Prometheus targets and metric paths for Node Exporter and Jenkins, plus the Grafana data-source/dashboard checks described in the packet. + +## Hints if you are stuck + +1. 1. If the pipeline design is unclear, compare the three 2026 enhancements with the older numbered steps and distinguish secret injection from ordinary application configuration +2. 1. If a monitoring target does not appear, check the target address, metric path, and whether the Prometheus configuration passes `promtool check config` before considering a reload +3. 1. If a security gate behaves unexpectedly, inspect the exact image tag and scan threshold used by the pipeline rather than changing the gate or exposing a secret. + +## Evidence to capture + +Annotated local pipeline diagram/checklist, redacted Jenkinsfile stage-to-enhancement mapping, Prometheus +target/config validation notes, and screenshots or logs from a safe local/mock run + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-09-devsecops-netflix-clone/fixtures/clean/contract.txt b/project-09-devsecops-netflix-clone/fixtures/clean/contract.txt new file mode 100644 index 00000000..024559de --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/clean/p2-clean.txt b/project-09-devsecops-netflix-clone/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..974d0b3b --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/evidence-local-result.txt b/project-09-devsecops-netflix-clone/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..5b3edcd5 --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/negative/credential.txt b/project-09-devsecops-netflix-clone/fixtures/negative/credential.txt new file mode 100644 index 00000000..c51b76cd --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/negative/mutation.txt b/project-09-devsecops-netflix-clone/fixtures/negative/mutation.txt new file mode 100644 index 00000000..4b327c96 --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/negative/p2-source-shaped.txt b/project-09-devsecops-netflix-clone/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..2be5ee81 --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/fixtures/negative/public_bind.txt b/project-09-devsecops-netflix-clone/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..fa67d72c --- /dev/null +++ b/project-09-devsecops-netflix-clone/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-09-devsecops-netflix-clone +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-09-devsecops-netflix-clone/local-lab/contract.json b/project-09-devsecops-netflix-clone/local-lab/contract.json new file mode 100644 index 00000000..536202d9 --- /dev/null +++ b/project-09-devsecops-netflix-clone/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-09-devsecops-netflix-clone", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-09-devsecops-netflix-clone/reset-p2-local.sh b/project-09-devsecops-netflix-clone/reset-p2-local.sh new file mode 100755 index 00000000..a56558fd --- /dev/null +++ b/project-09-devsecops-netflix-clone/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-09-devsecops-netflix-clone" ]; then + printf '%s +' "ERROR: expected project-09-devsecops-netflix-clone; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-09-devsecops-netflix-clone' diff --git a/project-09-devsecops-netflix-clone/validate-p1-stream3.sh b/project-09-devsecops-netflix-clone/validate-p1-stream3.sh new file mode 100755 index 00000000..de5a9b5f --- /dev/null +++ b/project-09-devsecops-netflix-clone/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-09-devsecops-netflix-clone" ]; then + printf '%s +' "ERROR: expected project-09-devsecops-netflix-clone; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-09-devsecops-netflix-clone' diff --git a/project-09-devsecops-netflix-clone/validate-p2-local.sh b/project-09-devsecops-netflix-clone/validate-p2-local.sh new file mode 100755 index 00000000..a56558fd --- /dev/null +++ b/project-09-devsecops-netflix-clone/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-09-devsecops-netflix-clone" ]; then + printf '%s +' "ERROR: expected project-09-devsecops-netflix-clone; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-09-devsecops-netflix-clone' diff --git a/project-10-dotnet-azure-devops/P2_CLASSROOM.md b/project-10-dotnet-azure-devops/P2_CLASSROOM.md new file mode 100644 index 00000000..015d27a6 --- /dev/null +++ b/project-10-dotnet-azure-devops/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Create a CI/CD pipeline for .NET with Azure App Service (formerly DevOps Starter) + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-10-dotnet-azure-devops/P2_EVIDENCE.md b/project-10-dotnet-azure-devops/P2_EVIDENCE.md new file mode 100644 index 00000000..b89e0000 --- /dev/null +++ b/project-10-dotnet-azure-devops/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Create a CI/CD pipeline for .NET with Azure App Service (formerly DevOps Starter) + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-10-dotnet-azure-devops/P2_HARDENING.md b/project-10-dotnet-azure-devops/P2_HARDENING.md new file mode 100644 index 00000000..93faae0d --- /dev/null +++ b/project-10-dotnet-azure-devops/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Create a CI/CD pipeline for .NET with Azure App Service (formerly DevOps Starter) + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-10-dotnet-azure-devops/P2_LOCAL_PILOT.md b/project-10-dotnet-azure-devops/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..4d9a7020 --- /dev/null +++ b/project-10-dotnet-azure-devops/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Create a CI/CD pipeline for .NET with Azure App Service (formerly DevOps Starter) + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-10-dotnet-azure-devops/START_HERE.md b/project-10-dotnet-azure-devops/START_HERE.md new file mode 100644 index 00000000..b795f1a9 --- /dev/null +++ b/project-10-dotnet-azure-devops/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-10-dotnet-azure-devops + +**Learning focus:** .NET CI/CD pipeline analysis with Azure DevOps and App Service + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the readme locally and map the three exercises into a paper or local notes checklist, starting with the +ASP.NET Core repository path and pipeline objects without signing into or provisioning Azure. + +## Checkpoints + +1. 1. Identify and record the expected ASP.NET Core Index page path stated in the readme and the build, release, artifact, and trigger objects named in the packet +2. 1. In a local notes checklist, sequence the stated CI steps—source retrieval, dependency restore, compilation, tests, and published output—and distinguish them from release tasks +3. 1. Produce a mock change-and-observation record showing the edited heading, expected commit, build/release progression, and updated heading as evidence targets, without executing a cloud deployment. + +## Hints if you are stuck + +1. 1. If the pipeline stages seem mixed together, separate build activities from release tasks and match each task to the artifact or environment it consumes +2. 1. If a repository path is hard to locate in your notes, copy it exactly from the exercise and verify each folder name before interpreting the expected change +3. 1. If a trigger appears not to fire in the described flow, check whether the packet attributes it to a commit, a new build artifact, or an optional manual setting before diagnosing further. + +## Evidence to capture + +Annotated local exercise checklist plus a mock CI/CD trace linking the Index page heading change, commit, +build, artifact, release tasks, and resulting updated heading + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-10-dotnet-azure-devops/fixtures/clean_local.txt b/project-10-dotnet-azure-devops/fixtures/clean_local.txt new file mode 100644 index 00000000..9163a4a8 --- /dev/null +++ b/project-10-dotnet-azure-devops/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-10-dotnet-azure-devops +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-10-dotnet-azure-devops/fixtures/evidence-local-result.txt b/project-10-dotnet-azure-devops/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..6a6f5efb --- /dev/null +++ b/project-10-dotnet-azure-devops/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-10-dotnet-azure-devops +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-10-dotnet-azure-devops/fixtures/negative_cloud_command.txt b/project-10-dotnet-azure-devops/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..d721fc7d --- /dev/null +++ b/project-10-dotnet-azure-devops/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-10-dotnet-azure-devops +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-10-dotnet-azure-devops/validate-p2-local.sh b/project-10-dotnet-azure-devops/validate-p2-local.sh new file mode 100755 index 00000000..5422c5e6 --- /dev/null +++ b/project-10-dotnet-azure-devops/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-10-dotnet-azure-devops" ]; then + printf '%s +' "ERROR: expected project-10-dotnet-azure-devops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-10-dotnet-azure-devops' diff --git a/project-10-dotnet-azure-devops/validate_local.py b/project-10-dotnet-azure-devops/validate_local.py new file mode 100755 index 00000000..ac0cf91d --- /dev/null +++ b/project-10-dotnet-azure-devops/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-10-dotnet-azure-devops.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-10-dotnet-azure-devops": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-10-dotnet-azure-devops local-only control: PASS (validate_local.py)") diff --git a/project-11-aws-2tier-terraform/P2_CLASSROOM.md b/project-11-aws-2tier-terraform/P2_CLASSROOM.md new file mode 100644 index 00000000..3ef89da4 --- /dev/null +++ b/project-11-aws-2tier-terraform/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Two-Tier AWS Infrastructure with Terraform + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-11-aws-2tier-terraform/P2_EVIDENCE.md b/project-11-aws-2tier-terraform/P2_EVIDENCE.md new file mode 100644 index 00000000..50ea0c1f --- /dev/null +++ b/project-11-aws-2tier-terraform/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Two-Tier AWS Infrastructure with Terraform + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-11-aws-2tier-terraform/P2_HARDENING.md b/project-11-aws-2tier-terraform/P2_HARDENING.md new file mode 100644 index 00000000..6dce4f3b --- /dev/null +++ b/project-11-aws-2tier-terraform/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Two-Tier AWS Infrastructure with Terraform + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-11-aws-2tier-terraform/P2_LOCAL_PILOT.md b/project-11-aws-2tier-terraform/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..00cfb9a8 --- /dev/null +++ b/project-11-aws-2tier-terraform/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Two-Tier AWS Infrastructure with Terraform + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-11-aws-2tier-terraform/START_HERE.md b/project-11-aws-2tier-terraform/START_HERE.md new file mode 100644 index 00000000..b10dbef5 --- /dev/null +++ b/project-11-aws-2tier-terraform/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-11-aws-2tier-terraform + +**Learning focus:** Modular AWS two-tier infrastructure as code with Terraform + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read `README.md`, `project.yaml`, `variables.tf`, and the module filenames to map how +the VPC, security groups, ALB/target group, autoscaling, RDS, IAM, WAF, CDN, ACM, and Route 53 components are +organized before running any Terraform command. + +## Checkpoints + +1. 1. You can draw or annotate the dependency flow from the VPC and security-group modules to the ALB/autoscaling and RDS components +2. 1. You can identify in the readme the two stated hardening changes—web-tier ingress limited to the ALB security group and RDS storage encryption enabled—and locate the corresponding active module files +3. 1. You can produce a local review showing the Terraform configuration is formatted according to the packet's stated validation command without applying or destroying infrastructure. + +## Hints if you are stuck + +1. 1. If the module relationships are unclear, start at `main.tf` and follow each module call into its `variables.tf` rather than inspecting files in arbitrary order +2. 1. For an input or reference error, compare variable names and required values across the root files and the module-specific variable files +3. 1. For the security review, trace the source security group on web-tier ports and the RDS encryption setting, checking that the configuration matches the README's stated 2026 enhancements. + +## Evidence to capture + +Annotated local module-dependency map plus a non-destructive Terraform formatting-check result and notes tying +the two security enhancements to their module files + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-11-aws-2tier-terraform/SUPPORTED_VERSIONS.md b/project-11-aws-2tier-terraform/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..623f1bdb --- /dev/null +++ b/project-11-aws-2tier-terraform/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Two-Tier AWS Infrastructure with Terraform + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-11-aws-2tier-terraform/fixtures/clean_local.txt b/project-11-aws-2tier-terraform/fixtures/clean_local.txt new file mode 100644 index 00000000..e91618e9 --- /dev/null +++ b/project-11-aws-2tier-terraform/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-11-aws-2tier-terraform +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-11-aws-2tier-terraform/fixtures/evidence-local-result.txt b/project-11-aws-2tier-terraform/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..31f71c50 --- /dev/null +++ b/project-11-aws-2tier-terraform/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-11-aws-2tier-terraform +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-11-aws-2tier-terraform/fixtures/negative_cloud_command.txt b/project-11-aws-2tier-terraform/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..40b8ace5 --- /dev/null +++ b/project-11-aws-2tier-terraform/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-11-aws-2tier-terraform +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-11-aws-2tier-terraform/validate-p1-stream2.sh b/project-11-aws-2tier-terraform/validate-p1-stream2.sh new file mode 100755 index 00000000..ba6393b6 --- /dev/null +++ b/project-11-aws-2tier-terraform/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-11-aws-2tier-terraform" ]; then + printf '%s +' "ERROR: expected project-11-aws-2tier-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-11-aws-2tier-terraform' diff --git a/project-11-aws-2tier-terraform/validate-p2-local.sh b/project-11-aws-2tier-terraform/validate-p2-local.sh new file mode 100755 index 00000000..b5f266fe --- /dev/null +++ b/project-11-aws-2tier-terraform/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-11-aws-2tier-terraform" ]; then + printf '%s +' "ERROR: expected project-11-aws-2tier-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-11-aws-2tier-terraform' diff --git a/project-12-super-mario-k8s/EVIDENCE_TEMPLATE.md b/project-12-super-mario-k8s/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..1057f6ed --- /dev/null +++ b/project-12-super-mario-k8s/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — Deployment of Super Mario on Kubernetes using Terraform + +| Field | Record | +| --- | --- | +| Project | `project-12-super-mario-k8s` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-12-super-mario-k8s/P0_REMEDIATION.md b/project-12-super-mario-k8s/P0_REMEDIATION.md new file mode 100644 index 00000000..3d9600a1 --- /dev/null +++ b/project-12-super-mario-k8s/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Deployment of Super Mario on Kubernetes using Terraform + +## Scope + +This record defines the active classroom path for `project-12-super-mario-k8s`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-12-super-mario-k8s/P2_CLASSROOM.md b/project-12-super-mario-k8s/P2_CLASSROOM.md new file mode 100644 index 00000000..c213d806 --- /dev/null +++ b/project-12-super-mario-k8s/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deployment of Super Mario on Kubernetes using Terraform + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-12-super-mario-k8s/P2_EVIDENCE.md b/project-12-super-mario-k8s/P2_EVIDENCE.md new file mode 100644 index 00000000..c6ffeec1 --- /dev/null +++ b/project-12-super-mario-k8s/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deployment of Super Mario on Kubernetes using Terraform + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-12-super-mario-k8s/P2_HARDENING.md b/project-12-super-mario-k8s/P2_HARDENING.md new file mode 100644 index 00000000..fc904c3b --- /dev/null +++ b/project-12-super-mario-k8s/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deployment of Super Mario on Kubernetes using Terraform + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-12-super-mario-k8s/P2_LOCAL_PILOT.md b/project-12-super-mario-k8s/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..a1452ea3 --- /dev/null +++ b/project-12-super-mario-k8s/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deployment of Super Mario on Kubernetes using Terraform + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-12-super-mario-k8s/START_HERE.md b/project-12-super-mario-k8s/START_HERE.md new file mode 100644 index 00000000..e322376c --- /dev/null +++ b/project-12-super-mario-k8s/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-12-super-mario-k8s + +**Learning focus:** Kubernetes application deployment and Terraform infrastructure-as-code concepts, framed +around a Super Mario game on AWS EKS + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the local README.md and project.yaml, then write down the stated Super Mario, Kubernetes, Terraform, and +EKS components without executing any cloud or deployment command. + +## Checkpoints + +1. 1. A local notes page identifies the project goal as deploying Super Mario with Kubernetes and Terraform and records EKS/AWS as the referenced environment +2. 1. A learner-produced diagram or checklist separates application deployment, Kubernetes resources, and Terraform-managed infrastructure +3. 1. A local review record explains the intended validation evidence and clearly marks any cloud execution as out of scope for the classroom lab. + +## Hints if you are stuck + +1. 1. If the project scope feels unclear, compare the readme title and the stack/cloud fields in project.yaml before choosing a next step +2. 1. If you cannot distinguish infrastructure from application work, label each item by whether Terraform or Kubernetes is named as its owner +3. 1. If validation seems too weak, check whether the packet provides implementation files or only a README-focused reference and record that limitation rather than inventing commands. + +## Evidence to capture + +Annotated local README/project.yaml notes plus a component diagram or checklist and a scope-limited validation +record + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-12-super-mario-k8s/fixtures/clean-contract.txt b/project-12-super-mario-k8s/fixtures/clean-contract.txt new file mode 100644 index 00000000..b2572513 --- /dev/null +++ b/project-12-super-mario-k8s/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-12-super-mario-k8s +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-12-super-mario-k8s/fixtures/evidence-local-result.txt b/project-12-super-mario-k8s/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..71a34d2b --- /dev/null +++ b/project-12-super-mario-k8s/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-12-super-mario-k8s +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-12-super-mario-k8s/fixtures/negative-contract.txt b/project-12-super-mario-k8s/fixtures/negative-contract.txt new file mode 100644 index 00000000..b1fe7891 --- /dev/null +++ b/project-12-super-mario-k8s/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-12-super-mario-k8s +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-12-super-mario-k8s/reset-local.sh b/project-12-super-mario-k8s/reset-local.sh new file mode 100755 index 00000000..cb09baee --- /dev/null +++ b/project-12-super-mario-k8s/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-12-super-mario-k8s" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-12-super-mario-k8s' diff --git a/project-12-super-mario-k8s/validate-p2-local.sh b/project-12-super-mario-k8s/validate-p2-local.sh new file mode 100755 index 00000000..ff0d7eac --- /dev/null +++ b/project-12-super-mario-k8s/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-12-super-mario-k8s" ]; then + printf '%s +' "ERROR: expected project-12-super-mario-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-12-super-mario-k8s' diff --git a/project-13-zomato-clone-devsecops/.env.example b/project-13-zomato-clone-devsecops/.env.example new file mode 100644 index 00000000..d354051c --- /dev/null +++ b/project-13-zomato-clone-devsecops/.env.example @@ -0,0 +1,4 @@ +# Synthetic local classroom configuration for project-13-zomato-clone-devsecops. +# Do not place live credentials, endpoints, or account identifiers in this file. +LOCAL_CLASSROOM_MODE=true +LOCAL_EVIDENCE_ONLY=true diff --git a/project-13-zomato-clone-devsecops/EVIDENCE_TEMPLATE.md b/project-13-zomato-clone-devsecops/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..2604ab66 --- /dev/null +++ b/project-13-zomato-clone-devsecops/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +| Field | Record | +| --- | --- | +| Project | `project-13-zomato-clone-devsecops` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-13-zomato-clone-devsecops/Makefile b/project-13-zomato-clone-devsecops/Makefile new file mode 100644 index 00000000..ceb6af94 --- /dev/null +++ b/project-13-zomato-clone-devsecops/Makefile @@ -0,0 +1,6 @@ +# Local-first helper targets for project-13-zomato-clone-devsecops; no cloud actions. +.PHONY: help validate-local +help: + @printf '%s\n' 'Use validate-local for deterministic source checks only.' +validate-local: + @sh validate-p2-local.sh diff --git a/project-13-zomato-clone-devsecops/P0_REMEDIATION.md b/project-13-zomato-clone-devsecops/P0_REMEDIATION.md new file mode 100644 index 00000000..71909968 --- /dev/null +++ b/project-13-zomato-clone-devsecops/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +## Scope + +This record defines the active classroom path for `project-13-zomato-clone-devsecops`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-13-zomato-clone-devsecops/P2_CLASSROOM.md b/project-13-zomato-clone-devsecops/P2_CLASSROOM.md new file mode 100644 index 00000000..0404f474 --- /dev/null +++ b/project-13-zomato-clone-devsecops/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-13-zomato-clone-devsecops/P2_EVIDENCE.md b/project-13-zomato-clone-devsecops/P2_EVIDENCE.md new file mode 100644 index 00000000..ca8ef4b9 --- /dev/null +++ b/project-13-zomato-clone-devsecops/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-13-zomato-clone-devsecops/P2_HARDENING.md b/project-13-zomato-clone-devsecops/P2_HARDENING.md new file mode 100644 index 00000000..be180813 --- /dev/null +++ b/project-13-zomato-clone-devsecops/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-13-zomato-clone-devsecops/P2_LOCAL_PILOT.md b/project-13-zomato-clone-devsecops/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..47037d4b --- /dev/null +++ b/project-13-zomato-clone-devsecops/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-13-zomato-clone-devsecops/START_HERE.md b/project-13-zomato-clone-devsecops/START_HERE.md new file mode 100644 index 00000000..753b4545 --- /dev/null +++ b/project-13-zomato-clone-devsecops/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-13-zomato-clone-devsecops + +**Learning focus:** DevSecOps security concepts and CI/CD deployment planning for a clone app + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the local README.md and write down the project’s stated DevSecOps/CI/CD goal and the three sample +outcomes shown there before attempting any deployment work. + +## Checkpoints + +1. 1. A short local notes file identifies the project as a Zomato clone with secure DevSecOps CI/CD as its stated focus +2. 1. The learner can point to the README’s sample images and explain what observable application or pipeline outcome each is intended to represent without claiming an unshown implementation +3. 1. The learner produces a local validation record showing README.md is present and separates documented concepts from steps that are not included in the active packet. + +## Hints if you are stuck + +1. 1. If you are unsure what to build first, distinguish the README’s project title and sample evidence from the external blog and source-code links +2. 1. If a sample is difficult to interpret, record only the visible outcome and avoid inventing pipeline stages or commands not documented locally +3. 1. If validation fails, check that you are working in the project root and that the filename is exactly README.md before changing anything else. + +## Evidence to capture + +Local learner notes mapping the stated DevSecOps/CI/CD objective to the readme samples, plus a non-cloud +validation record that README.md exists + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-13-zomato-clone-devsecops/app.py b/project-13-zomato-clone-devsecops/app.py new file mode 100644 index 00000000..22907b3a --- /dev/null +++ b/project-13-zomato-clone-devsecops/app.py @@ -0,0 +1,19 @@ +"""Local-only teaching helper for project-13-zomato-clone-devsecops. + +This reconstructed module contains no remote service, cloud credential, or deployment +behavior. It is intentionally deterministic for classroom evidence. +""" + +from __future__ import annotations + + +def local_status() -> dict[str, str]: + return { + "project": "project-13-zomato-clone-devsecops", + "mode": "local-first", + "status": "ready-for-local-validation", + } + + +if __name__ == "__main__": + print(local_status()) diff --git a/project-13-zomato-clone-devsecops/fixtures/clean-contract.txt b/project-13-zomato-clone-devsecops/fixtures/clean-contract.txt new file mode 100644 index 00000000..031547e6 --- /dev/null +++ b/project-13-zomato-clone-devsecops/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-13-zomato-clone-devsecops +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-13-zomato-clone-devsecops/fixtures/evidence-local-result.txt b/project-13-zomato-clone-devsecops/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..c6135246 --- /dev/null +++ b/project-13-zomato-clone-devsecops/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-13-zomato-clone-devsecops +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-13-zomato-clone-devsecops/fixtures/negative-contract.txt b/project-13-zomato-clone-devsecops/fixtures/negative-contract.txt new file mode 100644 index 00000000..f3b28865 --- /dev/null +++ b/project-13-zomato-clone-devsecops/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-13-zomato-clone-devsecops +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-13-zomato-clone-devsecops/optional-cloud/README.md b/project-13-zomato-clone-devsecops/optional-cloud/README.md new file mode 100644 index 00000000..1993a12d --- /dev/null +++ b/project-13-zomato-clone-devsecops/optional-cloud/README.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Zomato Clone: Secure Deployment with DevSecOps CI/CD + +This checked-in record is required by the active source contract for `project-13-zomato-clone-devsecops`. It +is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-13-zomato-clone-devsecops/scripts/negative.sh b/project-13-zomato-clone-devsecops/scripts/negative.sh new file mode 100755 index 00000000..871a6a76 --- /dev/null +++ b/project-13-zomato-clone-devsecops/scripts/negative.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-13-zomato-clone-devsecops" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-13-zomato-clone-devsecops' 'negative.sh' diff --git a/project-13-zomato-clone-devsecops/scripts/reset.sh b/project-13-zomato-clone-devsecops/scripts/reset.sh new file mode 100755 index 00000000..1d6059b3 --- /dev/null +++ b/project-13-zomato-clone-devsecops/scripts/reset.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-13-zomato-clone-devsecops" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-13-zomato-clone-devsecops' diff --git a/project-13-zomato-clone-devsecops/scripts/smoke.sh b/project-13-zomato-clone-devsecops/scripts/smoke.sh new file mode 100755 index 00000000..f7775eea --- /dev/null +++ b/project-13-zomato-clone-devsecops/scripts/smoke.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-13-zomato-clone-devsecops" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-13-zomato-clone-devsecops' 'smoke.sh' diff --git a/project-13-zomato-clone-devsecops/validate-p0.sh b/project-13-zomato-clone-devsecops/validate-p0.sh new file mode 100755 index 00000000..66585db6 --- /dev/null +++ b/project-13-zomato-clone-devsecops/validate-p0.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-13-zomato-clone-devsecops" ]; then + printf '%s +' "ERROR: expected project-13-zomato-clone-devsecops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P0 project-13-zomato-clone-devsecops' diff --git a/project-13-zomato-clone-devsecops/validate-p2-local.sh b/project-13-zomato-clone-devsecops/validate-p2-local.sh new file mode 100755 index 00000000..8fa5ca0e --- /dev/null +++ b/project-13-zomato-clone-devsecops/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-13-zomato-clone-devsecops" ]; then + printf '%s +' "ERROR: expected project-13-zomato-clone-devsecops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-13-zomato-clone-devsecops' diff --git a/project-14-github-actions-android/EVIDENCE_TEMPLATE.md b/project-14-github-actions-android/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..dccf482a --- /dev/null +++ b/project-14-github-actions-android/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +| Field | Record | +| --- | --- | +| Project | `project-14-github-actions-android` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-14-github-actions-android/P0_REMEDIATION.md b/project-14-github-actions-android/P0_REMEDIATION.md new file mode 100644 index 00000000..c26d0793 --- /dev/null +++ b/project-14-github-actions-android/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +## Scope + +This record defines the active classroom path for `project-14-github-actions-android`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-14-github-actions-android/P2_CLASSROOM.md b/project-14-github-actions-android/P2_CLASSROOM.md new file mode 100644 index 00000000..a9fd08f1 --- /dev/null +++ b/project-14-github-actions-android/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-14-github-actions-android/P2_EVIDENCE.md b/project-14-github-actions-android/P2_EVIDENCE.md new file mode 100644 index 00000000..7b8fa917 --- /dev/null +++ b/project-14-github-actions-android/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-14-github-actions-android/P2_HARDENING.md b/project-14-github-actions-android/P2_HARDENING.md new file mode 100644 index 00000000..f84149b9 --- /dev/null +++ b/project-14-github-actions-android/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-14-github-actions-android/P2_LOCAL_PILOT.md b/project-14-github-actions-android/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..f2de62c5 --- /dev/null +++ b/project-14-github-actions-android/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — end-to-end CI/CD pipeline using GitHub Actions for Android Application + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-14-github-actions-android/START_HERE.md b/project-14-github-actions-android/START_HERE.md new file mode 100644 index 00000000..0af359ee --- /dev/null +++ b/project-14-github-actions-android/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-14-github-actions-android + +**Learning focus:** Android Gradle CI/CD with GitHub Actions + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, open `project.yaml` and then inspect `android-demo-app/.github/workflows/android.yml` +alongside the local validation command `./android-demo-app/gradlew -p android-demo-app tasks`, without +changing any student files or contacting GitHub. + +## Checkpoints + +1. 1. You can identify the Android project root, Gradle wrapper, and the three workflow files under `android-demo-app/.github/workflows/` +2. 1. The local Gradle validation completes or reports a concrete, locally reproducible error for `./android-demo-app/gradlew -p android-demo-app tasks` +3. 1. You can explain, from the YAML, which workflow step builds/tests or handles APK/artifact output and distinguish the cache-cleanup and artifact-deletion workflows from the main Android CI flow. + +## Hints if you are stuck + +1. 1. If the Gradle command is not found, verify that you are at the directory containing `android-demo-app` and that the wrapper path matches the one recorded in `project.yaml` +2. 1. If validation fails during setup, inspect the wrapper and Gradle configuration files before changing application code +3. 1. If the workflow roles are unclear, compare the filenames and triggers/steps in `android.yml`, `clear-caches.yml`, and `delete-artifacts.yml`, then trace referenced scripts under `android-demo-app/scripts/`. + +## Evidence to capture + +Annotated workflow-role map plus the unedited local Gradle validation output or captured error diagnosis + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-14-github-actions-android/active-path-manifest.tsv b/project-14-github-actions-android/active-path-manifest.tsv new file mode 100644 index 00000000..c4d7a1ec --- /dev/null +++ b/project-14-github-actions-android/active-path-manifest.tsv @@ -0,0 +1,6 @@ +# active local classroom paths for project-14-github-actions-android +README.md student project overview +START_HERE.md beginner-safe entry point +P2_CLASSROOM.md classroom worksheet +P2_EVIDENCE.md local evidence record +P2_LOCAL_PILOT.md local rehearsal record diff --git a/project-14-github-actions-android/ci-contract.yaml b/project-14-github-actions-android/ci-contract.yaml new file mode 100644 index 00000000..71ecd876 --- /dev/null +++ b/project-14-github-actions-android/ci-contract.yaml @@ -0,0 +1,8 @@ +--- +schema_version: "1.0" +project: project-14-github-actions-android +purpose: synthetic local CI contract fixture +authorization: none +local_only: true +contains_credentials: false +provider_actions_authorized: false diff --git a/project-14-github-actions-android/fixtures/clean-contract.txt b/project-14-github-actions-android/fixtures/clean-contract.txt new file mode 100644 index 00000000..b32b4eb1 --- /dev/null +++ b/project-14-github-actions-android/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-14-github-actions-android +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-14-github-actions-android/fixtures/evidence-local-result.txt b/project-14-github-actions-android/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..fa61a038 --- /dev/null +++ b/project-14-github-actions-android/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-14-github-actions-android +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-14-github-actions-android/fixtures/negative-contract.txt b/project-14-github-actions-android/fixtures/negative-contract.txt new file mode 100644 index 00000000..32b0299c --- /dev/null +++ b/project-14-github-actions-android/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-14-github-actions-android +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-14-github-actions-android/fixtures/signing-fixture.properties b/project-14-github-actions-android/fixtures/signing-fixture.properties new file mode 100644 index 00000000..65869c91 --- /dev/null +++ b/project-14-github-actions-android/fixtures/signing-fixture.properties @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-14-github-actions-android +path=fixtures/signing-fixture.properties +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-14-github-actions-android/negative-quarantine-probe.sh b/project-14-github-actions-android/negative-quarantine-probe.sh new file mode 100755 index 00000000..112d0b30 --- /dev/null +++ b/project-14-github-actions-android/negative-quarantine-probe.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-14-github-actions-android" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-14-github-actions-android' 'negative-quarantine-probe.sh' diff --git a/project-14-github-actions-android/reset-local.sh b/project-14-github-actions-android/reset-local.sh new file mode 100755 index 00000000..136324e6 --- /dev/null +++ b/project-14-github-actions-android/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-14-github-actions-android" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-14-github-actions-android' diff --git a/project-14-github-actions-android/tools/test_verify_ci_contract.py b/project-14-github-actions-android/tools/test_verify_ci_contract.py new file mode 100644 index 00000000..d0de4dd3 --- /dev/null +++ b/project-14-github-actions-android/tools/test_verify_ci_contract.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def test_local_classroom_prerequisites() -> None: + root = next( + path + for path in Path(__file__).resolve().parents + if path.name == "project-14-github-actions-android" + ) + assert (root / "README.md").is_file() + assert (root / "START_HERE.md").is_file() diff --git a/project-14-github-actions-android/tools/verify_ci_contract.py b/project-14-github-actions-android/tools/verify_ci_contract.py new file mode 100644 index 00000000..b4c40c4b --- /dev/null +++ b/project-14-github-actions-android/tools/verify_ci_contract.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +"""Validate local release evidence without contacting external systems.""" + +from pathlib import Path + +root = Path(__file__).resolve().parent +if not (root / "P2_EVIDENCE.md").is_file(): + raise SystemExit("ERROR: missing P2_EVIDENCE.md") +print( + "project-14-github-actions-android local evidence validation: PASS (verify_ci_contract.py)" +) diff --git a/project-14-github-actions-android/validate-local.sh b/project-14-github-actions-android/validate-local.sh new file mode 100755 index 00000000..1c52e08c --- /dev/null +++ b/project-14-github-actions-android/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-14-github-actions-android" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-14-github-actions-android' 'validate-local.sh' diff --git a/project-14-github-actions-android/validate-p2-local.sh b/project-14-github-actions-android/validate-p2-local.sh new file mode 100755 index 00000000..24bf4107 --- /dev/null +++ b/project-14-github-actions-android/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-14-github-actions-android" ]; then + printf '%s +' "ERROR: expected project-14-github-actions-android; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-14-github-actions-android' diff --git a/project-14-github-actions-android/validate-quarantine.sh b/project-14-github-actions-android/validate-quarantine.sh new file mode 100755 index 00000000..f2af1efa --- /dev/null +++ b/project-14-github-actions-android/validate-quarantine.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-14-github-actions-android" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-14-github-actions-android' 'validate-quarantine.sh' diff --git a/project-15-ecommerce-eks-helm/.env.example b/project-15-ecommerce-eks-helm/.env.example new file mode 100644 index 00000000..04f592c1 --- /dev/null +++ b/project-15-ecommerce-eks-helm/.env.example @@ -0,0 +1,4 @@ +# Synthetic local classroom configuration for project-15-ecommerce-eks-helm. +# Do not place live credentials, endpoints, or account identifiers in this file. +LOCAL_CLASSROOM_MODE=true +LOCAL_EVIDENCE_ONLY=true diff --git a/project-15-ecommerce-eks-helm/EVIDENCE_TEMPLATE.md b/project-15-ecommerce-eks-helm/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..94578467 --- /dev/null +++ b/project-15-ecommerce-eks-helm/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +| Field | Record | +| --- | --- | +| Project | `project-15-ecommerce-eks-helm` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-15-ecommerce-eks-helm/P0_REMEDIATION.md b/project-15-ecommerce-eks-helm/P0_REMEDIATION.md new file mode 100644 index 00000000..e320334f --- /dev/null +++ b/project-15-ecommerce-eks-helm/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +## Scope + +This record defines the active classroom path for `project-15-ecommerce-eks-helm`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-15-ecommerce-eks-helm/P2_CLASSROOM.md b/project-15-ecommerce-eks-helm/P2_CLASSROOM.md new file mode 100644 index 00000000..5cf119b8 --- /dev/null +++ b/project-15-ecommerce-eks-helm/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-15-ecommerce-eks-helm/P2_EVIDENCE.md b/project-15-ecommerce-eks-helm/P2_EVIDENCE.md new file mode 100644 index 00000000..ab51c2df --- /dev/null +++ b/project-15-ecommerce-eks-helm/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-15-ecommerce-eks-helm/P2_HARDENING.md b/project-15-ecommerce-eks-helm/P2_HARDENING.md new file mode 100644 index 00000000..acfc545a --- /dev/null +++ b/project-15-ecommerce-eks-helm/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-15-ecommerce-eks-helm/P2_LOCAL_PILOT.md b/project-15-ecommerce-eks-helm/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..619383a0 --- /dev/null +++ b/project-15-ecommerce-eks-helm/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploy an E-Commerce Three Tier application on AWS EKS with Helm + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-15-ecommerce-eks-helm/START_HERE.md b/project-15-ecommerce-eks-helm/START_HERE.md new file mode 100644 index 00000000..bf93a427 --- /dev/null +++ b/project-15-ecommerce-eks-helm/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-15-ecommerce-eks-helm + +**Learning focus:** Kubernetes application deployment architecture with Helm, AWS EKS, ALB ingress, and +EBS-backed three-tier services + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +In a local copy of the packet, map the README’s presentation, application, and data tiers to the RobotShop +Helm chart, `robot-shop` namespace, `ingress.yaml`, and the stated EKS add-ons without running any cloud or +deployment command. + +## Checkpoints + +1. 1. Produce a local dependency map that connects the EKS cluster, IAM/OIDC and load-balancer prerequisites, Helm chart, namespace, pods, and ingress to the three application tiers +2. 1. Annotate the readme with the required substitutions and verification points for `cluster_name`, region, VPC ID, AWS account ID, and the RobotShop chart path, while leaving commands unexecuted +3. 1. Submit a local validation checklist showing how successful completion would be recognized from the packet: the `aws-load-balancer-controller` deployment and RobotShop pods would be running, an ingress would expose a load-balancer DNS name, and the application workflow would reach registration, cart, checkout, and order placement. + +## Hints if you are stuck + +1. 1. If the tier map is unclear, start from the README’s definitions of presentation, application, and data responsibilities before examining the RobotShop chart location +2. 1. Treat every angle-bracket placeholder and each named AWS resource as a value that must be accounted for, not as literal text +3. 1. When a verification point fails in a controlled environment, compare the relevant layer’s prerequisite and namespace/resource name before changing unrelated steps. + +## Evidence to capture + +Local three-tier dependency map, placeholder/substitution checklist, and ordered verification rubric tied to +controller deployment, RobotShop pods, ingress DNS, and checkout flow + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-15-ecommerce-eks-helm/fixtures/clean-contract.txt b/project-15-ecommerce-eks-helm/fixtures/clean-contract.txt new file mode 100644 index 00000000..64148009 --- /dev/null +++ b/project-15-ecommerce-eks-helm/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-15-ecommerce-eks-helm +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-15-ecommerce-eks-helm/fixtures/evidence-local-result.txt b/project-15-ecommerce-eks-helm/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..9afe7f57 --- /dev/null +++ b/project-15-ecommerce-eks-helm/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-15-ecommerce-eks-helm +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-15-ecommerce-eks-helm/fixtures/negative-contract.txt b/project-15-ecommerce-eks-helm/fixtures/negative-contract.txt new file mode 100644 index 00000000..6aa43d75 --- /dev/null +++ b/project-15-ecommerce-eks-helm/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-15-ecommerce-eks-helm +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-15-ecommerce-eks-helm/local/web.conf b/project-15-ecommerce-eks-helm/local/web.conf new file mode 100644 index 00000000..39298a73 --- /dev/null +++ b/project-15-ecommerce-eks-helm/local/web.conf @@ -0,0 +1,3 @@ +# Local classroom configuration for project-15-ecommerce-eks-helm. +# Bind only to loopback when a separate instructor-approved local service is used. +listen 127.0.0.1:8080; diff --git a/project-15-ecommerce-eks-helm/reset-local.sh b/project-15-ecommerce-eks-helm/reset-local.sh new file mode 100755 index 00000000..fd43bf38 --- /dev/null +++ b/project-15-ecommerce-eks-helm/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-15-ecommerce-eks-helm" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-15-ecommerce-eks-helm' diff --git a/project-15-ecommerce-eks-helm/validate-local.sh b/project-15-ecommerce-eks-helm/validate-local.sh new file mode 100755 index 00000000..ca6af9c3 --- /dev/null +++ b/project-15-ecommerce-eks-helm/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-15-ecommerce-eks-helm" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-15-ecommerce-eks-helm' 'validate-local.sh' diff --git a/project-15-ecommerce-eks-helm/validate-p2-local.sh b/project-15-ecommerce-eks-helm/validate-p2-local.sh new file mode 100755 index 00000000..72940896 --- /dev/null +++ b/project-15-ecommerce-eks-helm/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-15-ecommerce-eks-helm" ]; then + printf '%s +' "ERROR: expected project-15-ecommerce-eks-helm; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-15-ecommerce-eks-helm' diff --git a/project-16-jenkins-argocd-k8s/EVIDENCE_TEMPLATE.md b/project-16-jenkins-argocd-k8s/EVIDENCE_TEMPLATE.md new file mode 100644 index 00000000..08ed2ef5 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/EVIDENCE_TEMPLATE.md @@ -0,0 +1,13 @@ +# Local Evidence Template — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +| Field | Record | +| --- | --- | +| Project | `project-16-jenkins-argocd-k8s` | +| Learner | [name or identifier] | +| Local validator | [command] | +| Result | [PASS or FAIL] | +| Fixture/control observed | [description] | +| Instructor feedback | [optional] | + +This template documents classroom source validation only. It is not approval for cloud access or an +operational change. diff --git a/project-16-jenkins-argocd-k8s/LOCAL_GITOPS_LAB.md b/project-16-jenkins-argocd-k8s/LOCAL_GITOPS_LAB.md new file mode 100644 index 00000000..39a7e034 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/LOCAL_GITOPS_LAB.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +This checked-in record is required by the active source contract for `project-16-jenkins-argocd-k8s`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-16-jenkins-argocd-k8s/P0_REMEDIATION.md b/project-16-jenkins-argocd-k8s/P0_REMEDIATION.md new file mode 100644 index 00000000..50c841c9 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +## Scope + +This record defines the active classroom path for `project-16-jenkins-argocd-k8s`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-16-jenkins-argocd-k8s/P2_CLASSROOM.md b/project-16-jenkins-argocd-k8s/P2_CLASSROOM.md new file mode 100644 index 00000000..d6f490fe --- /dev/null +++ b/project-16-jenkins-argocd-k8s/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-16-jenkins-argocd-k8s/P2_EVIDENCE.md b/project-16-jenkins-argocd-k8s/P2_EVIDENCE.md new file mode 100644 index 00000000..75f8d4e1 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-16-jenkins-argocd-k8s/P2_HARDENING.md b/project-16-jenkins-argocd-k8s/P2_HARDENING.md new file mode 100644 index 00000000..ea6fe067 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-16-jenkins-argocd-k8s/P2_LOCAL_PILOT.md b/project-16-jenkins-argocd-k8s/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..7563e656 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Real Time DevOps Project | Deploy to Kubernetes Using Jenkins | end-to-end DevOps Project | CI/CD + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-16-jenkins-argocd-k8s/START_HERE.md b/project-16-jenkins-argocd-k8s/START_HERE.md new file mode 100644 index 00000000..0ed6acb0 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-16-jenkins-argocd-k8s + +**Learning focus:** Jenkins CI/CD integration with SonarQube, Docker, Kubernetes, and Argo CD deployment +concepts + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read the readme locally and make a three-column map of the intended Jenkins-Master, Jenkins-Agent, and +EKS-Bootstrap roles without launching servers or changing any files. + +## Checkpoints + +1. 1. Produce a role-and-stage map that connects Jenkins controller/agent setup to the pipeline, SonarQube, Docker image, and Kubernetes/Argo CD stages named in the readme +2. 1. Annotate the readme with a local inventory of required inputs such as repository URL, credentials, host addresses, ports, and configuration values, marking each as a placeholder rather than supplying secrets +3. 1. Submit a short dry-run explanation of how a change would move from the register-app repository through Jenkins quality/build steps toward Kubernetes deployment, identifying which observations would confirm each handoff. + +## Hints if you are stuck + +1. 1. If the stages seem unclear, separate the README's named machines and services before trying to connect them into one flow +2. 1. When a handoff fails conceptually, check whether the required address, credential identifier, port, or plugin/tool configuration is present in the packet +3. 1. Treat commands, screenshots, and version-specific settings as claims to verify in a controlled lab rather than as permission to use AWS, expose ports, or paste real tokens. + +## Evidence to capture + +Annotated local stage/role diagram, placeholder-and-dependency inventory, and a dry-run CI/CD handoff +narrative + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-16-jenkins-argocd-k8s/active-path-manifest.tsv b/project-16-jenkins-argocd-k8s/active-path-manifest.tsv new file mode 100644 index 00000000..ea77a206 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/active-path-manifest.tsv @@ -0,0 +1,6 @@ +# active local classroom paths for project-16-jenkins-argocd-k8s +README.md student project overview +START_HERE.md beginner-safe entry point +P2_CLASSROOM.md classroom worksheet +P2_EVIDENCE.md local evidence record +P2_LOCAL_PILOT.md local rehearsal record diff --git a/project-16-jenkins-argocd-k8s/fixtures/clean-contract.txt b/project-16-jenkins-argocd-k8s/fixtures/clean-contract.txt new file mode 100644 index 00000000..be97931c --- /dev/null +++ b/project-16-jenkins-argocd-k8s/fixtures/clean-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-16-jenkins-argocd-k8s +path=fixtures/clean-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-16-jenkins-argocd-k8s/fixtures/evidence-local-result.txt b/project-16-jenkins-argocd-k8s/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..cc2d47dd --- /dev/null +++ b/project-16-jenkins-argocd-k8s/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-16-jenkins-argocd-k8s +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-16-jenkins-argocd-k8s/fixtures/negative-contract.txt b/project-16-jenkins-argocd-k8s/fixtures/negative-contract.txt new file mode 100644 index 00000000..6cc6aaa3 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/fixtures/negative-contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-16-jenkins-argocd-k8s +path=fixtures/negative-contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-16-jenkins-argocd-k8s/local-fixture/desired-state.json b/project-16-jenkins-argocd-k8s/local-fixture/desired-state.json new file mode 100644 index 00000000..16918b68 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/local-fixture/desired-state.json @@ -0,0 +1,12 @@ +{ + "authorization": "none", + "contains_credentials": false, + "desired_state": { + "application": "sample-app", + "environment": "local-fixture", + "replicas": 1 + }, + "project": "project-16-jenkins-argocd-k8s", + "purpose": "synthetic desired-state fixture for local-first validation", + "schema_version": "1.0" +} diff --git a/project-16-jenkins-argocd-k8s/local-fixture/manifests/app.json b/project-16-jenkins-argocd-k8s/local-fixture/manifests/app.json new file mode 100644 index 00000000..c7055b48 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/local-fixture/manifests/app.json @@ -0,0 +1,12 @@ +{ + "apiVersion": "v1", + "data": { + "mode": "synthetic-local-validation", + "provider_access": "not-authorized" + }, + "kind": "ConfigMap", + "metadata": { + "name": "local-fixture-app", + "namespace": "classroom-local" + } +} diff --git a/project-16-jenkins-argocd-k8s/local_delivery.py b/project-16-jenkins-argocd-k8s/local_delivery.py new file mode 100644 index 00000000..334b6b95 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/local_delivery.py @@ -0,0 +1,19 @@ +"""Local-only teaching helper for project-16-jenkins-argocd-k8s. + +This reconstructed module contains no remote service, cloud credential, or deployment +behavior. It is intentionally deterministic for classroom evidence. +""" + +from __future__ import annotations + + +def local_status() -> dict[str, str]: + return { + "project": "project-16-jenkins-argocd-k8s", + "mode": "local-first", + "status": "ready-for-local-validation", + } + + +if __name__ == "__main__": + print(local_status()) diff --git a/project-16-jenkins-argocd-k8s/negative-quarantine-probe.sh b/project-16-jenkins-argocd-k8s/negative-quarantine-probe.sh new file mode 100755 index 00000000..109aebcc --- /dev/null +++ b/project-16-jenkins-argocd-k8s/negative-quarantine-probe.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-16-jenkins-argocd-k8s" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-16-jenkins-argocd-k8s' 'negative-quarantine-probe.sh' diff --git a/project-16-jenkins-argocd-k8s/reset-local.sh b/project-16-jenkins-argocd-k8s/reset-local.sh new file mode 100755 index 00000000..facf3a9c --- /dev/null +++ b/project-16-jenkins-argocd-k8s/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-16-jenkins-argocd-k8s" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-16-jenkins-argocd-k8s' diff --git a/project-16-jenkins-argocd-k8s/test_local_delivery.py b/project-16-jenkins-argocd-k8s/test_local_delivery.py new file mode 100644 index 00000000..575aff1f --- /dev/null +++ b/project-16-jenkins-argocd-k8s/test_local_delivery.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def test_local_classroom_prerequisites() -> None: + root = next( + path + for path in Path(__file__).resolve().parents + if path.name == "project-16-jenkins-argocd-k8s" + ) + assert (root / "README.md").is_file() + assert (root / "START_HERE.md").is_file() diff --git a/project-16-jenkins-argocd-k8s/validate-p2-local.sh b/project-16-jenkins-argocd-k8s/validate-p2-local.sh new file mode 100755 index 00000000..378a31f0 --- /dev/null +++ b/project-16-jenkins-argocd-k8s/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-16-jenkins-argocd-k8s" ]; then + printf '%s +' "ERROR: expected project-16-jenkins-argocd-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-16-jenkins-argocd-k8s' diff --git a/project-16-jenkins-argocd-k8s/validate-quarantine.sh b/project-16-jenkins-argocd-k8s/validate-quarantine.sh new file mode 100755 index 00000000..1f2fc16c --- /dev/null +++ b/project-16-jenkins-argocd-k8s/validate-quarantine.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-16-jenkins-argocd-k8s" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-16-jenkins-argocd-k8s' 'validate-quarantine.sh' diff --git a/project-17-aks-azure-devops/P2_CLASSROOM.md b/project-17-aks-azure-devops/P2_CLASSROOM.md new file mode 100644 index 00000000..9453c81c --- /dev/null +++ b/project-17-aks-azure-devops/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Deploying an app to AKS using Azure DevOps & Azure Cloud Shell + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-17-aks-azure-devops/P2_EVIDENCE.md b/project-17-aks-azure-devops/P2_EVIDENCE.md new file mode 100644 index 00000000..16554df4 --- /dev/null +++ b/project-17-aks-azure-devops/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Deploying an app to AKS using Azure DevOps & Azure Cloud Shell + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-17-aks-azure-devops/P2_HARDENING.md b/project-17-aks-azure-devops/P2_HARDENING.md new file mode 100644 index 00000000..a6ca19e2 --- /dev/null +++ b/project-17-aks-azure-devops/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Deploying an app to AKS using Azure DevOps & Azure Cloud Shell + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-17-aks-azure-devops/P2_LOCAL_PILOT.md b/project-17-aks-azure-devops/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..02a2202b --- /dev/null +++ b/project-17-aks-azure-devops/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Deploying an app to AKS using Azure DevOps & Azure Cloud Shell + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-17-aks-azure-devops/START_HERE.md b/project-17-aks-azure-devops/START_HERE.md new file mode 100644 index 00000000..bfd10006 --- /dev/null +++ b/project-17-aks-azure-devops/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-17-aks-azure-devops + +**Learning focus:** AKS container deployment and Azure DevOps CI/CD pipeline integration + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the local README.md and annotate the architecture paragraph by labeling GitHub, Azure DevOps, ACR, AKS, +and Azure Active Directory as source, pipeline, registry, runtime, and identity components. + +## Checkpoints + +1. 1. Produce a local component map that connects GitHub source to Azure DevOps, ACR, AKS, and the Azure identity/service-principal role +2. 1. Trace the README’s documented sequence from project setup through image build/push and Kubernetes deployment without running any cloud commands +3. 1. Mark every placeholder, credential-bearing step, and resource-name inconsistency in the readme, including the differing ACR names, and explain why each requires instructor review. + +## Hints if you are stuck + +1. 1. Compare each command’s resource group, cluster, registry, organization, project, and repository names with the names introduced earlier +2. 1. Treat PATs, service-principal output, passwords, and account access as sensitive prerequisites rather than values to invent or commit +3. 1. Use the architecture and Summary sections to check whether your component map explains both the container image path and the Kubernetes service’s external access. + +## Evidence to capture + +Annotated local readme component/sequence map plus a flagged list of placeholders, sensitive inputs, and +naming inconsistencies + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-17-aks-azure-devops/fixtures/clean_local.txt b/project-17-aks-azure-devops/fixtures/clean_local.txt new file mode 100644 index 00000000..6eee2d7c --- /dev/null +++ b/project-17-aks-azure-devops/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-17-aks-azure-devops +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-17-aks-azure-devops/fixtures/evidence-local-result.txt b/project-17-aks-azure-devops/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..c7efb41d --- /dev/null +++ b/project-17-aks-azure-devops/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-17-aks-azure-devops +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-17-aks-azure-devops/fixtures/negative_cloud_command.txt b/project-17-aks-azure-devops/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..6d90deee --- /dev/null +++ b/project-17-aks-azure-devops/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-17-aks-azure-devops +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-17-aks-azure-devops/validate-p2-local.sh b/project-17-aks-azure-devops/validate-p2-local.sh new file mode 100755 index 00000000..a5cbb825 --- /dev/null +++ b/project-17-aks-azure-devops/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-17-aks-azure-devops" ]; then + printf '%s +' "ERROR: expected project-17-aks-azure-devops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-17-aks-azure-devops' diff --git a/project-17-aks-azure-devops/validate_local.py b/project-17-aks-azure-devops/validate_local.py new file mode 100755 index 00000000..884dbdab --- /dev/null +++ b/project-17-aks-azure-devops/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-17-aks-azure-devops.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-17-aks-azure-devops": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-17-aks-azure-devops local-only control: PASS (validate_local.py)") diff --git a/project-18-jenkins-java-full-cicd/.p1_active_paths b/project-18-jenkins-java-full-cicd/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-18-jenkins-java-full-cicd/P1_LOCAL_CONTRACT.md b/project-18-jenkins-java-full-cicd/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..ef4193ba --- /dev/null +++ b/project-18-jenkins-java-full-cicd/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-18-jenkins-java-full-cicd/P2_CLASSROOM.md b/project-18-jenkins-java-full-cicd/P2_CLASSROOM.md new file mode 100644 index 00000000..53515b00 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-18-jenkins-java-full-cicd/P2_EVIDENCE.md b/project-18-jenkins-java-full-cicd/P2_EVIDENCE.md new file mode 100644 index 00000000..5995f501 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-18-jenkins-java-full-cicd/P2_HARDENING.md b/project-18-jenkins-java-full-cicd/P2_HARDENING.md new file mode 100644 index 00000000..f28cf17a --- /dev/null +++ b/project-18-jenkins-java-full-cicd/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-18-jenkins-java-full-cicd/P2_LOCAL_PILOT.md b/project-18-jenkins-java-full-cicd/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..5e61c11d --- /dev/null +++ b/project-18-jenkins-java-full-cicd/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-18-jenkins-java-full-cicd/START_HERE.md b/project-18-jenkins-java-full-cicd/START_HERE.md new file mode 100644 index 00000000..29c65a1d --- /dev/null +++ b/project-18-jenkins-java-full-cicd/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-18-jenkins-java-full-cicd + +**Learning focus:** Beginner Java/Spring Boot CI/CD and DevSecOps pipeline concepts + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `mvn -q -f spring-boot-app/pom.xml test` to establish the local Maven test baseline +before touching Docker, Jenkins, SonarQube, Helm, Argo CD, or Kubernetes. + +## Checkpoints + +1. 1. The Maven command completes and produces a passing local test result for `spring-boot-app` +2. 1. `mvn clean package` creates the Spring Boot artifact under `spring-boot-app/target`, which the learner can identify without deploying it +3. 1. The learner can run the packaged application locally and observe the web page at `http://localhost:8080`, then relate the JenkinsFile stages and Kubernetes manifests to checkout, build, scan, package, and deployment concepts without executing a live deployment. + +## Hints if you are stuck + +1. 1. If Maven fails immediately, compare the installed Java/Maven versions with the Spring Boot project's `pom.xml` expectations and read the first error rather than the final summary +2. 1. If the packaged application is not found, verify that the command was run from the project root and that the artifact was created in `spring-boot-app/target` +3. 1. If the local page is unreachable, check whether the Java process is still running and whether the URL and port match the README's local command, without changing the Kubernetes or Jenkins files. + +## Evidence to capture + +Terminal capture of passing Maven tests, the generated JAR in `spring-boot-app/target`, and a local browser +view of the Spring Boot page, plus a short stage-to-file mapping for `JenkinsFile`, `Dockerfile`, and the +Kubernetes manifests. + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-18-jenkins-java-full-cicd/fixtures/clean/contract.txt b/project-18-jenkins-java-full-cicd/fixtures/clean/contract.txt new file mode 100644 index 00000000..b240d6cb --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/clean/p2-clean.txt b/project-18-jenkins-java-full-cicd/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..f649a97d --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/evidence-local-result.txt b/project-18-jenkins-java-full-cicd/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..2589b2a5 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/negative/credential.txt b/project-18-jenkins-java-full-cicd/fixtures/negative/credential.txt new file mode 100644 index 00000000..25deba8b --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/negative/mutation.txt b/project-18-jenkins-java-full-cicd/fixtures/negative/mutation.txt new file mode 100644 index 00000000..0ead2c1d --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/negative/p2-source-shaped.txt b/project-18-jenkins-java-full-cicd/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..d57203ea --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/fixtures/negative/public_bind.txt b/project-18-jenkins-java-full-cicd/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..c633caf8 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-18-jenkins-java-full-cicd +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-18-jenkins-java-full-cicd/local-lab/contract.json b/project-18-jenkins-java-full-cicd/local-lab/contract.json new file mode 100644 index 00000000..3b35dd9a --- /dev/null +++ b/project-18-jenkins-java-full-cicd/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-18-jenkins-java-full-cicd", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-18-jenkins-java-full-cicd/reset-p2-local.sh b/project-18-jenkins-java-full-cicd/reset-p2-local.sh new file mode 100755 index 00000000..2828bc95 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-18-jenkins-java-full-cicd" ]; then + printf '%s +' "ERROR: expected project-18-jenkins-java-full-cicd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-18-jenkins-java-full-cicd' diff --git a/project-18-jenkins-java-full-cicd/validate-p1-stream3.sh b/project-18-jenkins-java-full-cicd/validate-p1-stream3.sh new file mode 100755 index 00000000..f96e7714 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-18-jenkins-java-full-cicd" ]; then + printf '%s +' "ERROR: expected project-18-jenkins-java-full-cicd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-18-jenkins-java-full-cicd' diff --git a/project-18-jenkins-java-full-cicd/validate-p2-local.sh b/project-18-jenkins-java-full-cicd/validate-p2-local.sh new file mode 100755 index 00000000..2828bc95 --- /dev/null +++ b/project-18-jenkins-java-full-cicd/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-18-jenkins-java-full-cicd" ]; then + printf '%s +' "ERROR: expected project-18-jenkins-java-full-cicd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-18-jenkins-java-full-cicd' diff --git a/project-19-eks-jenkins-terraform/INSTRUCTOR_BOUNDARY.md b/project-19-eks-jenkins-terraform/INSTRUCTOR_BOUNDARY.md new file mode 100644 index 00000000..a1c7f5bb --- /dev/null +++ b/project-19-eks-jenkins-terraform/INSTRUCTOR_BOUNDARY.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-19-eks-jenkins-terraform`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-19-eks-jenkins-terraform/P0_REMEDIATION.md b/project-19-eks-jenkins-terraform/P0_REMEDIATION.md new file mode 100644 index 00000000..485448df --- /dev/null +++ b/project-19-eks-jenkins-terraform/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +## Scope + +This record defines the active classroom path for `project-19-eks-jenkins-terraform`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-19-eks-jenkins-terraform/P1_REMEDIATION.md b/project-19-eks-jenkins-terraform/P1_REMEDIATION.md new file mode 100644 index 00000000..a1c7f5bb --- /dev/null +++ b/project-19-eks-jenkins-terraform/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-19-eks-jenkins-terraform`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-19-eks-jenkins-terraform/P2_CLASSROOM.md b/project-19-eks-jenkins-terraform/P2_CLASSROOM.md new file mode 100644 index 00000000..2f00b8cd --- /dev/null +++ b/project-19-eks-jenkins-terraform/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-19-eks-jenkins-terraform/P2_EVIDENCE.md b/project-19-eks-jenkins-terraform/P2_EVIDENCE.md new file mode 100644 index 00000000..70b3ebeb --- /dev/null +++ b/project-19-eks-jenkins-terraform/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-19-eks-jenkins-terraform/P2_HARDENING.md b/project-19-eks-jenkins-terraform/P2_HARDENING.md new file mode 100644 index 00000000..b47f0a5d --- /dev/null +++ b/project-19-eks-jenkins-terraform/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-19-eks-jenkins-terraform/P2_LOCAL_PILOT.md b/project-19-eks-jenkins-terraform/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..5bdcc84f --- /dev/null +++ b/project-19-eks-jenkins-terraform/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-19-eks-jenkins-terraform/QUARANTINE.md b/project-19-eks-jenkins-terraform/QUARANTINE.md new file mode 100644 index 00000000..a1c7f5bb --- /dev/null +++ b/project-19-eks-jenkins-terraform/QUARANTINE.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — From Scratch to Production: Deploying EKS Clusters and Applications with CI/CD using Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-19-eks-jenkins-terraform`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-19-eks-jenkins-terraform/START_HERE.md b/project-19-eks-jenkins-terraform/START_HERE.md new file mode 100644 index 00000000..2f4e769b --- /dev/null +++ b/project-19-eks-jenkins-terraform/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-19-eks-jenkins-terraform + +**Learning focus:** AWS infrastructure-as-code and Kubernetes CI/CD with Terraform, EKS, and Jenkins + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, open README.md and make a local inventory table mapping each stated stage to its +corresponding Terraform, Jenkins, shell-script, and Kubernetes manifest file without running any commands. + +## Checkpoints + +1. 1. The learner can point to the files implementing the three infrastructure/application layers: jenkins_server/tf-aws-ec2, tf-aws-eks, and manifest +2. 1. The learner can annotate the README's sequence from Jenkins server provisioning through EKS Terraform validation to Kubernetes application delivery and Jenkins pipeline configuration +3. 1. The learner can produce a local dependency sketch showing that the EC2 bootstrap script supports Jenkins tooling, tf-aws-eks defines the VPC/EKS resources, and the manifest files define the Nginx workload and service. + +## Hints if you are stuck + +1. 1. If the file-to-stage mapping is unclear, use the active filenames and the readme headings rather than starting with the command examples +2. 1. If Terraform responsibilities seem mixed together, separate the jenkins_server/tf-aws-ec2 directory from tf-aws-eks and inspect their backend, provider, variable, and resource/module files as distinct units +3. 1. If the Kubernetes portion is hard to trace, compare the names and fields in manifest/deployment.yaml and manifest/service.yaml with the example kubectl output, without attempting to connect to a cluster. + +## Evidence to capture + +Annotated local architecture/dependency map plus a stage-to-file inventory and a short explanation of the +Terraform, Jenkins, and Kubernetes handoffs + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-19-eks-jenkins-terraform/ci/local-ci.sh b/project-19-eks-jenkins-terraform/ci/local-ci.sh new file mode 100755 index 00000000..eaedf0de --- /dev/null +++ b/project-19-eks-jenkins-terraform/ci/local-ci.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-19-eks-jenkins-terraform" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-19-eks-jenkins-terraform' 'local-ci.sh' diff --git a/project-19-eks-jenkins-terraform/fixtures/clean/pipeline.yml b/project-19-eks-jenkins-terraform/fixtures/clean/pipeline.yml new file mode 100644 index 00000000..1972991d --- /dev/null +++ b/project-19-eks-jenkins-terraform/fixtures/clean/pipeline.yml @@ -0,0 +1,8 @@ +--- +schema_version: "1.0" +project: project-19-eks-jenkins-terraform +fixture: clean-pipeline +purpose: deterministic local-first validation only +authorization: none +contains_credentials: false +provider_actions_authorized: false diff --git a/project-19-eks-jenkins-terraform/fixtures/evidence-local-result.txt b/project-19-eks-jenkins-terraform/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a15b678c --- /dev/null +++ b/project-19-eks-jenkins-terraform/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-19-eks-jenkins-terraform +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-19-eks-jenkins-terraform/tests/test_policy.py b/project-19-eks-jenkins-terraform/tests/test_policy.py new file mode 100644 index 00000000..8a6b7132 --- /dev/null +++ b/project-19-eks-jenkins-terraform/tests/test_policy.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def test_local_classroom_prerequisites() -> None: + root = next( + path + for path in Path(__file__).resolve().parents + if path.name == "project-19-eks-jenkins-terraform" + ) + assert (root / "README.md").is_file() + assert (root / "START_HERE.md").is_file() diff --git a/project-19-eks-jenkins-terraform/validate-local.sh b/project-19-eks-jenkins-terraform/validate-local.sh new file mode 100755 index 00000000..0646c397 --- /dev/null +++ b/project-19-eks-jenkins-terraform/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-19-eks-jenkins-terraform" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-19-eks-jenkins-terraform' 'validate-local.sh' diff --git a/project-19-eks-jenkins-terraform/validate-p2-local.sh b/project-19-eks-jenkins-terraform/validate-p2-local.sh new file mode 100755 index 00000000..68f148b0 --- /dev/null +++ b/project-19-eks-jenkins-terraform/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-19-eks-jenkins-terraform" ]; then + printf '%s +' "ERROR: expected project-19-eks-jenkins-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-19-eks-jenkins-terraform' diff --git a/project-20-azure-terraform-pipeline/P2_CLASSROOM.md b/project-20-azure-terraform-pipeline/P2_CLASSROOM.md new file mode 100644 index 00000000..d1d7e9e1 --- /dev/null +++ b/project-20-azure-terraform-pipeline/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Azure DevOps pipeline + Terraform Deployment Tutorial + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-20-azure-terraform-pipeline/P2_EVIDENCE.md b/project-20-azure-terraform-pipeline/P2_EVIDENCE.md new file mode 100644 index 00000000..050b59df --- /dev/null +++ b/project-20-azure-terraform-pipeline/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Azure DevOps pipeline + Terraform Deployment Tutorial + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-20-azure-terraform-pipeline/P2_HARDENING.md b/project-20-azure-terraform-pipeline/P2_HARDENING.md new file mode 100644 index 00000000..002a7360 --- /dev/null +++ b/project-20-azure-terraform-pipeline/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Azure DevOps pipeline + Terraform Deployment Tutorial + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-20-azure-terraform-pipeline/P2_LOCAL_PILOT.md b/project-20-azure-terraform-pipeline/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..819b15eb --- /dev/null +++ b/project-20-azure-terraform-pipeline/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Azure DevOps pipeline + Terraform Deployment Tutorial + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-20-azure-terraform-pipeline/START_HERE.md b/project-20-azure-terraform-pipeline/START_HERE.md new file mode 100644 index 00000000..42ff6571 --- /dev/null +++ b/project-20-azure-terraform-pipeline/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-20-azure-terraform-pipeline + +**Learning focus:** Terraform infrastructure-as-code and Azure DevOps CI/CD pipeline structure + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open `README.md`, `deploy/tfdemo-env01-terraform.yml`, `deploy/templates/terraform-template.yml`, and the +`terraform/` files locally, then run only the packet’s stated validation command `terraform -chdir=terraform +fmt -check`. + +## Checkpoints + +1. 1. The learner can identify the root pipeline file, reusable template, Terraform provider/backend configuration, variables, resource definitions, and the packet’s local formatting validation command +2. 1. The learner can trace how `tfdemo-env01-terraform.yml` supplies `rootFolder`, `tfvarsFile`, and `adoEnvironment` to the template and how the template separates `Terraform_Plan` from gated `Terraform_Apply` +3. 1. The learner can explain from the code and readme that the Terraform resources are one resource group, one Service Bus namespace, and two queues, while documenting the plan/approval flow without running or approving a cloud deployment. + +## Hints if you are stuck + +1. 1. If the pipeline structure is unclear, start at the file that calls the template and follow each parameter into the template before inspecting the Terraform files +2. 1. If local validation fails, check formatting and working-directory assumptions first, and compare the command with the `validation.command` recorded in `project.yaml` +3. 1. If authentication or backend details seem confusing, distinguish the Terraform backend settings and variable-group names from resource declarations, and do not place secrets in repository files. + +## Evidence to capture + +Annotated local file map; successful or explained `terraform fmt -check` result; parameter/data-flow notes +linking the env01 pipeline to its template and Terraform inputs; a no-cloud plan/approval sequence diagram or +written trace + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-20-azure-terraform-pipeline/fixtures/clean_local.txt b/project-20-azure-terraform-pipeline/fixtures/clean_local.txt new file mode 100644 index 00000000..6732f7b2 --- /dev/null +++ b/project-20-azure-terraform-pipeline/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-20-azure-terraform-pipeline +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-20-azure-terraform-pipeline/fixtures/evidence-local-result.txt b/project-20-azure-terraform-pipeline/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..16eb491c --- /dev/null +++ b/project-20-azure-terraform-pipeline/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-20-azure-terraform-pipeline +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-20-azure-terraform-pipeline/fixtures/negative_cloud_command.txt b/project-20-azure-terraform-pipeline/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..f9cf846b --- /dev/null +++ b/project-20-azure-terraform-pipeline/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-20-azure-terraform-pipeline +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-20-azure-terraform-pipeline/validate-p2-local.sh b/project-20-azure-terraform-pipeline/validate-p2-local.sh new file mode 100755 index 00000000..ff4f9617 --- /dev/null +++ b/project-20-azure-terraform-pipeline/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-20-azure-terraform-pipeline" ]; then + printf '%s +' "ERROR: expected project-20-azure-terraform-pipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-20-azure-terraform-pipeline' diff --git a/project-20-azure-terraform-pipeline/validate_local.py b/project-20-azure-terraform-pipeline/validate_local.py new file mode 100755 index 00000000..c8097986 --- /dev/null +++ b/project-20-azure-terraform-pipeline/validate_local.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-20-azure-terraform-pipeline.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-20-azure-terraform-pipeline": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-20-azure-terraform-pipeline local-only control: PASS (validate_local.py)" +) diff --git a/project-21-aws-codepipeline/.p1_active_paths b/project-21-aws-codepipeline/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-21-aws-codepipeline/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-21-aws-codepipeline/P1_LOCAL_CONTRACT.md b/project-21-aws-codepipeline/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..832b114d --- /dev/null +++ b/project-21-aws-codepipeline/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — AWS DevOps CICD Pipeline + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-21-aws-codepipeline/P2_CLASSROOM.md b/project-21-aws-codepipeline/P2_CLASSROOM.md new file mode 100644 index 00000000..e41c8b22 --- /dev/null +++ b/project-21-aws-codepipeline/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — AWS DevOps CICD Pipeline + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-21-aws-codepipeline/P2_EVIDENCE.md b/project-21-aws-codepipeline/P2_EVIDENCE.md new file mode 100644 index 00000000..c73c74f3 --- /dev/null +++ b/project-21-aws-codepipeline/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — AWS DevOps CICD Pipeline + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-21-aws-codepipeline/P2_HARDENING.md b/project-21-aws-codepipeline/P2_HARDENING.md new file mode 100644 index 00000000..f164b696 --- /dev/null +++ b/project-21-aws-codepipeline/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — AWS DevOps CICD Pipeline + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-21-aws-codepipeline/P2_LOCAL_PILOT.md b/project-21-aws-codepipeline/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..69d45921 --- /dev/null +++ b/project-21-aws-codepipeline/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — AWS DevOps CICD Pipeline + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-21-aws-codepipeline/START_HERE.md b/project-21-aws-codepipeline/START_HERE.md new file mode 100644 index 00000000..f26b9a88 --- /dev/null +++ b/project-21-aws-codepipeline/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-21-aws-codepipeline + +**Learning focus:** AWS DevOps CI/CD for a Dockerized React/Vite video-streaming application + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read the readme and inspect `project.yaml`, `buildspec.yaml`, `appspec.yml`, +`Dockerfile`, and `package.json` before making any changes or attempting cloud access. + +## Checkpoints + +1. 1. You can identify the local React/Vite application entry points and explain the roles of `Dockerfile`, `buildspec.yaml`, `appspec.yml`, and `project.yaml` +2. 1. `npm run build` completes locally and produces the Vite build output without changing deployment configuration +3. 1. You can trace the documented source-to-build-to-deploy flow from CodeCommit through CodeBuild and DockerHub/S3 artifacts to CodeDeploy and an EC2 target, while noting where System Manager parameters are used. + +## Hints if you are stuck + +1. 1. If the local build fails, compare the command and dependency declarations in `package.json` with the project’s installed Node/npm environment before changing application code +2. 1. For a pipeline-file question, check whether the relevant behavior belongs to the Docker image, the CodeBuild phases, or the CodeDeploy lifecycle configuration +3. 1. When a stage cannot be reasoned about locally, use the filenames and readme headings to map its inputs and outputs rather than inventing AWS resource values or credentials. + +## Evidence to capture + +Local build output plus a short annotated pipeline map covering source, build, image/artifact, deployment, and +secret-parameter roles + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-21-aws-codepipeline/fixtures/clean/contract.txt b/project-21-aws-codepipeline/fixtures/clean/contract.txt new file mode 100644 index 00000000..fb1748e8 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/clean/p2-clean.txt b/project-21-aws-codepipeline/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..737590f5 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/evidence-local-result.txt b/project-21-aws-codepipeline/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..cfce0b64 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/negative/credential.txt b/project-21-aws-codepipeline/fixtures/negative/credential.txt new file mode 100644 index 00000000..d01cb7c5 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/negative/mutation.txt b/project-21-aws-codepipeline/fixtures/negative/mutation.txt new file mode 100644 index 00000000..7e76d6c9 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/negative/p2-source-shaped.txt b/project-21-aws-codepipeline/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..1b0b85f3 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/fixtures/negative/public_bind.txt b/project-21-aws-codepipeline/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..f58cf621 --- /dev/null +++ b/project-21-aws-codepipeline/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-21-aws-codepipeline +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-21-aws-codepipeline/local-lab/contract.json b/project-21-aws-codepipeline/local-lab/contract.json new file mode 100644 index 00000000..ed4b7969 --- /dev/null +++ b/project-21-aws-codepipeline/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-21-aws-codepipeline", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-21-aws-codepipeline/reset-p2-local.sh b/project-21-aws-codepipeline/reset-p2-local.sh new file mode 100755 index 00000000..6088dd6d --- /dev/null +++ b/project-21-aws-codepipeline/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-21-aws-codepipeline" ]; then + printf '%s +' "ERROR: expected project-21-aws-codepipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-21-aws-codepipeline' diff --git a/project-21-aws-codepipeline/validate-p1-stream3.sh b/project-21-aws-codepipeline/validate-p1-stream3.sh new file mode 100755 index 00000000..7d079432 --- /dev/null +++ b/project-21-aws-codepipeline/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-21-aws-codepipeline" ]; then + printf '%s +' "ERROR: expected project-21-aws-codepipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-21-aws-codepipeline' diff --git a/project-21-aws-codepipeline/validate-p2-local.sh b/project-21-aws-codepipeline/validate-p2-local.sh new file mode 100755 index 00000000..6088dd6d --- /dev/null +++ b/project-21-aws-codepipeline/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-21-aws-codepipeline" ]; then + printf '%s +' "ERROR: expected project-21-aws-codepipeline; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-21-aws-codepipeline' diff --git a/project-22-aws-serverless/P0_REMEDIATION.md b/project-22-aws-serverless/P0_REMEDIATION.md new file mode 100644 index 00000000..cb946225 --- /dev/null +++ b/project-22-aws-serverless/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — AWS Fully Serverless Architecture with CI/CD + +## Scope + +This record defines the active classroom path for `project-22-aws-serverless`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-22-aws-serverless/P1_REMEDIATION.md b/project-22-aws-serverless/P1_REMEDIATION.md new file mode 100644 index 00000000..ea7c72c6 --- /dev/null +++ b/project-22-aws-serverless/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — AWS Fully Serverless Architecture with CI/CD + +This checked-in record is required by the active source contract for `project-22-aws-serverless`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-22-aws-serverless/P2_CLASSROOM.md b/project-22-aws-serverless/P2_CLASSROOM.md new file mode 100644 index 00000000..e8823aef --- /dev/null +++ b/project-22-aws-serverless/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — AWS Fully Serverless Architecture with CI/CD + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-22-aws-serverless/P2_EVIDENCE.md b/project-22-aws-serverless/P2_EVIDENCE.md new file mode 100644 index 00000000..5076ac57 --- /dev/null +++ b/project-22-aws-serverless/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — AWS Fully Serverless Architecture with CI/CD + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-22-aws-serverless/P2_HARDENING.md b/project-22-aws-serverless/P2_HARDENING.md new file mode 100644 index 00000000..787e4217 --- /dev/null +++ b/project-22-aws-serverless/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — AWS Fully Serverless Architecture with CI/CD + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-22-aws-serverless/P2_LOCAL_PILOT.md b/project-22-aws-serverless/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..700fe552 --- /dev/null +++ b/project-22-aws-serverless/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — AWS Fully Serverless Architecture with CI/CD + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-22-aws-serverless/START_HERE.md b/project-22-aws-serverless/START_HERE.md new file mode 100644 index 00000000..a204f8d3 --- /dev/null +++ b/project-22-aws-serverless/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-22-aws-serverless + +**Learning focus:** AWS serverless API architecture, Terraform IaC, and CI/CD + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `terraform fmt -check` and inspect the README’s local `serverless-api` +prerequisites before considering any cloud-related action. + +## Checkpoints + +1. 1. The formatting check reports the Terraform files are correctly formatted +2. 1. In `serverless-api`, the learner can identify the Node.js entry point, route definitions, controllers, models, and service layer and can explain how `/healthz` differs from the user and product routes +3. 1. After following the documented local setup in a non-cloud environment, the learner records the test result or a clearly identified dependency/configuration blocker without attempting `terraform apply`. + +## Hints if you are stuck + +1. 1. If the formatting check fails, compare the reported files with the expected Terraform formatting rather than changing infrastructure behavior +2. 1. If the local Node.js process or tests fail, verify that dependencies were installed from the existing `package.json` and that the command is being run inside `serverless-api` +3. 1. If an API route behaves unexpectedly, trace the path from `routes.js` through its controller and service/model dependencies before changing code. + +## Evidence to capture + +Terraform format-check output; a brief local component-and-route map; local test or startup output with any +blocker and supporting error text + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-22-aws-serverless/SUPPORTED_VERSIONS.md b/project-22-aws-serverless/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..c267cd58 --- /dev/null +++ b/project-22-aws-serverless/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — AWS Fully Serverless Architecture with CI/CD + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-22-aws-serverless/fixtures/evidence-local-result.txt b/project-22-aws-serverless/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..37600419 --- /dev/null +++ b/project-22-aws-serverless/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-22-aws-serverless +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-22-aws-serverless/validate-local.sh b/project-22-aws-serverless/validate-local.sh new file mode 100755 index 00000000..18a1f7f6 --- /dev/null +++ b/project-22-aws-serverless/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-22-aws-serverless" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-22-aws-serverless' 'validate-local.sh' diff --git a/project-22-aws-serverless/validate-p1-stream2.sh b/project-22-aws-serverless/validate-p1-stream2.sh new file mode 100755 index 00000000..d84dc28e --- /dev/null +++ b/project-22-aws-serverless/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-22-aws-serverless" ]; then + printf '%s +' "ERROR: expected project-22-aws-serverless; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-22-aws-serverless' diff --git a/project-22-aws-serverless/validate-p2-local.sh b/project-22-aws-serverless/validate-p2-local.sh new file mode 100755 index 00000000..146957f3 --- /dev/null +++ b/project-22-aws-serverless/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-22-aws-serverless" ]; then + printf '%s +' "ERROR: expected project-22-aws-serverless; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-22-aws-serverless' diff --git a/project-23-swiggy-clone-ecs/.p1_active_paths b/project-23-swiggy-clone-ecs/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-23-swiggy-clone-ecs/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-23-swiggy-clone-ecs/P1_LOCAL_CONTRACT.md b/project-23-swiggy-clone-ecs/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..211e028d --- /dev/null +++ b/project-23-swiggy-clone-ecs/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — DevSecOps: Blue-Green Deployment of Swiggy-Clone on AWS ECS with AWS Code Pipeline + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-23-swiggy-clone-ecs/P2_CLASSROOM.md b/project-23-swiggy-clone-ecs/P2_CLASSROOM.md new file mode 100644 index 00000000..4173f76d --- /dev/null +++ b/project-23-swiggy-clone-ecs/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps: Blue-Green Deployment of Swiggy-Clone on AWS ECS with AWS Code Pipeline + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-23-swiggy-clone-ecs/P2_EVIDENCE.md b/project-23-swiggy-clone-ecs/P2_EVIDENCE.md new file mode 100644 index 00000000..2032c4a6 --- /dev/null +++ b/project-23-swiggy-clone-ecs/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps: Blue-Green Deployment of Swiggy-Clone on AWS ECS with AWS Code Pipeline + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-23-swiggy-clone-ecs/P2_HARDENING.md b/project-23-swiggy-clone-ecs/P2_HARDENING.md new file mode 100644 index 00000000..91a93448 --- /dev/null +++ b/project-23-swiggy-clone-ecs/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps: Blue-Green Deployment of Swiggy-Clone on AWS ECS with AWS Code Pipeline + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-23-swiggy-clone-ecs/P2_LOCAL_PILOT.md b/project-23-swiggy-clone-ecs/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..703c7953 --- /dev/null +++ b/project-23-swiggy-clone-ecs/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps: Blue-Green Deployment of Swiggy-Clone on AWS ECS with AWS Code Pipeline + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-23-swiggy-clone-ecs/START_HERE.md b/project-23-swiggy-clone-ecs/START_HERE.md new file mode 100644 index 00000000..90149f4b --- /dev/null +++ b/project-23-swiggy-clone-ecs/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-23-swiggy-clone-ecs + +**Learning focus:** DevSecOps CI/CD for Dockerized React deployment with AWS ECS blue-green releases + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect `Swiggy_clone/package.json`, `Swiggy_clone/Dockerfile`, +`Swiggy_clone/buildspec.yaml`, and `Swiggy_clone/appspec.yaml`, then record the app port, build stages, scan +gates, image tag convention, and ECS deployment references without changing them. + +## Checkpoints + +1. 1. The learner can identify the React entry point and explain how `public/index.html` and `src/` contribute to the Swiggy application +2. 1. The learner can trace the local container/build flow from `Dockerfile` through the non-root production runtime and connect it to the `buildspec.yaml` security checks and numbered image tagging +3. 1. The learner can annotate how `appspec.yaml` maps the ECS task definition, `swiggy` container, and port 3000 to a blue/green target-service update, without creating cloud resources. + +## Hints if you are stuck + +1. 1. If the file relationships are unclear, start with the package scripts and follow each referenced filename before interpreting the deployment YAML +2. 1. If the container flow seems inconsistent, compare the port exposed by the application configuration with the port named in the Dockerfile and `appspec.yaml` +3. 1. If the pipeline stages are hard to follow, separate source/build/security/deploy responsibilities and look for where credentials, SonarQube, Trivy, and the build-number tag are referenced rather than treating them as one command. + +## Evidence to capture + +A local architecture trace with annotated file excerpts, a port-and-image-tag table, and a short blue/green +deployment sequence diagram or written equivalent + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-23-swiggy-clone-ecs/fixtures/clean/contract.txt b/project-23-swiggy-clone-ecs/fixtures/clean/contract.txt new file mode 100644 index 00000000..19404a60 --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/clean/p2-clean.txt b/project-23-swiggy-clone-ecs/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..94d24e4c --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/evidence-local-result.txt b/project-23-swiggy-clone-ecs/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..1dbc9770 --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/negative/credential.txt b/project-23-swiggy-clone-ecs/fixtures/negative/credential.txt new file mode 100644 index 00000000..75fde361 --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/negative/mutation.txt b/project-23-swiggy-clone-ecs/fixtures/negative/mutation.txt new file mode 100644 index 00000000..d7ecbb9a --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/negative/p2-source-shaped.txt b/project-23-swiggy-clone-ecs/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..651132a3 --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/fixtures/negative/public_bind.txt b/project-23-swiggy-clone-ecs/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..31902e17 --- /dev/null +++ b/project-23-swiggy-clone-ecs/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-23-swiggy-clone-ecs +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-23-swiggy-clone-ecs/local-lab/contract.json b/project-23-swiggy-clone-ecs/local-lab/contract.json new file mode 100644 index 00000000..c7512e77 --- /dev/null +++ b/project-23-swiggy-clone-ecs/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-23-swiggy-clone-ecs", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-23-swiggy-clone-ecs/reset-p2-local.sh b/project-23-swiggy-clone-ecs/reset-p2-local.sh new file mode 100755 index 00000000..c47cc697 --- /dev/null +++ b/project-23-swiggy-clone-ecs/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-23-swiggy-clone-ecs" ]; then + printf '%s +' "ERROR: expected project-23-swiggy-clone-ecs; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-23-swiggy-clone-ecs' diff --git a/project-23-swiggy-clone-ecs/validate-p1-stream3.sh b/project-23-swiggy-clone-ecs/validate-p1-stream3.sh new file mode 100755 index 00000000..106d42ee --- /dev/null +++ b/project-23-swiggy-clone-ecs/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-23-swiggy-clone-ecs" ]; then + printf '%s +' "ERROR: expected project-23-swiggy-clone-ecs; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-23-swiggy-clone-ecs' diff --git a/project-23-swiggy-clone-ecs/validate-p2-local.sh b/project-23-swiggy-clone-ecs/validate-p2-local.sh new file mode 100755 index 00000000..c47cc697 --- /dev/null +++ b/project-23-swiggy-clone-ecs/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-23-swiggy-clone-ecs" ]; then + printf '%s +' "ERROR: expected project-23-swiggy-clone-ecs; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-23-swiggy-clone-ecs' diff --git a/project-24-dotnet-devsecops/P0_REMEDIATION.md b/project-24-dotnet-devsecops/P0_REMEDIATION.md new file mode 100644 index 00000000..a7939da4 --- /dev/null +++ b/project-24-dotnet-devsecops/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +## Scope + +This record defines the active classroom path for `project-24-dotnet-devsecops`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-24-dotnet-devsecops/P1_REMEDIATION.md b/project-24-dotnet-devsecops/P1_REMEDIATION.md new file mode 100644 index 00000000..192c9991 --- /dev/null +++ b/project-24-dotnet-devsecops/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +This checked-in record is required by the active source contract for `project-24-dotnet-devsecops`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-24-dotnet-devsecops/P2_CLASSROOM.md b/project-24-dotnet-devsecops/P2_CLASSROOM.md new file mode 100644 index 00000000..6a50030f --- /dev/null +++ b/project-24-dotnet-devsecops/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-24-dotnet-devsecops/P2_EVIDENCE.md b/project-24-dotnet-devsecops/P2_EVIDENCE.md new file mode 100644 index 00000000..606cb386 --- /dev/null +++ b/project-24-dotnet-devsecops/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-24-dotnet-devsecops/P2_HARDENING.md b/project-24-dotnet-devsecops/P2_HARDENING.md new file mode 100644 index 00000000..05c5802b --- /dev/null +++ b/project-24-dotnet-devsecops/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-24-dotnet-devsecops/P2_LOCAL_PILOT.md b/project-24-dotnet-devsecops/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..bc9ddc2b --- /dev/null +++ b/project-24-dotnet-devsecops/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-24-dotnet-devsecops/START_HERE.md b/project-24-dotnet-devsecops/START_HERE.md new file mode 100644 index 00000000..e4ec92da --- /dev/null +++ b/project-24-dotnet-devsecops/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-24-dotnet-devsecops + +**Learning focus:** Local .NET web application DevSecOps pipeline and container/Kubernetes delivery + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the packet’s project root, inspect `DotNet-monitoring/README.md`, `makefile`, and +`.github/workflows/ci-build.yaml`, then run only the local application’s documented build/test targets rather +than any cloud deployment target. + +## Checkpoints + +1. 1. The .NET project restores/builds locally and the xUnit test target completes, with the result recorded +2. 1. The application runs locally on its documented Kestrel port and the Info, Tools, and Monitoring pages are observable without optional cloud/API configuration +3. 1. A local review of the CI workflow and container/Kubernetes manifests identifies the build, Trivy security-scan, dependency-check, image, and deployment stages, with a brief mapping of each stage to its evidence. + +## Hints if you are stuck + +1. 1. If the first local command fails, verify that the available .NET SDK matches the README’s .NET 6 prerequisite and that you are invoking commands from the directory containing `src/dotnet-demoapp.csproj` +2. 1. If an expected page or feature is absent, check the README’s optional-configuration section before treating it as an application defect +3. 1. If CI/security review results differ from expectations, compare the workflow’s stage names and scan thresholds with the active YAML and distinguish static inspection from actually running cloud-dependent steps. + +## Evidence to capture + +Local build/test output, a localhost screenshot or notes for Info/Tools/Monitoring, and a short +stage-to-artifact security/CI mapping + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-24-dotnet-devsecops/SUPPORTED_VERSIONS.md b/project-24-dotnet-devsecops/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..fbd2530d --- /dev/null +++ b/project-24-dotnet-devsecops/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — 🌻 Real-Time DevSecOps Pipeline for a DotNet Web App 🌻 + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-24-dotnet-devsecops/fixtures/evidence-local-result.txt b/project-24-dotnet-devsecops/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..21a56e5d --- /dev/null +++ b/project-24-dotnet-devsecops/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-24-dotnet-devsecops +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-24-dotnet-devsecops/validate-local.sh b/project-24-dotnet-devsecops/validate-local.sh new file mode 100755 index 00000000..84834b4a --- /dev/null +++ b/project-24-dotnet-devsecops/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-24-dotnet-devsecops" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-24-dotnet-devsecops' 'validate-local.sh' diff --git a/project-24-dotnet-devsecops/validate-p1-stream2.sh b/project-24-dotnet-devsecops/validate-p1-stream2.sh new file mode 100755 index 00000000..cdf7ddc3 --- /dev/null +++ b/project-24-dotnet-devsecops/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-24-dotnet-devsecops" ]; then + printf '%s +' "ERROR: expected project-24-dotnet-devsecops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-24-dotnet-devsecops' diff --git a/project-24-dotnet-devsecops/validate-p2-local.sh b/project-24-dotnet-devsecops/validate-p2-local.sh new file mode 100755 index 00000000..8811fa9e --- /dev/null +++ b/project-24-dotnet-devsecops/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-24-dotnet-devsecops" ]; then + printf '%s +' "ERROR: expected project-24-dotnet-devsecops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-24-dotnet-devsecops' diff --git a/project-25-petshop-devsecops/P2_CLASSROOM.md b/project-25-petshop-devsecops/P2_CLASSROOM.md new file mode 100644 index 00000000..f2c322b7 --- /dev/null +++ b/project-25-petshop-devsecops/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps (DevOps) Project: Deploying a Petshop Java-Based Application with CI/CD, Docker, and Kubernetes + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-25-petshop-devsecops/P2_EVIDENCE.md b/project-25-petshop-devsecops/P2_EVIDENCE.md new file mode 100644 index 00000000..5c2725a8 --- /dev/null +++ b/project-25-petshop-devsecops/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps (DevOps) Project: Deploying a Petshop Java-Based Application with CI/CD, Docker, and Kubernetes + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-25-petshop-devsecops/P2_HARDENING.md b/project-25-petshop-devsecops/P2_HARDENING.md new file mode 100644 index 00000000..24ad4889 --- /dev/null +++ b/project-25-petshop-devsecops/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps (DevOps) Project: Deploying a Petshop Java-Based Application with CI/CD, Docker, and Kubernetes + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-25-petshop-devsecops/P2_LOCAL_PILOT.md b/project-25-petshop-devsecops/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..50ec8f85 --- /dev/null +++ b/project-25-petshop-devsecops/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps (DevOps) Project: Deploying a Petshop Java-Based Application with CI/CD, Docker, and Kubernetes + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-25-petshop-devsecops/START_HERE.md b/project-25-petshop-devsecops/START_HERE.md new file mode 100644 index 00000000..880e2917 --- /dev/null +++ b/project-25-petshop-devsecops/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-25-petshop-devsecops + +**Learning focus:** Java application DevSecOps CI/CD with Docker, Kubernetes, security scanning, and +infrastructure automation + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project folder, read the readme and make a local checklist mapping the Petshop pipeline stages—Maven +build/test, Docker image, SonarQube/Trivy checks, and Kubernetes manifests—without applying the Terraform or +cloud commands. + +## Checkpoints + +1. 1. The learner can identify and explain the intended flow from Java source through Maven, Jenkins, Docker, security gates, and Kubernetes using a labeled local diagram or checklist +2. 1. The learner can show a local, non-cloud build/test or configuration review with the relevant Maven/Jenkins/Docker/Kubernetes names and placeholders preserved rather than real credentials +3. 1. The learner can inspect the README's hardened-pipeline claims and produce evidence that the proposed image uses an unprivileged Tomcat runtime, an immutable BUILD_NUMBER tag, and a Trivy vulnerability gate, while explicitly marking any unverified runtime result. + +## Hints if you are stuck + +1. 1. If the starting point is unclear, begin with the README's Pipeline Overview and compare each numbered stage with the later detailed sections before changing anything +2. 1. If a Jenkins example does not line up with the described pipeline, check tool names, stage order, repository placeholders, and environment variables for consistency +3. 1. If a security or deployment claim cannot be demonstrated locally, separate configuration evidence from execution evidence and record the missing prerequisite instead of opening the AWS or public-IP steps. + +## Evidence to capture + +Annotated local pipeline map, sanitized configuration review, and a short verification log distinguishing +readme claims from locally observed results + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-25-petshop-devsecops/fixtures/clean_local.txt b/project-25-petshop-devsecops/fixtures/clean_local.txt new file mode 100644 index 00000000..99c55a7d --- /dev/null +++ b/project-25-petshop-devsecops/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-25-petshop-devsecops +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-25-petshop-devsecops/fixtures/evidence-local-result.txt b/project-25-petshop-devsecops/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..7f3b9850 --- /dev/null +++ b/project-25-petshop-devsecops/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-25-petshop-devsecops +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-25-petshop-devsecops/fixtures/negative_cloud_command.txt b/project-25-petshop-devsecops/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..fc03a199 --- /dev/null +++ b/project-25-petshop-devsecops/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-25-petshop-devsecops +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-25-petshop-devsecops/validate-p2-local.sh b/project-25-petshop-devsecops/validate-p2-local.sh new file mode 100755 index 00000000..9a2212b9 --- /dev/null +++ b/project-25-petshop-devsecops/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-25-petshop-devsecops" ]; then + printf '%s +' "ERROR: expected project-25-petshop-devsecops; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-25-petshop-devsecops' diff --git a/project-25-petshop-devsecops/validate_local.py b/project-25-petshop-devsecops/validate_local.py new file mode 100755 index 00000000..89b170fa --- /dev/null +++ b/project-25-petshop-devsecops/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-25-petshop-devsecops.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-25-petshop-devsecops": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-25-petshop-devsecops local-only control: PASS (validate_local.py)") diff --git a/project-26-terraform-gitlab-cicd/P0_REMEDIATION.md b/project-26-terraform-gitlab-cicd/P0_REMEDIATION.md new file mode 100644 index 00000000..e62dfbe2 --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +## Scope + +This record defines the active classroom path for `project-26-terraform-gitlab-cicd`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-26-terraform-gitlab-cicd/P1_REMEDIATION.md b/project-26-terraform-gitlab-cicd/P1_REMEDIATION.md new file mode 100644 index 00000000..24913779 --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +This checked-in record is required by the active source contract for `project-26-terraform-gitlab-cicd`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-26-terraform-gitlab-cicd/P2_CLASSROOM.md b/project-26-terraform-gitlab-cicd/P2_CLASSROOM.md new file mode 100644 index 00000000..4c74e39d --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-26-terraform-gitlab-cicd/P2_EVIDENCE.md b/project-26-terraform-gitlab-cicd/P2_EVIDENCE.md new file mode 100644 index 00000000..920d313d --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-26-terraform-gitlab-cicd/P2_HARDENING.md b/project-26-terraform-gitlab-cicd/P2_HARDENING.md new file mode 100644 index 00000000..5e51b1de --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-26-terraform-gitlab-cicd/P2_LOCAL_PILOT.md b/project-26-terraform-gitlab-cicd/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..639b6404 --- /dev/null +++ b/project-26-terraform-gitlab-cicd/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-26-terraform-gitlab-cicd/START_HERE.md b/project-26-terraform-gitlab-cicd/START_HERE.md new file mode 100644 index 00000000..b56388b9 --- /dev/null +++ b/project-26-terraform-gitlab-cicd/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-26-terraform-gitlab-cicd + +**Learning focus:** AWS infrastructure as code with Terraform modules and GitLab CI/CD + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read `README.md`, `.gitlab-ci.yml`, and the Terraform file inventory, then sketch how +the `vpc` and `web` modules connect without running any cloud or deployment command. + +## Checkpoints + +1. 1. The learner can label the root Terraform files and distinguish the `vpc` module from the `web` module using the project structure +2. 1. A local `terraform fmt -check -recursive` run reports whether the configuration meets the validation command recorded in `project.yaml` +3. 1. The learner can explain the CI/CD stage order (`validate`, `plan`, `apply`, `destroy`) and identify that `apply` and `destroy` are manual gates in the documented pipeline. + +## Hints if you are stuck + +1. 1. If the file layout is unclear, trace inputs and outputs between the root configuration and the `vpc` and `web` directories before changing resource blocks +2. 1. If formatting validation fails, compare the reported paths with Terraform's formatting conventions and make only local, reviewable edits +3. 1. If the pipeline sequence is confusing, follow the stages in `.gitlab-ci.yml` and separate checks and planning from the two explicitly manual operations. + +## Evidence to capture + +Annotated module/data-flow sketch, local formatting-check output, and a short explanation of the CI stage +order and manual gates + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-26-terraform-gitlab-cicd/SUPPORTED_VERSIONS.md b/project-26-terraform-gitlab-cicd/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..7c0cd5ee --- /dev/null +++ b/project-26-terraform-gitlab-cicd/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — 🚀 DevOps Project to Automate Infrastructure on AWS Using Terraform and GitLab CICD + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-26-terraform-gitlab-cicd/fixtures/evidence-local-result.txt b/project-26-terraform-gitlab-cicd/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..532e039b --- /dev/null +++ b/project-26-terraform-gitlab-cicd/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-26-terraform-gitlab-cicd +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-26-terraform-gitlab-cicd/validate-local.sh b/project-26-terraform-gitlab-cicd/validate-local.sh new file mode 100755 index 00000000..103b930f --- /dev/null +++ b/project-26-terraform-gitlab-cicd/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-26-terraform-gitlab-cicd" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-26-terraform-gitlab-cicd' 'validate-local.sh' diff --git a/project-26-terraform-gitlab-cicd/validate-p1-stream2.sh b/project-26-terraform-gitlab-cicd/validate-p1-stream2.sh new file mode 100755 index 00000000..a7830965 --- /dev/null +++ b/project-26-terraform-gitlab-cicd/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-26-terraform-gitlab-cicd" ]; then + printf '%s +' "ERROR: expected project-26-terraform-gitlab-cicd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-26-terraform-gitlab-cicd' diff --git a/project-26-terraform-gitlab-cicd/validate-p2-local.sh b/project-26-terraform-gitlab-cicd/validate-p2-local.sh new file mode 100755 index 00000000..6370b8ec --- /dev/null +++ b/project-26-terraform-gitlab-cicd/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-26-terraform-gitlab-cicd" ]; then + printf '%s +' "ERROR: expected project-26-terraform-gitlab-cicd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-26-terraform-gitlab-cicd' diff --git a/project-27-reddit-eks-argocd/P2_CLASSROOM.md b/project-27-reddit-eks-argocd/P2_CLASSROOM.md new file mode 100644 index 00000000..645b0f3f --- /dev/null +++ b/project-27-reddit-eks-argocd/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 🚀DevSecOps: Deploy Reddit App to Amazon Elastic Kubernetes Service (EKS) using ArgoCD and monitor its performance ✨ + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-27-reddit-eks-argocd/P2_EVIDENCE.md b/project-27-reddit-eks-argocd/P2_EVIDENCE.md new file mode 100644 index 00000000..1ddcfbfc --- /dev/null +++ b/project-27-reddit-eks-argocd/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 🚀DevSecOps: Deploy Reddit App to Amazon Elastic Kubernetes Service (EKS) using ArgoCD and monitor its performance ✨ + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-27-reddit-eks-argocd/P2_HARDENING.md b/project-27-reddit-eks-argocd/P2_HARDENING.md new file mode 100644 index 00000000..d2b85b5b --- /dev/null +++ b/project-27-reddit-eks-argocd/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 🚀DevSecOps: Deploy Reddit App to Amazon Elastic Kubernetes Service (EKS) using ArgoCD and monitor its performance ✨ + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-27-reddit-eks-argocd/P2_LOCAL_PILOT.md b/project-27-reddit-eks-argocd/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..9e7bea22 --- /dev/null +++ b/project-27-reddit-eks-argocd/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 🚀DevSecOps: Deploy Reddit App to Amazon Elastic Kubernetes Service (EKS) using ArgoCD and monitor its performance ✨ + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-27-reddit-eks-argocd/START_HERE.md b/project-27-reddit-eks-argocd/START_HERE.md new file mode 100644 index 00000000..a6763b6f --- /dev/null +++ b/project-27-reddit-eks-argocd/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-27-reddit-eks-argocd + +**Learning focus:** DevSecOps GitOps deployment and monitoring with Jenkins, Argo CD, Amazon EKS, Prometheus, +and Grafana + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read the readme locally and create a no-execution flow map linking Jenkins scanning and image tagging to the +Kubernetes manifests, Argo CD reconciliation, and Prometheus/Grafana monitoring. + +## Checkpoints + +1. 1. Produce a labeled diagram or notes that distinguish Jenkins, the immutable build-number image tag, the K8s/ manifest source, Argo CD, EKS, and the Prometheus/Grafana monitoring path +2. 1. Annotate the README's stated handoffs, including the deployment manifest update and the Argo CD application's repoURL, path K8s/, targetRevision HEAD, and default Kubernetes destination +3. 1. Submit a local validation checklist that names the evidence expected at each stage: scan outputs, Argo CD sync and health state, Reddit workload status, and observable monitoring metrics, without running cloud commands. + +## Hints if you are stuck + +1. 1. If the workflow is confusing, trace the desired state from Git rather than starting with the cluster, and identify which component is described as continuously reconciling it +2. 1. If image-version behavior is unclear, compare the README's warning about latest with its description of the Jenkins build-number tag and locate where that tag is said to be written +3. 1. If monitoring evidence is incomplete, separate Prometheus/Grafana installation, service exposure, data-source configuration, and metric interpretation into distinct checks. + +## Evidence to capture + +Annotated local workflow map and staged validation checklist covering security scans, immutable image tagging, +Argo CD reconciliation, Reddit deployment, and Prometheus/Grafana observations + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-27-reddit-eks-argocd/fixtures/clean_local.txt b/project-27-reddit-eks-argocd/fixtures/clean_local.txt new file mode 100644 index 00000000..fb7f9675 --- /dev/null +++ b/project-27-reddit-eks-argocd/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-27-reddit-eks-argocd +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-27-reddit-eks-argocd/fixtures/evidence-local-result.txt b/project-27-reddit-eks-argocd/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..3ac394bc --- /dev/null +++ b/project-27-reddit-eks-argocd/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-27-reddit-eks-argocd +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-27-reddit-eks-argocd/fixtures/negative_cloud_command.txt b/project-27-reddit-eks-argocd/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..291635be --- /dev/null +++ b/project-27-reddit-eks-argocd/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-27-reddit-eks-argocd +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-27-reddit-eks-argocd/validate-p2-local.sh b/project-27-reddit-eks-argocd/validate-p2-local.sh new file mode 100755 index 00000000..8dcc0199 --- /dev/null +++ b/project-27-reddit-eks-argocd/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-27-reddit-eks-argocd" ]; then + printf '%s +' "ERROR: expected project-27-reddit-eks-argocd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-27-reddit-eks-argocd' diff --git a/project-27-reddit-eks-argocd/validate_local.py b/project-27-reddit-eks-argocd/validate_local.py new file mode 100755 index 00000000..ab47c8fc --- /dev/null +++ b/project-27-reddit-eks-argocd/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-27-reddit-eks-argocd.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-27-reddit-eks-argocd": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-27-reddit-eks-argocd local-only control: PASS (validate_local.py)") diff --git a/project-28-openai-chatbot-eks/INSTRUCTOR_BOUNDARY.md b/project-28-openai-chatbot-eks/INSTRUCTOR_BOUNDARY.md new file mode 100644 index 00000000..b5441d14 --- /dev/null +++ b/project-28-openai-chatbot-eks/INSTRUCTOR_BOUNDARY.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-28-openai-chatbot-eks`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-28-openai-chatbot-eks/P0_REMEDIATION.md b/project-28-openai-chatbot-eks/P0_REMEDIATION.md new file mode 100644 index 00000000..810818c4 --- /dev/null +++ b/project-28-openai-chatbot-eks/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +## Scope + +This record defines the active classroom path for `project-28-openai-chatbot-eks`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-28-openai-chatbot-eks/P1_REMEDIATION.md b/project-28-openai-chatbot-eks/P1_REMEDIATION.md new file mode 100644 index 00000000..b5441d14 --- /dev/null +++ b/project-28-openai-chatbot-eks/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-28-openai-chatbot-eks`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-28-openai-chatbot-eks/P2_CLASSROOM.md b/project-28-openai-chatbot-eks/P2_CLASSROOM.md new file mode 100644 index 00000000..95b67038 --- /dev/null +++ b/project-28-openai-chatbot-eks/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-28-openai-chatbot-eks/P2_EVIDENCE.md b/project-28-openai-chatbot-eks/P2_EVIDENCE.md new file mode 100644 index 00000000..d62d602d --- /dev/null +++ b/project-28-openai-chatbot-eks/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-28-openai-chatbot-eks/P2_HARDENING.md b/project-28-openai-chatbot-eks/P2_HARDENING.md new file mode 100644 index 00000000..d14c696e --- /dev/null +++ b/project-28-openai-chatbot-eks/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-28-openai-chatbot-eks/P2_LOCAL_PILOT.md b/project-28-openai-chatbot-eks/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..668d596c --- /dev/null +++ b/project-28-openai-chatbot-eks/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-28-openai-chatbot-eks/QUARANTINE.md b/project-28-openai-chatbot-eks/QUARANTINE.md new file mode 100644 index 00000000..b5441d14 --- /dev/null +++ b/project-28-openai-chatbot-eks/QUARANTINE.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — DevSecOps: OpenAI Chatbot UI Deployment in EKS with Jenkins and Terraform + +This checked-in record is required by the active source contract for `project-28-openai-chatbot-eks`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-28-openai-chatbot-eks/START_HERE.md b/project-28-openai-chatbot-eks/START_HERE.md new file mode 100644 index 00000000..f64bac2b --- /dev/null +++ b/project-28-openai-chatbot-eks/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-28-openai-chatbot-eks + +**Learning focus:** DevSecOps deployment of a Next.js/TypeScript chatbot using Docker, Jenkins, Terraform, and +Kubernetes EKS + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the repository root, open `Chatbot-UI/README.md` and inspect `package.json`, `.env.example`, and the +local source/configuration files before touching any AWS, Jenkins, Terraform, or Kubernetes resources. + +## Checkpoints + +1. 1. You can identify the local app entry points (`pages/index.tsx`, `pages/api/chat.ts`), the package scripts, and the environment-variable template without changing student materials +2. 1. The Chatbot-UI dependencies install locally and `npm run dev` starts a development server without invoking Terraform, AWS CLI, Jenkins, or EKS +3. 1. The local interface loads in a browser and you can document the expected API-key configuration path and a test-chat observation, keeping credentials out of submitted evidence. + +## Hints if you are stuck + +1. 1. If the local start command fails, compare the command and working directory with `Chatbot-UI/README.md` and inspect the exact script names in `Chatbot-UI/package.json` +2. 1. If the interface loads but chat requests fail, check whether the environment variable names and server-key fallback setting match `.env.example` and the readme, rather than changing application code first +3. 1. If you are tempted to begin with the EKS files, Jenkinsfiles, or Terraform variables, first verify the local app boundary and capture the error from the smallest local test so the failure is attributable. + +## Evidence to capture + +Annotated local file map; dependency/startup output; browser capture of the local Chatbot UI; redacted +configuration note and one documented test-chat result + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-28-openai-chatbot-eks/chatbot.py b/project-28-openai-chatbot-eks/chatbot.py new file mode 100644 index 00000000..bc4b6643 --- /dev/null +++ b/project-28-openai-chatbot-eks/chatbot.py @@ -0,0 +1,19 @@ +"""Local-only teaching helper for project-28-openai-chatbot-eks. + +This reconstructed module contains no remote service, cloud credential, or deployment +behavior. It is intentionally deterministic for classroom evidence. +""" + +from __future__ import annotations + + +def local_status() -> dict[str, str]: + return { + "project": "project-28-openai-chatbot-eks", + "mode": "local-first", + "status": "ready-for-local-validation", + } + + +if __name__ == "__main__": + print(local_status()) diff --git a/project-28-openai-chatbot-eks/fixtures/evidence-local-result.txt b/project-28-openai-chatbot-eks/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a397504f --- /dev/null +++ b/project-28-openai-chatbot-eks/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-28-openai-chatbot-eks +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-28-openai-chatbot-eks/main.py b/project-28-openai-chatbot-eks/main.py new file mode 100644 index 00000000..bc4b6643 --- /dev/null +++ b/project-28-openai-chatbot-eks/main.py @@ -0,0 +1,19 @@ +"""Local-only teaching helper for project-28-openai-chatbot-eks. + +This reconstructed module contains no remote service, cloud credential, or deployment +behavior. It is intentionally deterministic for classroom evidence. +""" + +from __future__ import annotations + + +def local_status() -> dict[str, str]: + return { + "project": "project-28-openai-chatbot-eks", + "mode": "local-first", + "status": "ready-for-local-validation", + } + + +if __name__ == "__main__": + print(local_status()) diff --git a/project-28-openai-chatbot-eks/test_chatbot.py b/project-28-openai-chatbot-eks/test_chatbot.py new file mode 100644 index 00000000..ca464c0d --- /dev/null +++ b/project-28-openai-chatbot-eks/test_chatbot.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def test_local_classroom_prerequisites() -> None: + root = next( + path + for path in Path(__file__).resolve().parents + if path.name == "project-28-openai-chatbot-eks" + ) + assert (root / "README.md").is_file() + assert (root / "START_HERE.md").is_file() diff --git a/project-28-openai-chatbot-eks/validate-local.sh b/project-28-openai-chatbot-eks/validate-local.sh new file mode 100755 index 00000000..d9be87fb --- /dev/null +++ b/project-28-openai-chatbot-eks/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-28-openai-chatbot-eks" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-28-openai-chatbot-eks' 'validate-local.sh' diff --git a/project-28-openai-chatbot-eks/validate-p2-local.sh b/project-28-openai-chatbot-eks/validate-p2-local.sh new file mode 100755 index 00000000..93842b5c --- /dev/null +++ b/project-28-openai-chatbot-eks/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-28-openai-chatbot-eks" ]; then + printf '%s +' "ERROR: expected project-28-openai-chatbot-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-28-openai-chatbot-eks' diff --git a/project-29-voting-app-argocd/P2_CLASSROOM.md b/project-29-voting-app-argocd/P2_CLASSROOM.md new file mode 100644 index 00000000..adb1df21 --- /dev/null +++ b/project-29-voting-app-argocd/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — CI/CD Project: Deploy a 3-tier Microservice Voting App using ArgoCD and Azure DevOps Pipeline + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-29-voting-app-argocd/P2_EVIDENCE.md b/project-29-voting-app-argocd/P2_EVIDENCE.md new file mode 100644 index 00000000..3f2af2f2 --- /dev/null +++ b/project-29-voting-app-argocd/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — CI/CD Project: Deploy a 3-tier Microservice Voting App using ArgoCD and Azure DevOps Pipeline + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-29-voting-app-argocd/P2_HARDENING.md b/project-29-voting-app-argocd/P2_HARDENING.md new file mode 100644 index 00000000..126d159c --- /dev/null +++ b/project-29-voting-app-argocd/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — CI/CD Project: Deploy a 3-tier Microservice Voting App using ArgoCD and Azure DevOps Pipeline + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-29-voting-app-argocd/P2_LOCAL_PILOT.md b/project-29-voting-app-argocd/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..fb863ff3 --- /dev/null +++ b/project-29-voting-app-argocd/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — CI/CD Project: Deploy a 3-tier Microservice Voting App using ArgoCD and Azure DevOps Pipeline + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-29-voting-app-argocd/START_HERE.md b/project-29-voting-app-argocd/START_HERE.md new file mode 100644 index 00000000..da3369a7 --- /dev/null +++ b/project-29-voting-app-argocd/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-29-voting-app-argocd + +**Learning focus:** Microservices CI/CD with Docker Compose, Azure DevOps, Kubernetes, and Argo CD + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Clone the referenced example-voting-app repository into a disposable local directory and inspect its +docker-compose configuration and service directories before starting any containers. + +## Checkpoints + +1. 1. You can identify the vote, result, worker, Redis, and PostgreSQL services and explain the vote-to-results data flow from the readme +2. 1. The local Compose run starts the application containers and the voting page is reachable at the documented local port 5000 +3. 1. After submitting a test vote locally, the results page reflects the vote and you can document which service path connects Redis processing to PostgreSQL-backed results. + +## Hints if you are stuck + +1. 1. If the Compose startup does not behave as expected, first compare the service names, working directory, and port mapping with the repository's Compose file +2. 1. If the page loads but results do not change, check whether the worker and both data stores are running rather than troubleshooting the browser first +3. 1. For a later pipeline or Argo CD exercise, verify one naming or image-tag value at a time against the repository path and the intended microservice instead of changing every configuration field together. + +## Evidence to capture + +Annotated local service/data-flow diagram, terminal capture of the Compose services, and screenshots or notes +showing a submitted vote and updated results + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-29-voting-app-argocd/fixtures/clean_local.txt b/project-29-voting-app-argocd/fixtures/clean_local.txt new file mode 100644 index 00000000..533f7bd9 --- /dev/null +++ b/project-29-voting-app-argocd/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-29-voting-app-argocd +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-29-voting-app-argocd/fixtures/evidence-local-result.txt b/project-29-voting-app-argocd/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..065b3abb --- /dev/null +++ b/project-29-voting-app-argocd/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-29-voting-app-argocd +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-29-voting-app-argocd/fixtures/negative_cloud_command.txt b/project-29-voting-app-argocd/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..0acec10c --- /dev/null +++ b/project-29-voting-app-argocd/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-29-voting-app-argocd +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-29-voting-app-argocd/validate-p2-local.sh b/project-29-voting-app-argocd/validate-p2-local.sh new file mode 100755 index 00000000..1fe38b42 --- /dev/null +++ b/project-29-voting-app-argocd/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-29-voting-app-argocd" ]; then + printf '%s +' "ERROR: expected project-29-voting-app-argocd; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-29-voting-app-argocd' diff --git a/project-29-voting-app-argocd/validate_local.py b/project-29-voting-app-argocd/validate_local.py new file mode 100755 index 00000000..e7227c26 --- /dev/null +++ b/project-29-voting-app-argocd/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-29-voting-app-argocd.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-29-voting-app-argocd": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-29-voting-app-argocd local-only control: PASS (validate_local.py)") diff --git a/project-30-blog-app-eks/INSTRUCTOR_BOUNDARY.md b/project-30-blog-app-eks/INSTRUCTOR_BOUNDARY.md new file mode 100644 index 00000000..f60040a5 --- /dev/null +++ b/project-30-blog-app-eks/INSTRUCTOR_BOUNDARY.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +This checked-in record is required by the active source contract for `project-30-blog-app-eks`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-30-blog-app-eks/P0_REMEDIATION.md b/project-30-blog-app-eks/P0_REMEDIATION.md new file mode 100644 index 00000000..97ec65c5 --- /dev/null +++ b/project-30-blog-app-eks/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +## Scope + +This record defines the active classroom path for `project-30-blog-app-eks`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-30-blog-app-eks/P1_REMEDIATION.md b/project-30-blog-app-eks/P1_REMEDIATION.md new file mode 100644 index 00000000..f60040a5 --- /dev/null +++ b/project-30-blog-app-eks/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +This checked-in record is required by the active source contract for `project-30-blog-app-eks`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-30-blog-app-eks/P2_CLASSROOM.md b/project-30-blog-app-eks/P2_CLASSROOM.md new file mode 100644 index 00000000..3484e6fb --- /dev/null +++ b/project-30-blog-app-eks/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-30-blog-app-eks/P2_EVIDENCE.md b/project-30-blog-app-eks/P2_EVIDENCE.md new file mode 100644 index 00000000..ae7804fa --- /dev/null +++ b/project-30-blog-app-eks/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-30-blog-app-eks/P2_HARDENING.md b/project-30-blog-app-eks/P2_HARDENING.md new file mode 100644 index 00000000..07626db0 --- /dev/null +++ b/project-30-blog-app-eks/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-30-blog-app-eks/P2_LOCAL_PILOT.md b/project-30-blog-app-eks/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..a8fda4a7 --- /dev/null +++ b/project-30-blog-app-eks/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-30-blog-app-eks/START_HERE.md b/project-30-blog-app-eks/START_HERE.md new file mode 100644 index 00000000..ad5279ad --- /dev/null +++ b/project-30-blog-app-eks/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-30-blog-app-eks + +**Learning focus:** DevSecOps CI/CD for a Spring Boot blogging app on Kubernetes/EKS + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect `app/pom.xml`, `app/Dockerfile`, `app/Jenkinsfile`, +`app/deployment-service.yml`, and `app/EKS_Terraform/main.tf` locally, then write down how source code, image +build, pipeline stages, Kubernetes resources, and Terraform infrastructure connect before running anything. + +## Checkpoints + +1. 1. The student can identify the Spring Boot/Maven build entry point and explain what the Dockerfile packages without changing the files +2. 1. The student can trace the Jenkins pipeline stages from checkout and Maven compilation through Trivy/SonarQube checks and image publication, noting the required tool and credential names +3. 1. The student can map `deployment-service.yml` and `RBAC.md` to the `webapps` namespace, Jenkins service account permissions, application deployment, and service exposure, and relate the Terraform files to EKS infrastructure without applying them. + +## Hints if you are stuck + +1. 1. If the pipeline structure is unclear, compare the stage names and configured tool labels in `app/Jenkinsfile` with the Maven project metadata in `app/pom.xml` +2. 1. If Kubernetes resources do not seem to fit together, check namespace, service-account, selector, labels, image, and container-port fields across `app/RBAC.md` and `app/deployment-service.yml` +3. 1. If Terraform variables or outputs are confusing, trace each referenced variable and output across `app/EKS_Terraform/main.tf`, `variables.tf`, and `output.tf` before considering any command execution. + +## Evidence to capture + +Annotated local dependency map plus a dry-run pipeline/Kubernetes flow diagram and a short explanation of the +relevant files, stages, namespaces, selectors, ports, credentials, and Terraform inputs/outputs + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-30-blog-app-eks/SUPPORTED_VERSIONS.md b/project-30-blog-app-eks/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..4fa84012 --- /dev/null +++ b/project-30-blog-app-eks/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — CICD PROJECT: Blog APP Deployment with EKS, Nexus, SonarQube, Trivy with Monitoring Tools + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-30-blog-app-eks/fixtures/evidence-local-result.txt b/project-30-blog-app-eks/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..1fb652cf --- /dev/null +++ b/project-30-blog-app-eks/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-30-blog-app-eks +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-30-blog-app-eks/validate-local.sh b/project-30-blog-app-eks/validate-local.sh new file mode 100755 index 00000000..b897de85 --- /dev/null +++ b/project-30-blog-app-eks/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-30-blog-app-eks" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-30-blog-app-eks' 'validate-local.sh' diff --git a/project-30-blog-app-eks/validate-p1-stream2.sh b/project-30-blog-app-eks/validate-p1-stream2.sh new file mode 100755 index 00000000..8af7d3ac --- /dev/null +++ b/project-30-blog-app-eks/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-30-blog-app-eks" ]; then + printf '%s +' "ERROR: expected project-30-blog-app-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-30-blog-app-eks' diff --git a/project-30-blog-app-eks/validate-p2-local.sh b/project-30-blog-app-eks/validate-p2-local.sh new file mode 100755 index 00000000..e01cc132 --- /dev/null +++ b/project-30-blog-app-eks/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-30-blog-app-eks" ]; then + printf '%s +' "ERROR: expected project-30-blog-app-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-30-blog-app-eks' diff --git a/project-30-blog-app-eks/validate_p1_manifest.py b/project-30-blog-app-eks/validate_p1_manifest.py new file mode 100755 index 00000000..f377287f --- /dev/null +++ b/project-30-blog-app-eks/validate_p1_manifest.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-30-blog-app-eks.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-30-blog-app-eks": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-30-blog-app-eks local-only control: PASS (validate_p1_manifest.py)") diff --git a/project-31-cloud-native-monitoring/P2_CLASSROOM.md b/project-31-cloud-native-monitoring/P2_CLASSROOM.md new file mode 100644 index 00000000..a53cb44b --- /dev/null +++ b/project-31-cloud-native-monitoring/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Cloud-Native-Monitoring-App + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-31-cloud-native-monitoring/P2_EVIDENCE.md b/project-31-cloud-native-monitoring/P2_EVIDENCE.md new file mode 100644 index 00000000..dd8c7e74 --- /dev/null +++ b/project-31-cloud-native-monitoring/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Cloud-Native-Monitoring-App + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-31-cloud-native-monitoring/P2_HARDENING.md b/project-31-cloud-native-monitoring/P2_HARDENING.md new file mode 100644 index 00000000..c076cbd6 --- /dev/null +++ b/project-31-cloud-native-monitoring/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Cloud-Native-Monitoring-App + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-31-cloud-native-monitoring/P2_LOCAL_PILOT.md b/project-31-cloud-native-monitoring/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..8cb7dd53 --- /dev/null +++ b/project-31-cloud-native-monitoring/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Cloud-Native-Monitoring-App + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-31-cloud-native-monitoring/START_HERE.md b/project-31-cloud-native-monitoring/START_HERE.md new file mode 100644 index 00000000..06a1635b --- /dev/null +++ b/project-31-cloud-native-monitoring/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-31-cloud-native-monitoring + +**Learning focus:** Local Flask monitoring app containerization and Kubernetes deployment concepts + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read the README's local application section and run the repository's stated validation +command `make test` without configuring AWS, Docker pushes, or an EKS cluster. + +## Checkpoints + +1. 1. `make test` completes and the healthcheck test passes +2. 1. the learner can identify from `README.md` how `app.py`, `requirements.txt`, `Dockerfile`, and `tests/test_healthcheck.py` fit together for the local Flask app +3. 1. the learner records a local-only explanation of the intended container, ECR, and Kubernetes Deployment/Service flow without executing cloud-provider or cluster commands. + +## Hints if you are stuck + +1. 1. If the validation command fails, distinguish a test/assertion problem from a missing local dependency before changing application code +2. 1. compare the Flask listen port and healthcheck expectations with the port exposed and published in the Docker instructions +3. 1. when reviewing the Kubernetes examples, check that selectors, labels, service ports, and the image placeholder agree before treating the manifest logic as correct. + +## Evidence to capture + +Passing `make test` output plus a short local architecture note mapping the Flask app, healthcheck, container +settings, and Kubernetes object relationships + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-31-cloud-native-monitoring/fixtures/clean_local.txt b/project-31-cloud-native-monitoring/fixtures/clean_local.txt new file mode 100644 index 00000000..0274883d --- /dev/null +++ b/project-31-cloud-native-monitoring/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-31-cloud-native-monitoring +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-31-cloud-native-monitoring/fixtures/evidence-local-result.txt b/project-31-cloud-native-monitoring/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..70c838b2 --- /dev/null +++ b/project-31-cloud-native-monitoring/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-31-cloud-native-monitoring +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-31-cloud-native-monitoring/fixtures/negative_cloud_command.txt b/project-31-cloud-native-monitoring/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..b1fe9544 --- /dev/null +++ b/project-31-cloud-native-monitoring/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-31-cloud-native-monitoring +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-31-cloud-native-monitoring/validate-p2-local.sh b/project-31-cloud-native-monitoring/validate-p2-local.sh new file mode 100755 index 00000000..eb97c1aa --- /dev/null +++ b/project-31-cloud-native-monitoring/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-31-cloud-native-monitoring" ]; then + printf '%s +' "ERROR: expected project-31-cloud-native-monitoring; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-31-cloud-native-monitoring' diff --git a/project-31-cloud-native-monitoring/validate_local.py b/project-31-cloud-native-monitoring/validate_local.py new file mode 100755 index 00000000..b73b11b6 --- /dev/null +++ b/project-31-cloud-native-monitoring/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-31-cloud-native-monitoring.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-31-cloud-native-monitoring": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-31-cloud-native-monitoring local-only control: PASS (validate_local.py)") diff --git a/project-32-tetris-devsecops-k8s/.p1_active_paths b/project-32-tetris-devsecops-k8s/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-32-tetris-devsecops-k8s/P1_LOCAL_CONTRACT.md b/project-32-tetris-devsecops-k8s/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..9ab406a3 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — 🚀 End-to-End DevSecOps Kubernetes Project 🌐 + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-32-tetris-devsecops-k8s/P2_CLASSROOM.md b/project-32-tetris-devsecops-k8s/P2_CLASSROOM.md new file mode 100644 index 00000000..a9382140 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 🚀 End-to-End DevSecOps Kubernetes Project 🌐 + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-32-tetris-devsecops-k8s/P2_EVIDENCE.md b/project-32-tetris-devsecops-k8s/P2_EVIDENCE.md new file mode 100644 index 00000000..3bb43da9 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 🚀 End-to-End DevSecOps Kubernetes Project 🌐 + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-32-tetris-devsecops-k8s/P2_HARDENING.md b/project-32-tetris-devsecops-k8s/P2_HARDENING.md new file mode 100644 index 00000000..0c3f0465 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 🚀 End-to-End DevSecOps Kubernetes Project 🌐 + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-32-tetris-devsecops-k8s/P2_LOCAL_PILOT.md b/project-32-tetris-devsecops-k8s/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..6313478c --- /dev/null +++ b/project-32-tetris-devsecops-k8s/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 🚀 End-to-End DevSecOps Kubernetes Project 🌐 + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-32-tetris-devsecops-k8s/START_HERE.md b/project-32-tetris-devsecops-k8s/START_HERE.md new file mode 100644 index 00000000..19cc1aa2 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-32-tetris-devsecops-k8s + +**Learning focus:** DevSecOps CI/CD for a React application with Docker, Kubernetes manifests, Jenkins, +Terraform, and EKS architecture + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect `Tetris-V1/package.json`, `Tetris-V1/README.md`, and +`Manifest-file/deployment-service.yml` to map the React app, its local test command, and its Kubernetes +resource definitions without applying any infrastructure. + +## Checkpoints + +1. 1. The learner can identify Tetris-V1 as the initial React application and locate its package scripts and test file +2. 1. The learner can explain how the Dockerfile, Jenkins pipeline files, and `Manifest-file/deployment-service.yml` connect the application build to container and Kubernetes delivery +3. 1. The learner can run the packet’s validation command `npm --prefix Tetris-V1 test --if-present` locally and capture the result without provisioning AWS, Jenkins, or EKS. + +## Hints if you are stuck + +1. 1. If the validation command behaves unexpectedly, compare the working directory and the `--prefix` path with the inventory before changing application files +2. 1. If the pipeline flow is unclear, read the Jenkinsfiles alongside the Dockerfile and note which filenames and stages are referenced +3. 1. If the Kubernetes manifest is difficult to interpret, separate the workload fields from the service fields and compare their labels, ports, and image references without deploying them. + +## Evidence to capture + +A local inspection note or screenshot showing the React package/test entry point, the +Docker-to-pipeline-to-manifest relationship, and the captured local test output + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-32-tetris-devsecops-k8s/fixtures/clean/contract.txt b/project-32-tetris-devsecops-k8s/fixtures/clean/contract.txt new file mode 100644 index 00000000..bd8008b6 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/clean/p2-clean.txt b/project-32-tetris-devsecops-k8s/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..5d19a0ae --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/evidence-local-result.txt b/project-32-tetris-devsecops-k8s/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..4290672e --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/negative/credential.txt b/project-32-tetris-devsecops-k8s/fixtures/negative/credential.txt new file mode 100644 index 00000000..08d950a1 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/negative/mutation.txt b/project-32-tetris-devsecops-k8s/fixtures/negative/mutation.txt new file mode 100644 index 00000000..ac2d7492 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/negative/p2-source-shaped.txt b/project-32-tetris-devsecops-k8s/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..df592cf5 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/fixtures/negative/public_bind.txt b/project-32-tetris-devsecops-k8s/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..d3cd613c --- /dev/null +++ b/project-32-tetris-devsecops-k8s/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-32-tetris-devsecops-k8s +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-32-tetris-devsecops-k8s/local-lab/contract.json b/project-32-tetris-devsecops-k8s/local-lab/contract.json new file mode 100644 index 00000000..7a398de7 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-32-tetris-devsecops-k8s", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-32-tetris-devsecops-k8s/reset-p2-local.sh b/project-32-tetris-devsecops-k8s/reset-p2-local.sh new file mode 100755 index 00000000..b6384d32 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-32-tetris-devsecops-k8s" ]; then + printf '%s +' "ERROR: expected project-32-tetris-devsecops-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-32-tetris-devsecops-k8s' diff --git a/project-32-tetris-devsecops-k8s/validate-p1-stream3.sh b/project-32-tetris-devsecops-k8s/validate-p1-stream3.sh new file mode 100755 index 00000000..34b9096c --- /dev/null +++ b/project-32-tetris-devsecops-k8s/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-32-tetris-devsecops-k8s" ]; then + printf '%s +' "ERROR: expected project-32-tetris-devsecops-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-32-tetris-devsecops-k8s' diff --git a/project-32-tetris-devsecops-k8s/validate-p2-local.sh b/project-32-tetris-devsecops-k8s/validate-p2-local.sh new file mode 100755 index 00000000..b6384d32 --- /dev/null +++ b/project-32-tetris-devsecops-k8s/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-32-tetris-devsecops-k8s" ]; then + printf '%s +' "ERROR: expected project-32-tetris-devsecops-k8s; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-32-tetris-devsecops-k8s' diff --git a/project-33-node-cicd-eks-gha/.github/workflows/e2ecicd.yaml.blocked b/project-33-node-cicd-eks-gha/.github/workflows/e2ecicd.yaml.blocked new file mode 100644 index 00000000..8efd3be8 --- /dev/null +++ b/project-33-node-cicd-eks-gha/.github/workflows/e2ecicd.yaml.blocked @@ -0,0 +1,6 @@ +--- +# Blocked historical workflow specimen for project-33-node-cicd-eks-gha. +# This file is documentation only; it must not be enabled or executed. +status: blocked +execution: prohibited +reason: local-first classroom boundary diff --git a/project-33-node-cicd-eks-gha/P0_REMEDIATION.md b/project-33-node-cicd-eks-gha/P0_REMEDIATION.md new file mode 100644 index 00000000..cd1ddea1 --- /dev/null +++ b/project-33-node-cicd-eks-gha/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +## Scope + +This record defines the active classroom path for `project-33-node-cicd-eks-gha`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-33-node-cicd-eks-gha/P1_REMEDIATION.md b/project-33-node-cicd-eks-gha/P1_REMEDIATION.md new file mode 100644 index 00000000..6a56a30a --- /dev/null +++ b/project-33-node-cicd-eks-gha/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +This checked-in record is required by the active source contract for `project-33-node-cicd-eks-gha`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-33-node-cicd-eks-gha/P2_CLASSROOM.md b/project-33-node-cicd-eks-gha/P2_CLASSROOM.md new file mode 100644 index 00000000..8bd20039 --- /dev/null +++ b/project-33-node-cicd-eks-gha/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-33-node-cicd-eks-gha/P2_EVIDENCE.md b/project-33-node-cicd-eks-gha/P2_EVIDENCE.md new file mode 100644 index 00000000..369fab00 --- /dev/null +++ b/project-33-node-cicd-eks-gha/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-33-node-cicd-eks-gha/P2_HARDENING.md b/project-33-node-cicd-eks-gha/P2_HARDENING.md new file mode 100644 index 00000000..bdbc015e --- /dev/null +++ b/project-33-node-cicd-eks-gha/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-33-node-cicd-eks-gha/P2_LOCAL_PILOT.md b/project-33-node-cicd-eks-gha/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..839e78e4 --- /dev/null +++ b/project-33-node-cicd-eks-gha/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-33-node-cicd-eks-gha/START_HERE.md b/project-33-node-cicd-eks-gha/START_HERE.md new file mode 100644 index 00000000..f818664c --- /dev/null +++ b/project-33-node-cicd-eks-gha/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-33-node-cicd-eks-gha + +**Learning focus:** Node.js CI/CD and DevSecOps pipeline configuration with Docker, Kustomize, Terraform, +GitHub Actions, and EKS + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the repository root, read `README.md` and inspect `app/package.json`, `Makefile`, and +`.github/workflows/e2ecicd.yaml` to map the local test/build flow before changing any files or invoking cloud +deployment steps. + +## Checkpoints + +1. 1. The student can identify the Node application entry points and test files under `app/` and explain that `make test` is the packet's local validation command +2. 1. The student can trace the workflow's build stages from dependency installation and unit tests through semantic-version handling and Docker image publication without running the deployment job +3. 1. The student can compare the `dev`, `staging`, and `prod` Kustomize overlays and point to the corresponding Terraform and workflow sections that provision and deploy each environment, while keeping this comparison local-only. + +## Hints if you are stuck + +1. 1. If the starting point is unclear, follow the README's repository structure and CI/CD Workflow headings, then open the named files rather than guessing commands +2. 1. If local validation does not behave as expected, check the `app/package.json` scripts and the Makefile target against the test files listed in `app/` +3. 1. If the environment comparison is confusing, inspect each overlay's `kustomization.yaml` together with its deployment, service, and ingress patches, and distinguish those files from the Terraform and GitHub Actions layers. + +## Evidence to capture + +A local inspection note or diff-free report containing the successful `make test` result, a build-job flow +diagram or annotated trace, and a dev/staging/prod overlay comparison + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-33-node-cicd-eks-gha/SUPPORTED_VERSIONS.md b/project-33-node-cicd-eks-gha/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..145813d7 --- /dev/null +++ b/project-33-node-cicd-eks-gha/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — End-to-End CI/CD Pipeline for Simple Node App Deployment on EKS using GitHub Actions + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-33-node-cicd-eks-gha/fixtures/evidence-local-result.txt b/project-33-node-cicd-eks-gha/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a89a6680 --- /dev/null +++ b/project-33-node-cicd-eks-gha/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-33-node-cicd-eks-gha +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-33-node-cicd-eks-gha/validate-local.sh b/project-33-node-cicd-eks-gha/validate-local.sh new file mode 100755 index 00000000..3704b90f --- /dev/null +++ b/project-33-node-cicd-eks-gha/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-33-node-cicd-eks-gha" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-33-node-cicd-eks-gha' 'validate-local.sh' diff --git a/project-33-node-cicd-eks-gha/validate-p1-stream2.sh b/project-33-node-cicd-eks-gha/validate-p1-stream2.sh new file mode 100755 index 00000000..e6964902 --- /dev/null +++ b/project-33-node-cicd-eks-gha/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-33-node-cicd-eks-gha" ]; then + printf '%s +' "ERROR: expected project-33-node-cicd-eks-gha; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-33-node-cicd-eks-gha' diff --git a/project-33-node-cicd-eks-gha/validate-p2-local.sh b/project-33-node-cicd-eks-gha/validate-p2-local.sh new file mode 100755 index 00000000..3c3b75f3 --- /dev/null +++ b/project-33-node-cicd-eks-gha/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-33-node-cicd-eks-gha" ]; then + printf '%s +' "ERROR: expected project-33-node-cicd-eks-gha; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-33-node-cicd-eks-gha' diff --git a/project-34-node-cicd-ecs-terraform-gha/.p1_active_paths b/project-34-node-cicd-ecs-terraform-gha/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-34-node-cicd-ecs-terraform-gha/P1_LOCAL_CONTRACT.md b/project-34-node-cicd-ecs-terraform-gha/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..8b047c4c --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — Project 34 Node Cicd Ecs Terraform Gha + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-34-node-cicd-ecs-terraform-gha/P2_CLASSROOM.md b/project-34-node-cicd-ecs-terraform-gha/P2_CLASSROOM.md new file mode 100644 index 00000000..89c13c2a --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 34 Node Cicd Ecs Terraform Gha + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-34-node-cicd-ecs-terraform-gha/P2_EVIDENCE.md b/project-34-node-cicd-ecs-terraform-gha/P2_EVIDENCE.md new file mode 100644 index 00000000..9fbf5cc4 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 34 Node Cicd Ecs Terraform Gha + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-34-node-cicd-ecs-terraform-gha/P2_HARDENING.md b/project-34-node-cicd-ecs-terraform-gha/P2_HARDENING.md new file mode 100644 index 00000000..ff8c232a --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 34 Node Cicd Ecs Terraform Gha + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-34-node-cicd-ecs-terraform-gha/P2_LOCAL_PILOT.md b/project-34-node-cicd-ecs-terraform-gha/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..a5b7b43e --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 34 Node Cicd Ecs Terraform Gha + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-34-node-cicd-ecs-terraform-gha/START_HERE.md b/project-34-node-cicd-ecs-terraform-gha/START_HERE.md new file mode 100644 index 00000000..3da95c7c --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-34-node-cicd-ecs-terraform-gha + +**Learning focus:** Python/Flask container CI/CD with Terraform-managed AWS ECS and GitHub Actions + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read `app.py`, `Dockerfile`, `terraform/main.tf`, and the three workflow files locally, then compare their +declared runtime, image, and deployment steps without running or applying anything. + +## Checkpoints + +1. 1. The learner can explain whether the Python/Flask files and Dockerfile agree with the README’s Node.js description +2. 1. `terraform -chdir=terraform fmt -check` passes, showing the infrastructure file meets the packet’s stated local validation +3. 1. The learner can trace the test-to-deploy dependency in the workflow files and identify where OIDC, ECR image publishing, and ECS service updating are configured, without executing a cloud deployment. + +## Hints if you are stuck + +1. 1. When the project description and active files disagree, compare the actual base image, application entry point, dependencies, and exposed port before changing anything +2. 1. For a formatting-check failure, inspect Terraform whitespace and formatting rather than changing resource behavior +3. 1. If the workflow’s deployment path is unclear, follow job names, `needs` relationships, environment variables, and action inputs from test through image push to ECS update. + +## Evidence to capture + +A local comparison table or annotated notes covering runtime alignment, Docker build inputs, Terraform +formatting, and the workflow test/deploy dependency graph + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/contract.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/contract.txt new file mode 100644 index 00000000..0637ad61 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/p2-clean.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..c022a0bc --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/evidence-local-result.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..419a08b3 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/credential.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/credential.txt new file mode 100644 index 00000000..fe0748fa --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/mutation.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/mutation.txt new file mode 100644 index 00000000..c9cff08c --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/p2-source-shaped.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..6bd704a7 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/public_bind.txt b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..e16c01fb --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-34-node-cicd-ecs-terraform-gha +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-34-node-cicd-ecs-terraform-gha/local-lab/contract.json b/project-34-node-cicd-ecs-terraform-gha/local-lab/contract.json new file mode 100644 index 00000000..2943d175 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-34-node-cicd-ecs-terraform-gha", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-34-node-cicd-ecs-terraform-gha/reset-p2-local.sh b/project-34-node-cicd-ecs-terraform-gha/reset-p2-local.sh new file mode 100755 index 00000000..4f4efeb9 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-34-node-cicd-ecs-terraform-gha" ]; then + printf '%s +' "ERROR: expected project-34-node-cicd-ecs-terraform-gha; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-34-node-cicd-ecs-terraform-gha' diff --git a/project-34-node-cicd-ecs-terraform-gha/validate-p1-stream3.sh b/project-34-node-cicd-ecs-terraform-gha/validate-p1-stream3.sh new file mode 100755 index 00000000..207717dd --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-34-node-cicd-ecs-terraform-gha" ]; then + printf '%s +' "ERROR: expected project-34-node-cicd-ecs-terraform-gha; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-34-node-cicd-ecs-terraform-gha' diff --git a/project-34-node-cicd-ecs-terraform-gha/validate-p2-local.sh b/project-34-node-cicd-ecs-terraform-gha/validate-p2-local.sh new file mode 100755 index 00000000..4f4efeb9 --- /dev/null +++ b/project-34-node-cicd-ecs-terraform-gha/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-34-node-cicd-ecs-terraform-gha" ]; then + printf '%s +' "ERROR: expected project-34-node-cicd-ecs-terraform-gha; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-34-node-cicd-ecs-terraform-gha' diff --git a/project-35-devsecops-pipeline-series/.gitignore b/project-35-devsecops-pipeline-series/.gitignore new file mode 100644 index 00000000..a73928ed --- /dev/null +++ b/project-35-devsecops-pipeline-series/.gitignore @@ -0,0 +1,3 @@ +.env +*.local +__pycache__/ diff --git a/project-35-devsecops-pipeline-series/INSTRUCTOR_BOUNDARY.md b/project-35-devsecops-pipeline-series/INSTRUCTOR_BOUNDARY.md new file mode 100644 index 00000000..e3f270b9 --- /dev/null +++ b/project-35-devsecops-pipeline-series/INSTRUCTOR_BOUNDARY.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — DevSecOps Pipeline Series — Progressive CI/CD with Security + +This checked-in record is required by the active source contract for `project-35-devsecops-pipeline-series`. +It is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-35-devsecops-pipeline-series/P0_REMEDIATION.md b/project-35-devsecops-pipeline-series/P0_REMEDIATION.md new file mode 100644 index 00000000..3db1855e --- /dev/null +++ b/project-35-devsecops-pipeline-series/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — DevSecOps Pipeline Series — Progressive CI/CD with Security + +## Scope + +This record defines the active classroom path for `project-35-devsecops-pipeline-series`. It is source-only +and local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-35-devsecops-pipeline-series/P1_REMEDIATION.md b/project-35-devsecops-pipeline-series/P1_REMEDIATION.md new file mode 100644 index 00000000..e3f270b9 --- /dev/null +++ b/project-35-devsecops-pipeline-series/P1_REMEDIATION.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — DevSecOps Pipeline Series — Progressive CI/CD with Security + +This checked-in record is required by the active source contract for `project-35-devsecops-pipeline-series`. +It is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-35-devsecops-pipeline-series/P2_CLASSROOM.md b/project-35-devsecops-pipeline-series/P2_CLASSROOM.md new file mode 100644 index 00000000..fa03a6c3 --- /dev/null +++ b/project-35-devsecops-pipeline-series/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps Pipeline Series — Progressive CI/CD with Security + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-35-devsecops-pipeline-series/P2_EVIDENCE.md b/project-35-devsecops-pipeline-series/P2_EVIDENCE.md new file mode 100644 index 00000000..eae8d492 --- /dev/null +++ b/project-35-devsecops-pipeline-series/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps Pipeline Series — Progressive CI/CD with Security + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-35-devsecops-pipeline-series/P2_HARDENING.md b/project-35-devsecops-pipeline-series/P2_HARDENING.md new file mode 100644 index 00000000..b6f4f2ca --- /dev/null +++ b/project-35-devsecops-pipeline-series/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps Pipeline Series — Progressive CI/CD with Security + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-35-devsecops-pipeline-series/P2_LOCAL_PILOT.md b/project-35-devsecops-pipeline-series/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..f1b7e492 --- /dev/null +++ b/project-35-devsecops-pipeline-series/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps Pipeline Series — Progressive CI/CD with Security + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-35-devsecops-pipeline-series/START_HERE.md b/project-35-devsecops-pipeline-series/START_HERE.md new file mode 100644 index 00000000..3813c105 --- /dev/null +++ b/project-35-devsecops-pipeline-series/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-35-devsecops-pipeline-series + +**Learning focus:** Local DevSecOps CI/CD security pipeline analysis + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read the top-level readme and map the six folders into a local checklist without +running Terraform, cloud, deployment, or teardown commands. + +## Checkpoints + +1. 1. The learner can label the six stages as infrastructure, SAST, SCA, image build/push, Kubernetes deployment, and DAST/end-to-end from the readme +2. 1. The learner can identify the local validation command in project.yaml and distinguish the EasyBuggy Maven/Docker material from the cloud-dependent Terraform and Kubernetes files +3. 1. The learner can produce a stage-by-stage evidence table linking Jenkinsfiles, pom.xml/Dockerfiles, scan tools, and the final ZAP/end-to-end stage without executing live-cloud steps. + +## Hints if you are stuck + +1. 1. If the sequence feels unclear, compare the readme architecture arrows with the numbered step folders before opening implementation files +2. 1. If a check appears unsafe or cloud-dependent, first classify it by the project.yaml cloud, IaC, and CI/CD fields and look for a local analogue +3. 1. If the EasyBuggy stage is hard to interpret, use its listed Maven/Docker quick-start artifacts and vulnerability categories to explain what the pipeline is meant to observe, not to reproduce attacks. + +## Evidence to capture + +A local six-stage pipeline map, dependency/tool classification, and recorded result or rationale for the +project.yaml Maven test validation command + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-35-devsecops-pipeline-series/fixtures/evidence-local-result.txt b/project-35-devsecops-pipeline-series/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..33bcc4cb --- /dev/null +++ b/project-35-devsecops-pipeline-series/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-35-devsecops-pipeline-series +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-35-devsecops-pipeline-series/fixtures/intentionally-vulnerable/README.md b/project-35-devsecops-pipeline-series/fixtures/intentionally-vulnerable/README.md new file mode 100644 index 00000000..21b90172 --- /dev/null +++ b/project-35-devsecops-pipeline-series/fixtures/intentionally-vulnerable/README.md @@ -0,0 +1,10 @@ +# Intentionally Vulnerable Fixture + +This synthetic fixture supports deterministic local-first validation for `project-35-devsecops-pipeline-series`. + +| Field | Value | +| --- | --- | +| Path | `fixtures/intentionally-vulnerable/README.md` | +| Purpose | Local-first validation only | +| Credentials | None | +| Cloud authorization | None | diff --git a/project-35-devsecops-pipeline-series/pipeline_security.py b/project-35-devsecops-pipeline-series/pipeline_security.py new file mode 100644 index 00000000..9584850f --- /dev/null +++ b/project-35-devsecops-pipeline-series/pipeline_security.py @@ -0,0 +1,19 @@ +"""Local-only teaching helper for project-35-devsecops-pipeline-series. + +This reconstructed module contains no remote service, cloud credential, or deployment +behavior. It is intentionally deterministic for classroom evidence. +""" + +from __future__ import annotations + + +def local_status() -> dict[str, str]: + return { + "project": "project-35-devsecops-pipeline-series", + "mode": "local-first", + "status": "ready-for-local-validation", + } + + +if __name__ == "__main__": + print(local_status()) diff --git a/project-35-devsecops-pipeline-series/policy.json b/project-35-devsecops-pipeline-series/policy.json new file mode 100644 index 00000000..8dfb9076 --- /dev/null +++ b/project-35-devsecops-pipeline-series/policy.json @@ -0,0 +1,14 @@ +{ + "authorization": "none", + "contains_credentials": false, + "project": "project-35-devsecops-pipeline-series", + "purpose": "synthetic policy fixture for local-first validation", + "rules": [ + { + "condition": "fixture scope is local", + "effect": "allow", + "id": "local-only" + } + ], + "schema_version": "1.0" +} diff --git a/project-35-devsecops-pipeline-series/reset-local.sh b/project-35-devsecops-pipeline-series/reset-local.sh new file mode 100755 index 00000000..1011cfbe --- /dev/null +++ b/project-35-devsecops-pipeline-series/reset-local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +# Local classroom reset only; no provider, container, or deployment command is used. +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +[ "$(basename "$root")" = "project-35-devsecops-pipeline-series" ] || exit 1 +rm -f "$root/evidence/local-validation.tmp" +printf '%s reset: local-only state cleared\n' 'project-35-devsecops-pipeline-series' diff --git a/project-35-devsecops-pipeline-series/test_pipeline_security.py b/project-35-devsecops-pipeline-series/test_pipeline_security.py new file mode 100644 index 00000000..3cc41a72 --- /dev/null +++ b/project-35-devsecops-pipeline-series/test_pipeline_security.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def test_local_classroom_prerequisites() -> None: + root = next( + path + for path in Path(__file__).resolve().parents + if path.name == "project-35-devsecops-pipeline-series" + ) + assert (root / "README.md").is_file() + assert (root / "START_HERE.md").is_file() diff --git a/project-35-devsecops-pipeline-series/validate-local.sh b/project-35-devsecops-pipeline-series/validate-local.sh new file mode 100755 index 00000000..0c40bd98 --- /dev/null +++ b/project-35-devsecops-pipeline-series/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-35-devsecops-pipeline-series" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-35-devsecops-pipeline-series' 'validate-local.sh' diff --git a/project-35-devsecops-pipeline-series/validate-p2-local.sh b/project-35-devsecops-pipeline-series/validate-p2-local.sh new file mode 100755 index 00000000..8de0592b --- /dev/null +++ b/project-35-devsecops-pipeline-series/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-35-devsecops-pipeline-series" ]; then + printf '%s +' "ERROR: expected project-35-devsecops-pipeline-series; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-35-devsecops-pipeline-series' diff --git a/project-36-aws-realtime-deployment/.p1_active_paths b/project-36-aws-realtime-deployment/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-36-aws-realtime-deployment/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-36-aws-realtime-deployment/P1_LOCAL_CONTRACT.md b/project-36-aws-realtime-deployment/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..e932c927 --- /dev/null +++ b/project-36-aws-realtime-deployment/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — ☁️ AWS DevOps Real-Time Deployment - Dev → Pre-PROD → Production + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-36-aws-realtime-deployment/P2_CLASSROOM.md b/project-36-aws-realtime-deployment/P2_CLASSROOM.md new file mode 100644 index 00000000..dc3918b7 --- /dev/null +++ b/project-36-aws-realtime-deployment/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — ☁️ AWS DevOps Real-Time Deployment - Dev → Pre-PROD → Production + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-36-aws-realtime-deployment/P2_EVIDENCE.md b/project-36-aws-realtime-deployment/P2_EVIDENCE.md new file mode 100644 index 00000000..7ce9bf46 --- /dev/null +++ b/project-36-aws-realtime-deployment/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — ☁️ AWS DevOps Real-Time Deployment - Dev → Pre-PROD → Production + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-36-aws-realtime-deployment/P2_HARDENING.md b/project-36-aws-realtime-deployment/P2_HARDENING.md new file mode 100644 index 00000000..8b8fc85c --- /dev/null +++ b/project-36-aws-realtime-deployment/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — ☁️ AWS DevOps Real-Time Deployment - Dev → Pre-PROD → Production + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-36-aws-realtime-deployment/P2_LOCAL_PILOT.md b/project-36-aws-realtime-deployment/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..e14ca98e --- /dev/null +++ b/project-36-aws-realtime-deployment/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — ☁️ AWS DevOps Real-Time Deployment - Dev → Pre-PROD → Production + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-36-aws-realtime-deployment/START_HERE.md b/project-36-aws-realtime-deployment/START_HERE.md new file mode 100644 index 00000000..214c45fa --- /dev/null +++ b/project-36-aws-realtime-deployment/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-36-aws-realtime-deployment + +**Learning focus:** AWS DevSecOps CI/CD deployment with environment isolation + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the local README.md, project.yaml, appspec.yml, and buildspec.yml together and annotate how the HTML +artifact is intended to move through isolated Dev, Pre-Prod, and Production stages without connecting to AWS. + +## Checkpoints + +1. 1. A local inventory confirms the HTML entry point, Nginx install/start scripts, appspec.yml, and buildspec.yml are present +2. 1. A learner-produced diagram or notes trace the intended CodeBuild-to-CodeDeploy/CodePipeline flow and identify separate environments or accounts/VPCs as the isolation boundary +3. 1. A local validation record shows the packet's required files satisfy `test -f buildspec.yml -a -f appspec.yml` without performing deployment or teardown. + +## Hints if you are stuck + +1. 1. Compare the filenames referenced by the deployment configuration with the actual repository paths, including both scripts under `scripts/` +2. 1. If the pipeline stages are unclear, separate the questions of what builds the HTML package, what installs or starts Nginx, and what promotes between environments +3. 1. Treat the README's environment-isolation claim as an architecture requirement and check whether your notes distinguish Dev, Pre-Prod, and Production rather than collapsing them into one target. + +## Evidence to capture + +Annotated local file map, environment-isolation deployment-flow sketch, and captured local file-presence +validation + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-36-aws-realtime-deployment/fixtures/clean/contract.txt b/project-36-aws-realtime-deployment/fixtures/clean/contract.txt new file mode 100644 index 00000000..3856aa3d --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/clean/p2-clean.txt b/project-36-aws-realtime-deployment/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..1689d8e2 --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/evidence-local-result.txt b/project-36-aws-realtime-deployment/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..d6399bbc --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/negative/credential.txt b/project-36-aws-realtime-deployment/fixtures/negative/credential.txt new file mode 100644 index 00000000..f555591a --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/negative/mutation.txt b/project-36-aws-realtime-deployment/fixtures/negative/mutation.txt new file mode 100644 index 00000000..fb3ce313 --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/negative/p2-source-shaped.txt b/project-36-aws-realtime-deployment/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..bf34a43a --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/fixtures/negative/public_bind.txt b/project-36-aws-realtime-deployment/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..c19283c1 --- /dev/null +++ b/project-36-aws-realtime-deployment/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-36-aws-realtime-deployment +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-36-aws-realtime-deployment/local-lab/contract.json b/project-36-aws-realtime-deployment/local-lab/contract.json new file mode 100644 index 00000000..48685f0c --- /dev/null +++ b/project-36-aws-realtime-deployment/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-36-aws-realtime-deployment", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-36-aws-realtime-deployment/reset-p2-local.sh b/project-36-aws-realtime-deployment/reset-p2-local.sh new file mode 100755 index 00000000..62b57b06 --- /dev/null +++ b/project-36-aws-realtime-deployment/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-36-aws-realtime-deployment" ]; then + printf '%s +' "ERROR: expected project-36-aws-realtime-deployment; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-36-aws-realtime-deployment' diff --git a/project-36-aws-realtime-deployment/validate-p1-stream3.sh b/project-36-aws-realtime-deployment/validate-p1-stream3.sh new file mode 100755 index 00000000..d0e3ae46 --- /dev/null +++ b/project-36-aws-realtime-deployment/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-36-aws-realtime-deployment" ]; then + printf '%s +' "ERROR: expected project-36-aws-realtime-deployment; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-36-aws-realtime-deployment' diff --git a/project-36-aws-realtime-deployment/validate-p2-local.sh b/project-36-aws-realtime-deployment/validate-p2-local.sh new file mode 100755 index 00000000..62b57b06 --- /dev/null +++ b/project-36-aws-realtime-deployment/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-36-aws-realtime-deployment" ]; then + printf '%s +' "ERROR: expected project-36-aws-realtime-deployment; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-36-aws-realtime-deployment' diff --git a/project-37-eks-terraform-provision/P0_REMEDIATION.md b/project-37-eks-terraform-provision/P0_REMEDIATION.md new file mode 100644 index 00000000..d9f292b8 --- /dev/null +++ b/project-37-eks-terraform-provision/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +## Scope + +This record defines the active classroom path for `project-37-eks-terraform-provision`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-37-eks-terraform-provision/P2_CLASSROOM.md b/project-37-eks-terraform-provision/P2_CLASSROOM.md new file mode 100644 index 00000000..6cdc1a61 --- /dev/null +++ b/project-37-eks-terraform-provision/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-37-eks-terraform-provision/P2_EVIDENCE.md b/project-37-eks-terraform-provision/P2_EVIDENCE.md new file mode 100644 index 00000000..1922d1f3 --- /dev/null +++ b/project-37-eks-terraform-provision/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-37-eks-terraform-provision/P2_HARDENING.md b/project-37-eks-terraform-provision/P2_HARDENING.md new file mode 100644 index 00000000..97a166ad --- /dev/null +++ b/project-37-eks-terraform-provision/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-37-eks-terraform-provision/P2_LOCAL_PILOT.md b/project-37-eks-terraform-provision/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..4b4856b3 --- /dev/null +++ b/project-37-eks-terraform-provision/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-37-eks-terraform-provision/START_HERE.md b/project-37-eks-terraform-provision/START_HERE.md new file mode 100644 index 00000000..d5753f95 --- /dev/null +++ b/project-37-eks-terraform-provision/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-37-eks-terraform-provision + +**Learning focus:** AWS EKS infrastructure-as-code with Terraform: VPC networking, IAM, security groups, and +node-group configuration + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Open the project locally and trace the Terraform resource references from `vpc.tf`, `subnets.tf`, +`internetgw.tf`, and `rout.tf` into the EKS cluster and node-group files without running `terraform apply`. + +## Checkpoints + +1. 1. A local dependency map identifies the VPC, two public subnets, internet gateway, route-table associations, security group, IAM roles/policies, EKS cluster, kubectl-server EC2 instance, and EKS node group +2. 1. `terraform fmt -check` and `terraform validate` complete locally after the learner reviews the backend placeholders and variable/default configuration +3. 1. A dry-run plan is inspected locally and the learner can explain the expected EKS cluster, two-node desired capacity, subnet placement, SSH source restriction, and the resources that would incur AWS charges, without applying it. + +## Hints if you are stuck + +1. 1. If validation or planning reports a backend problem, inspect `eks-backend-terra.tf` for placeholder bucket, key, region, and lock-table values before changing resource definitions +2. 1. If a reference is unresolved, follow the resource name across `vpc.tf`, `subnets.tf`, `iam_role.tf`, `eks_cluster.tf`, and `eks_node_group.tf`, paying attention to hyphenated resource labels +3. 1. If the security review conflicts with the README's safer-default note, compare the active `sg.tf` ingress rule with the documented `admin_cidr_blocks` setting and record the discrepancy rather than widening access. + +## Evidence to capture + +Local formatted/validated Terraform files, a dependency map or annotated resource graph, and a reviewed +non-applied plan summary with cost and security observations + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-37-eks-terraform-provision/SUPPORTED_VERSIONS.md b/project-37-eks-terraform-provision/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..ef4582db --- /dev/null +++ b/project-37-eks-terraform-provision/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — PROVISION EKS (Amazon Elastic Kubernetes Service) CLUSTER ON AWS USING TERRAFORM + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-37-eks-terraform-provision/fixtures/evidence-local-result.txt b/project-37-eks-terraform-provision/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..fc8fe02b --- /dev/null +++ b/project-37-eks-terraform-provision/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-37-eks-terraform-provision +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-37-eks-terraform-provision/tests/test_policy.sh b/project-37-eks-terraform-provision/tests/test_policy.sh new file mode 100755 index 00000000..7bd79450 --- /dev/null +++ b/project-37-eks-terraform-provision/tests/test_policy.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-37-eks-terraform-provision" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-37-eks-terraform-provision' 'test_policy.sh' diff --git a/project-37-eks-terraform-provision/validate-local.sh b/project-37-eks-terraform-provision/validate-local.sh new file mode 100755 index 00000000..90c26bf2 --- /dev/null +++ b/project-37-eks-terraform-provision/validate-local.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-37-eks-terraform-provision" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-37-eks-terraform-provision' 'validate-local.sh' diff --git a/project-37-eks-terraform-provision/validate-p2-local.sh b/project-37-eks-terraform-provision/validate-p2-local.sh new file mode 100755 index 00000000..738e0583 --- /dev/null +++ b/project-37-eks-terraform-provision/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-37-eks-terraform-provision" ]; then + printf '%s +' "ERROR: expected project-37-eks-terraform-provision; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-37-eks-terraform-provision' diff --git a/project-38-docker-terraform-3tier/P2_CLASSROOM.md b/project-38-docker-terraform-3tier/P2_CLASSROOM.md new file mode 100644 index 00000000..a87b4b75 --- /dev/null +++ b/project-38-docker-terraform-3tier/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — ⇥ Docker & Terraform Three Tier Architecture + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-38-docker-terraform-3tier/P2_EVIDENCE.md b/project-38-docker-terraform-3tier/P2_EVIDENCE.md new file mode 100644 index 00000000..7c88a0b3 --- /dev/null +++ b/project-38-docker-terraform-3tier/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — ⇥ Docker & Terraform Three Tier Architecture + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-38-docker-terraform-3tier/P2_HARDENING.md b/project-38-docker-terraform-3tier/P2_HARDENING.md new file mode 100644 index 00000000..3ebe249b --- /dev/null +++ b/project-38-docker-terraform-3tier/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — ⇥ Docker & Terraform Three Tier Architecture + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-38-docker-terraform-3tier/P2_LOCAL_PILOT.md b/project-38-docker-terraform-3tier/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..ec627ec3 --- /dev/null +++ b/project-38-docker-terraform-3tier/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — ⇥ Docker & Terraform Three Tier Architecture + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-38-docker-terraform-3tier/START_HERE.md b/project-38-docker-terraform-3tier/START_HERE.md new file mode 100644 index 00000000..9742b3c4 --- /dev/null +++ b/project-38-docker-terraform-3tier/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-38-docker-terraform-3tier + +**Learning focus:** Local Docker Compose three-tier Node.js application architecture with Terraform/IaC design + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, review `README.md` and run the packet’s local validation command `docker compose +config` without supplying cloud credentials or applying Terraform. + +## Checkpoints + +1. 1. `docker compose config` parses the three services (`webapp`, `api`, and `db`) and shows the two networks and webapp port mapping +2. 1. The local compose stack builds and starts, with the webapp, API, and PostgreSQL containers reporting running/listening status +3. 1. Visiting `http://localhost:3000` displays the countries-and-capitals table, while the Terraform directory passes `terraform fmt -check` and `terraform validate` without any apply operation. + +## Hints if you are stuck + +1. 1. If Compose cannot resolve the API or database, compare the service names and attached `network-frontend`/`network-backend` networks with the environment variables in `docker-compose.yml` +2. 1. If the table is empty or the API returns an error, inspect the database container’s initialization output and verify that `init_sql_scripts/init.sql` was mounted as shown +3. 1. If Terraform validation fails, check formatting, required variable declarations, and references among the VPC, subnet, security-group, ALB, EC2, and RDS files before considering any provider interaction. + +## Evidence to capture + +Local `docker compose config` output, container/status and relevant logs, browser capture of the localhost +countries-and-capitals table, and Terraform formatting/validation output + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-38-docker-terraform-3tier/SUPPORTED_VERSIONS.md b/project-38-docker-terraform-3tier/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..8d5e7d04 --- /dev/null +++ b/project-38-docker-terraform-3tier/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — ⇥ Docker & Terraform Three Tier Architecture + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-38-docker-terraform-3tier/fixtures/evidence-local-result.txt b/project-38-docker-terraform-3tier/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..ea060ab7 --- /dev/null +++ b/project-38-docker-terraform-3tier/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-38-docker-terraform-3tier +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-38-docker-terraform-3tier/validate-p1-stream2.sh b/project-38-docker-terraform-3tier/validate-p1-stream2.sh new file mode 100755 index 00000000..3737ee3d --- /dev/null +++ b/project-38-docker-terraform-3tier/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-38-docker-terraform-3tier" ]; then + printf '%s +' "ERROR: expected project-38-docker-terraform-3tier; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-38-docker-terraform-3tier' diff --git a/project-38-docker-terraform-3tier/validate-p2-local.sh b/project-38-docker-terraform-3tier/validate-p2-local.sh new file mode 100755 index 00000000..bd09dbcd --- /dev/null +++ b/project-38-docker-terraform-3tier/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-38-docker-terraform-3tier" ]; then + printf '%s +' "ERROR: expected project-38-docker-terraform-3tier; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-38-docker-terraform-3tier' diff --git a/project-39-gha-aws-terraform/.github/workflows/local-plan.yml b/project-39-gha-aws-terraform/.github/workflows/local-plan.yml new file mode 100644 index 00000000..7e237da9 --- /dev/null +++ b/project-39-gha-aws-terraform/.github/workflows/local-plan.yml @@ -0,0 +1,13 @@ +--- +name: Local Policy Plan Check +"on": + pull_request: {} + workflow_dispatch: {} +permissions: + contents: read +jobs: + local-policy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: sh ci/check-local-policy.sh diff --git a/project-39-gha-aws-terraform/P0_REMEDIATION.md b/project-39-gha-aws-terraform/P0_REMEDIATION.md new file mode 100644 index 00000000..53468a5b --- /dev/null +++ b/project-39-gha-aws-terraform/P0_REMEDIATION.md @@ -0,0 +1,21 @@ +# P0 Local-First Remediation — 👉 GitHub Actions + AWS + Terraform # + +## Scope ## + +This record defines the active classroom path for `project-39-gha-aws-terraform`. It is source-only and +local-first: it must not require provider credentials, cloud accounts, external deployment, or destructive +lifecycle commands. + +## Required controls ## + +| Control | Classroom implementation | +| --- | --- | +| Starting boundary | Students begin with `README.md` and `START_HERE.md`. | +| Validation | Run only the project-local validator from the project root. | +| Evidence | Capture local validator output and the listed local fixture results. | +| Escalation | Ask the instructor before any provider, container, or deployment action. | + +## Non-claim ## + +Passing local validation demonstrates source-level readiness only. It does not authorize or evidence a live +cloud deployment, teardown, or cost review. diff --git a/project-39-gha-aws-terraform/P2_CLASSROOM.md b/project-39-gha-aws-terraform/P2_CLASSROOM.md new file mode 100644 index 00000000..5b942357 --- /dev/null +++ b/project-39-gha-aws-terraform/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 👉 GitHub Actions + AWS + Terraform # + +## Learning and assessment ## + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow ## + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints ## + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-39-gha-aws-terraform/P2_EVIDENCE.md b/project-39-gha-aws-terraform/P2_EVIDENCE.md new file mode 100644 index 00000000..b3673cd2 --- /dev/null +++ b/project-39-gha-aws-terraform/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 👉 GitHub Actions + AWS + Terraform # + +## Evidence to retain ## + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary ## + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-39-gha-aws-terraform/P2_HARDENING.md b/project-39-gha-aws-terraform/P2_HARDENING.md new file mode 100644 index 00000000..e6072015 --- /dev/null +++ b/project-39-gha-aws-terraform/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 👉 GitHub Actions + AWS + Terraform # + +## Local-first controls ## + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist ## + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-39-gha-aws-terraform/P2_LOCAL_PILOT.md b/project-39-gha-aws-terraform/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..d2bf8206 --- /dev/null +++ b/project-39-gha-aws-terraform/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 👉 GitHub Actions + AWS + Terraform # + +## Purpose ## + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template ## + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition ## + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-39-gha-aws-terraform/START_HERE.md b/project-39-gha-aws-terraform/START_HERE.md new file mode 100644 index 00000000..31d9998b --- /dev/null +++ b/project-39-gha-aws-terraform/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-39-gha-aws-terraform + +**Learning focus:** Terraform-based AWS infrastructure and GitHub Actions CI/CD for container deployment + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read the readme and inspect the Terraform and workflow filenames locally, then run the repository's stated +validation command `terraform fmt -check` without applying or destroying anything. + +## Checkpoints + +1. 1. The learner can identify the stated stack and AWS components from the readme and project metadata +2. 1. `terraform fmt -check` completes locally and any formatting issue is recorded without changing infrastructure +3. 1. The learner can map the Terraform files, ECS/VPC modules, Docker files, and GitHub Actions workflows to their roles in the intended CI/CD path without triggering a workflow. + +## Hints if you are stuck + +1. 1. Start by separating configuration files from the two reusable Terraform module directories and note which files define inputs, outputs, and resources +2. 1. If formatting validation fails, inspect the reported file and compare its layout with Terraform's formatting conventions rather than changing deployment settings +3. 1. When tracing the workflow, follow references between ECR image building, Terraform apply, and Terraform destroy, and check required names or variables locally before considering any cloud action. + +## Evidence to capture + +Local `terraform fmt -check` result, a file-to-role map, and a short annotated diagram or notes tracing the +GitHub Actions/ECR/Terraform workflow + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-39-gha-aws-terraform/ci/check-local-policy.sh b/project-39-gha-aws-terraform/ci/check-local-policy.sh new file mode 100755 index 00000000..addf6a55 --- /dev/null +++ b/project-39-gha-aws-terraform/ci/check-local-policy.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-39-gha-aws-terraform" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-39-gha-aws-terraform' 'check-local-policy.sh' diff --git a/project-39-gha-aws-terraform/ci/plan-only.sh b/project-39-gha-aws-terraform/ci/plan-only.sh new file mode 100755 index 00000000..7441af2a --- /dev/null +++ b/project-39-gha-aws-terraform/ci/plan-only.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-39-gha-aws-terraform" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-39-gha-aws-terraform' 'plan-only.sh' diff --git a/project-39-gha-aws-terraform/ci/test-local-policy.sh b/project-39-gha-aws-terraform/ci/test-local-policy.sh new file mode 100755 index 00000000..54373bd0 --- /dev/null +++ b/project-39-gha-aws-terraform/ci/test-local-policy.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-39-gha-aws-terraform" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-39-gha-aws-terraform' 'test-local-policy.sh' diff --git a/project-39-gha-aws-terraform/fixtures/clean/plan-policy.json b/project-39-gha-aws-terraform/fixtures/clean/plan-policy.json new file mode 100644 index 00000000..4180867a --- /dev/null +++ b/project-39-gha-aws-terraform/fixtures/clean/plan-policy.json @@ -0,0 +1,9 @@ +{ + "contains_cloud_authorization": false, + "contains_credentials": false, + "decision": "pass", + "fixture": "clean-plan-policy", + "project": "project-39-gha-aws-terraform", + "purpose": "deterministic local-first validation only", + "schema_version": "1.0" +} diff --git a/project-39-gha-aws-terraform/fixtures/evidence-local-result.txt b/project-39-gha-aws-terraform/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..2a10cc14 --- /dev/null +++ b/project-39-gha-aws-terraform/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-39-gha-aws-terraform +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-39-gha-aws-terraform/fixtures/negative/mutation.yml b/project-39-gha-aws-terraform/fixtures/negative/mutation.yml new file mode 100644 index 00000000..84c364ed --- /dev/null +++ b/project-39-gha-aws-terraform/fixtures/negative/mutation.yml @@ -0,0 +1,9 @@ +--- +schema_version: "1.0" +project: project-39-gha-aws-terraform +fixture: negative-mutation +purpose: deterministic local-first validation only +authorization: none +contains_credentials: false +provider_actions_authorized: false +expected_result: fail diff --git a/project-39-gha-aws-terraform/validate-p2-local.sh b/project-39-gha-aws-terraform/validate-p2-local.sh new file mode 100755 index 00000000..44437a88 --- /dev/null +++ b/project-39-gha-aws-terraform/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-39-gha-aws-terraform" ]; then + printf '%s +' "ERROR: expected project-39-gha-aws-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-39-gha-aws-terraform' diff --git a/project-40-k8s-dashboard-trivy/.p1_active_paths b/project-40-k8s-dashboard-trivy/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-40-k8s-dashboard-trivy/P1_LOCAL_CONTRACT.md b/project-40-k8s-dashboard-trivy/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..c9758104 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — Kubernetes-Dashboard + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-40-k8s-dashboard-trivy/P2_CLASSROOM.md b/project-40-k8s-dashboard-trivy/P2_CLASSROOM.md new file mode 100644 index 00000000..37b67ec3 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Kubernetes-Dashboard + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-40-k8s-dashboard-trivy/P2_EVIDENCE.md b/project-40-k8s-dashboard-trivy/P2_EVIDENCE.md new file mode 100644 index 00000000..505d0b63 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Kubernetes-Dashboard + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-40-k8s-dashboard-trivy/P2_HARDENING.md b/project-40-k8s-dashboard-trivy/P2_HARDENING.md new file mode 100644 index 00000000..6a50a19a --- /dev/null +++ b/project-40-k8s-dashboard-trivy/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Kubernetes-Dashboard + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-40-k8s-dashboard-trivy/P2_LOCAL_PILOT.md b/project-40-k8s-dashboard-trivy/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..0efec831 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Kubernetes-Dashboard + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-40-k8s-dashboard-trivy/START_HERE.md b/project-40-k8s-dashboard-trivy/START_HERE.md new file mode 100644 index 00000000..207e6d99 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-40-k8s-dashboard-trivy + +**Learning focus:** Local Kubernetes dashboard observability and DevSecOps image scanning + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run the documented local validation command `node --check app.js && python3 -m +py_compile systeminfo.py` before attempting to launch the dashboard. + +## Checkpoints + +1. 1. Both `app.js` and `systeminfo.py` pass the syntax checks without errors +2. 1. The Flask dashboard opens at the documented local address and displays its system-metrics area +3. 1. A selected namespace shows Kubernetes resource counts and a test image scan produces a visible Trivy report in the dashboard. + +## Hints if you are stuck + +1. 1. If the first checkpoint fails, inspect the reported file and line number before changing behavior +2. 1. If the page loads but data is missing, check whether the local process has access to the expected Kubernetes context and namespace +3. 1. If scanning does not return a report, verify the image identifier and that the local Trivy command is available, then capture the exact error rather than broadening permissions. + +## Evidence to capture + +Validation output, local dashboard screenshot, namespace resource-count view, and Trivy scan report or +captured diagnostic error + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-40-k8s-dashboard-trivy/fixtures/clean/contract.txt b/project-40-k8s-dashboard-trivy/fixtures/clean/contract.txt new file mode 100644 index 00000000..c4116596 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/clean/p2-clean.txt b/project-40-k8s-dashboard-trivy/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..c537059a --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/evidence-local-result.txt b/project-40-k8s-dashboard-trivy/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..472be4f8 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/negative/credential.txt b/project-40-k8s-dashboard-trivy/fixtures/negative/credential.txt new file mode 100644 index 00000000..17c68d6f --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/negative/mutation.txt b/project-40-k8s-dashboard-trivy/fixtures/negative/mutation.txt new file mode 100644 index 00000000..6f09bd72 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/negative/p2-source-shaped.txt b/project-40-k8s-dashboard-trivy/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..9b1d128e --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/fixtures/negative/public_bind.txt b/project-40-k8s-dashboard-trivy/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..5f60ff28 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-40-k8s-dashboard-trivy +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-40-k8s-dashboard-trivy/local-lab/contract.json b/project-40-k8s-dashboard-trivy/local-lab/contract.json new file mode 100644 index 00000000..5c89ea9d --- /dev/null +++ b/project-40-k8s-dashboard-trivy/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-40-k8s-dashboard-trivy", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-40-k8s-dashboard-trivy/reset-p2-local.sh b/project-40-k8s-dashboard-trivy/reset-p2-local.sh new file mode 100755 index 00000000..78f268db --- /dev/null +++ b/project-40-k8s-dashboard-trivy/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-40-k8s-dashboard-trivy" ]; then + printf '%s +' "ERROR: expected project-40-k8s-dashboard-trivy; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-40-k8s-dashboard-trivy' diff --git a/project-40-k8s-dashboard-trivy/validate-p1-stream3.sh b/project-40-k8s-dashboard-trivy/validate-p1-stream3.sh new file mode 100755 index 00000000..1b5df711 --- /dev/null +++ b/project-40-k8s-dashboard-trivy/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-40-k8s-dashboard-trivy" ]; then + printf '%s +' "ERROR: expected project-40-k8s-dashboard-trivy; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-40-k8s-dashboard-trivy' diff --git a/project-40-k8s-dashboard-trivy/validate-p2-local.sh b/project-40-k8s-dashboard-trivy/validate-p2-local.sh new file mode 100755 index 00000000..78f268db --- /dev/null +++ b/project-40-k8s-dashboard-trivy/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-40-k8s-dashboard-trivy" ]; then + printf '%s +' "ERROR: expected project-40-k8s-dashboard-trivy; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-40-k8s-dashboard-trivy' diff --git a/project-41-online-boutique-microservices/P2_CLASSROOM.md b/project-41-online-boutique-microservices/P2_CLASSROOM.md new file mode 100644 index 00000000..2b267396 --- /dev/null +++ b/project-41-online-boutique-microservices/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Online Boutique Assignment + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-41-online-boutique-microservices/P2_EVIDENCE.md b/project-41-online-boutique-microservices/P2_EVIDENCE.md new file mode 100644 index 00000000..e89ead30 --- /dev/null +++ b/project-41-online-boutique-microservices/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Online Boutique Assignment + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-41-online-boutique-microservices/P2_HARDENING.md b/project-41-online-boutique-microservices/P2_HARDENING.md new file mode 100644 index 00000000..1a81894e --- /dev/null +++ b/project-41-online-boutique-microservices/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Online Boutique Assignment + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-41-online-boutique-microservices/P2_LOCAL_PILOT.md b/project-41-online-boutique-microservices/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..13439633 --- /dev/null +++ b/project-41-online-boutique-microservices/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Online Boutique Assignment + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-41-online-boutique-microservices/START_HERE.md b/project-41-online-boutique-microservices/START_HERE.md new file mode 100644 index 00000000..b3cd43d2 --- /dev/null +++ b/project-41-online-boutique-microservices/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-41-online-boutique-microservices + +**Learning focus:** Local Kubernetes microservices deployment and troubleshooting with Kind + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `kubectl apply --dry-run=client -f deploy/` to validate the supplied Kubernetes +manifests before creating or changing a local cluster. + +## Checkpoints + +1. 1. A local Kind cluster named `qa-cluster` exists and `kubectl get nodes` shows the control-plane and worker nodes as `Ready` +2. 1. After applying `deploy/`, all 11 Online Boutique service Pods reach `Running` and the Services expose the README’s stated service and target ports, with no unresolved scheduling, image, probe, or service-account issue +3. 1. A local port-forwarded frontend loads the Online Boutique home page, a test order completes successfully, and the `qa`-namespace load-generator log contains no failures. + +## Hints if you are stuck + +1. 1. For a Pod that remains `Pending` or fails to start, compare its scheduling constraints, image reference, events, and requested resources with the nodes in the supplied `kind-config/config.yaml` +2. 1. If the page opens but ordering fails, start with the `frontend` logs and trace the configured service DNS names and ports through the checkout, payment, currency, cart, email, and shipping dependencies +3. 1. If the load test reports errors after the browser flow works, inspect the load-generator namespace, endpoint configuration, and Pod logs before changing any application manifest. + +## Evidence to capture + +`kubectl get nodes` and `kubectl get all` output, manifest diffs with RCA in `SOLUTION.md`, a local +frontend/order verification record, and failure-free `test/loadgenerator-output.txt` + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-41-online-boutique-microservices/SUPPORTED_VERSIONS.md b/project-41-online-boutique-microservices/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..ea26c1b3 --- /dev/null +++ b/project-41-online-boutique-microservices/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Online Boutique Assignment + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-41-online-boutique-microservices/fixtures/evidence-local-result.txt b/project-41-online-boutique-microservices/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..b5b67090 --- /dev/null +++ b/project-41-online-boutique-microservices/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-41-online-boutique-microservices +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-41-online-boutique-microservices/validate-p1-stream2.sh b/project-41-online-boutique-microservices/validate-p1-stream2.sh new file mode 100755 index 00000000..56ac1b8a --- /dev/null +++ b/project-41-online-boutique-microservices/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-41-online-boutique-microservices" ]; then + printf '%s +' "ERROR: expected project-41-online-boutique-microservices; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-41-online-boutique-microservices' diff --git a/project-41-online-boutique-microservices/validate-p2-local.sh b/project-41-online-boutique-microservices/validate-p2-local.sh new file mode 100755 index 00000000..8ad05aef --- /dev/null +++ b/project-41-online-boutique-microservices/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-41-online-boutique-microservices" ]; then + printf '%s +' "ERROR: expected project-41-online-boutique-microservices; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-41-online-boutique-microservices' diff --git a/project-42-serverless-api-dynamodb/P2_CLASSROOM.md b/project-42-serverless-api-dynamodb/P2_CLASSROOM.md new file mode 100644 index 00000000..d3ed7bf6 --- /dev/null +++ b/project-42-serverless-api-dynamodb/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — terraform-serverless-rest-api-dynamodb + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-42-serverless-api-dynamodb/P2_EVIDENCE.md b/project-42-serverless-api-dynamodb/P2_EVIDENCE.md new file mode 100644 index 00000000..983d07f0 --- /dev/null +++ b/project-42-serverless-api-dynamodb/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — terraform-serverless-rest-api-dynamodb + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-42-serverless-api-dynamodb/P2_HARDENING.md b/project-42-serverless-api-dynamodb/P2_HARDENING.md new file mode 100644 index 00000000..fd87eae3 --- /dev/null +++ b/project-42-serverless-api-dynamodb/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — terraform-serverless-rest-api-dynamodb + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-42-serverless-api-dynamodb/P2_LOCAL_PILOT.md b/project-42-serverless-api-dynamodb/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..67feea0a --- /dev/null +++ b/project-42-serverless-api-dynamodb/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — terraform-serverless-rest-api-dynamodb + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-42-serverless-api-dynamodb/START_HERE.md b/project-42-serverless-api-dynamodb/START_HERE.md new file mode 100644 index 00000000..bf91afda --- /dev/null +++ b/project-42-serverless-api-dynamodb/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-42-serverless-api-dynamodb + +**Learning focus:** Infrastructure as code for a Node.js serverless REST API backed by DynamoDB + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read README.md and list the local Terraform and SAM files to map the API, Lambda, and +DynamoDB components before changing anything. + +## Checkpoints + +1. 1. You can point to the README's stated Lambda/API Gateway/DynamoDB stack and match it to the listed SAM and Terraform files +2. 1. You can run the packet's local validation command `terraform -chdir=terraform fmt -check` and record whether the Terraform formatting passes +3. 1. You can produce a local architecture note showing the GET and PUT controllers, shared helper layer, API definition, and sample product-import script without provisioning resources. + +## Hints if you are stuck + +1. 1. If the file map feels unclear, group the paths by runtime code, shared helpers, infrastructure definitions, and scripts before tracing relationships +2. 1. If the validation check fails, inspect formatting in the Terraform directory rather than changing application logic +3. 1. If you cannot explain a request path, compare the API definition with the names of the GET and PUT controller files and note the remaining question for the instructor. + +## Evidence to capture + +Local file-to-component map, recorded Terraform format-check result, and a short request/data-flow diagram or +written trace + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-42-serverless-api-dynamodb/fixtures/clean_local.txt b/project-42-serverless-api-dynamodb/fixtures/clean_local.txt new file mode 100644 index 00000000..8b5b4517 --- /dev/null +++ b/project-42-serverless-api-dynamodb/fixtures/clean_local.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-42-serverless-api-dynamodb +path=fixtures/clean_local.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-42-serverless-api-dynamodb/fixtures/evidence-local-result.txt b/project-42-serverless-api-dynamodb/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..ad08998a --- /dev/null +++ b/project-42-serverless-api-dynamodb/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-42-serverless-api-dynamodb +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-42-serverless-api-dynamodb/fixtures/negative_cloud_command.txt b/project-42-serverless-api-dynamodb/fixtures/negative_cloud_command.txt new file mode 100644 index 00000000..bb36db1a --- /dev/null +++ b/project-42-serverless-api-dynamodb/fixtures/negative_cloud_command.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-42-serverless-api-dynamodb +path=fixtures/negative_cloud_command.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-42-serverless-api-dynamodb/validate-p2-local.sh b/project-42-serverless-api-dynamodb/validate-p2-local.sh new file mode 100755 index 00000000..c8169014 --- /dev/null +++ b/project-42-serverless-api-dynamodb/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-42-serverless-api-dynamodb" ]; then + printf '%s +' "ERROR: expected project-42-serverless-api-dynamodb; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-42-serverless-api-dynamodb' diff --git a/project-42-serverless-api-dynamodb/validate_local.py b/project-42-serverless-api-dynamodb/validate_local.py new file mode 100755 index 00000000..685ea2e7 --- /dev/null +++ b/project-42-serverless-api-dynamodb/validate_local.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-42-serverless-api-dynamodb.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-42-serverless-api-dynamodb": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print("project-42-serverless-api-dynamodb local-only control: PASS (validate_local.py)") diff --git a/project-43-ecs-fargate-terraform/P2_CLASSROOM.md b/project-43-ecs-fargate-terraform/P2_CLASSROOM.md new file mode 100644 index 00000000..4dfd8141 --- /dev/null +++ b/project-43-ecs-fargate-terraform/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — **Deploying a Scalable Web App Using AWS ECS, ECR, and Fargate with Terraform** + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-43-ecs-fargate-terraform/P2_EVIDENCE.md b/project-43-ecs-fargate-terraform/P2_EVIDENCE.md new file mode 100644 index 00000000..d9a8fb46 --- /dev/null +++ b/project-43-ecs-fargate-terraform/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — **Deploying a Scalable Web App Using AWS ECS, ECR, and Fargate with Terraform** + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-43-ecs-fargate-terraform/P2_HARDENING.md b/project-43-ecs-fargate-terraform/P2_HARDENING.md new file mode 100644 index 00000000..c1879641 --- /dev/null +++ b/project-43-ecs-fargate-terraform/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — **Deploying a Scalable Web App Using AWS ECS, ECR, and Fargate with Terraform** + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-43-ecs-fargate-terraform/P2_LOCAL_PILOT.md b/project-43-ecs-fargate-terraform/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..eeee820d --- /dev/null +++ b/project-43-ecs-fargate-terraform/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — **Deploying a Scalable Web App Using AWS ECS, ECR, and Fargate with Terraform** + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-43-ecs-fargate-terraform/START_HERE.md b/project-43-ecs-fargate-terraform/START_HERE.md new file mode 100644 index 00000000..a8b6025e --- /dev/null +++ b/project-43-ecs-fargate-terraform/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-43-ecs-fargate-terraform + +**Learning focus:** Terraform-based AWS ECS Fargate container deployment and cloud networking/IAM architecture + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project directory, read README.md and inspect main.tf, variables.tf, providers.tf, outputs.tf, and +project.yaml without configuring credentials or running any apply command. + +## Checkpoints + +1. 1. `terraform fmt -check` reports whether the local Terraform files match the repository's stated validation command +2. 1. The student can trace, on paper or in a local diagram, the declared flow from container image/ECR through ECS Fargate, VPC subnets/security groups, and the application load balancer +3. 1. The student can identify in the Terraform files where the task execution role, task role, image reference, networking, and `alb_dns_name` output are defined, without applying infrastructure. + +## Hints if you are stuck + +1. 1. If formatting validation fails, compare indentation and block layout across all `.tf` files before changing resource behavior +2. 1. If the architecture is unclear, follow references from variables and provider configuration into the ECS task definition and service, then outward to networking and load-balancer resources +3. 1. If the two IAM roles seem interchangeable, use the README's distinction between ECS agent operations and permissions used by application code as the comparison criterion. + +## Evidence to capture + +A local validation result, annotated architecture sketch, and file/line references for image, IAM roles, +network wiring, and ALB output + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-43-ecs-fargate-terraform/SUPPORTED_VERSIONS.md b/project-43-ecs-fargate-terraform/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..0916abf8 --- /dev/null +++ b/project-43-ecs-fargate-terraform/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — **Deploying a Scalable Web App Using AWS ECS, ECR, and Fargate with Terraform** + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-43-ecs-fargate-terraform/fixtures/evidence-local-result.txt b/project-43-ecs-fargate-terraform/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..69931fd5 --- /dev/null +++ b/project-43-ecs-fargate-terraform/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-43-ecs-fargate-terraform +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-43-ecs-fargate-terraform/validate-p1-stream2.sh b/project-43-ecs-fargate-terraform/validate-p1-stream2.sh new file mode 100755 index 00000000..9ae995d7 --- /dev/null +++ b/project-43-ecs-fargate-terraform/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-43-ecs-fargate-terraform" ]; then + printf '%s +' "ERROR: expected project-43-ecs-fargate-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-43-ecs-fargate-terraform' diff --git a/project-43-ecs-fargate-terraform/validate-p2-local.sh b/project-43-ecs-fargate-terraform/validate-p2-local.sh new file mode 100755 index 00000000..774deaed --- /dev/null +++ b/project-43-ecs-fargate-terraform/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-43-ecs-fargate-terraform" ]; then + printf '%s +' "ERROR: expected project-43-ecs-fargate-terraform; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-43-ecs-fargate-terraform' diff --git a/project-44-devsecops-101/.p1_active_paths b/project-44-devsecops-101/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-44-devsecops-101/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-44-devsecops-101/P1_LOCAL_CONTRACT.md b/project-44-devsecops-101/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..876446f3 --- /dev/null +++ b/project-44-devsecops-101/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — DevSecOps-Project + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-44-devsecops-101/P2_CLASSROOM.md b/project-44-devsecops-101/P2_CLASSROOM.md new file mode 100644 index 00000000..61b13817 --- /dev/null +++ b/project-44-devsecops-101/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DevSecOps-Project + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-44-devsecops-101/P2_EVIDENCE.md b/project-44-devsecops-101/P2_EVIDENCE.md new file mode 100644 index 00000000..243af3f1 --- /dev/null +++ b/project-44-devsecops-101/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DevSecOps-Project + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-44-devsecops-101/P2_HARDENING.md b/project-44-devsecops-101/P2_HARDENING.md new file mode 100644 index 00000000..74317322 --- /dev/null +++ b/project-44-devsecops-101/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DevSecOps-Project + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-44-devsecops-101/P2_LOCAL_PILOT.md b/project-44-devsecops-101/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..e0b17741 --- /dev/null +++ b/project-44-devsecops-101/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DevSecOps-Project + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-44-devsecops-101/START_HERE.md b/project-44-devsecops-101/START_HERE.md new file mode 100644 index 00000000..4bdc8819 --- /dev/null +++ b/project-44-devsecops-101/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-44-devsecops-101 + +**Learning focus:** Local DevSecOps CI/CD for a Spring Boot application + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect README.md, Jenkinsfile, Dockerfile, and spring-boot-deployment.yaml, then run +the packet's local validation command ./mvnw test without configuring Jenkins, AWS, Docker Hub, Vault, Slack, +or Kubernetes. + +## Checkpoints + +1. 1. ./mvnw test completes and produces the Maven test output for DemoApplicationTests +2. 1. The student can trace the Jenkinsfile stages from Git checkout through Maven/JUnit, SonarQube, Docker/Trivy, report upload, image push, and Kubernetes deployment +3. 1. The student can match Dockerfile and spring-boot-deployment.yaml to the intended Spring Boot image-and-service flow without using external credentials or live infrastructure. + +## Hints if you are stuck + +1. 1. If the first check fails, distinguish a Maven/dependency or Java-version problem from a test assertion failure by reading the earliest actionable error and the surefire output path +2. 1. For a pipeline-reading mismatch, compare each stage name and shell command with the pipeline-flow sequence in README.md +3. 1. For manifest or image questions, check whether the image reference, container port, service type, and declared application settings agree across Dockerfile, spring-boot-deployment.yaml, and application.properties. + +## Evidence to capture + +Local ./mvnw test result plus annotated stage-to-file mapping and a reviewed Docker/Kubernetes configuration +comparison + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-44-devsecops-101/fixtures/clean/contract.txt b/project-44-devsecops-101/fixtures/clean/contract.txt new file mode 100644 index 00000000..762d06bd --- /dev/null +++ b/project-44-devsecops-101/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/clean/p2-clean.txt b/project-44-devsecops-101/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..882e7e67 --- /dev/null +++ b/project-44-devsecops-101/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/evidence-local-result.txt b/project-44-devsecops-101/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..3ba48083 --- /dev/null +++ b/project-44-devsecops-101/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/negative/credential.txt b/project-44-devsecops-101/fixtures/negative/credential.txt new file mode 100644 index 00000000..234099c2 --- /dev/null +++ b/project-44-devsecops-101/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/negative/mutation.txt b/project-44-devsecops-101/fixtures/negative/mutation.txt new file mode 100644 index 00000000..006842b4 --- /dev/null +++ b/project-44-devsecops-101/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/negative/p2-source-shaped.txt b/project-44-devsecops-101/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..8bf59312 --- /dev/null +++ b/project-44-devsecops-101/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/fixtures/negative/public_bind.txt b/project-44-devsecops-101/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..ed13565b --- /dev/null +++ b/project-44-devsecops-101/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-44-devsecops-101 +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-44-devsecops-101/local-lab/contract.json b/project-44-devsecops-101/local-lab/contract.json new file mode 100644 index 00000000..4593a313 --- /dev/null +++ b/project-44-devsecops-101/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-44-devsecops-101", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-44-devsecops-101/reset-p2-local.sh b/project-44-devsecops-101/reset-p2-local.sh new file mode 100755 index 00000000..d850015c --- /dev/null +++ b/project-44-devsecops-101/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-44-devsecops-101" ]; then + printf '%s +' "ERROR: expected project-44-devsecops-101; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-44-devsecops-101' diff --git a/project-44-devsecops-101/validate-p1-stream3.sh b/project-44-devsecops-101/validate-p1-stream3.sh new file mode 100755 index 00000000..9eaa0966 --- /dev/null +++ b/project-44-devsecops-101/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-44-devsecops-101" ]; then + printf '%s +' "ERROR: expected project-44-devsecops-101; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-44-devsecops-101' diff --git a/project-44-devsecops-101/validate-p2-local.sh b/project-44-devsecops-101/validate-p2-local.sh new file mode 100755 index 00000000..d850015c --- /dev/null +++ b/project-44-devsecops-101/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-44-devsecops-101" ]; then + printf '%s +' "ERROR: expected project-44-devsecops-101; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-44-devsecops-101' diff --git a/project-45-jenkins-cicd-argocd-vault/.p1_active_paths b/project-45-jenkins-cicd-argocd-vault/.p1_active_paths new file mode 100644 index 00000000..fb5e9633 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/.p1_active_paths @@ -0,0 +1,2 @@ +README.md +START_HERE.md diff --git a/project-45-jenkins-cicd-argocd-vault/P1_LOCAL_CONTRACT.md b/project-45-jenkins-cicd-argocd-vault/P1_LOCAL_CONTRACT.md new file mode 100644 index 00000000..0447722d --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/P1_LOCAL_CONTRACT.md @@ -0,0 +1,17 @@ +# P1 Local Contract — DEVOPS_JENKINS_101 + +## Allowed local path + +Students may inspect checked-in source, fixtures, and documentation and may run the local validation scripts +declared in the active-integrity manifest. + +## Prohibited operations + +Do not use credentials, provider CLIs, cloud endpoints, deployment commands, destructive commands, or +production/shared environments. The contract fails closed: when a required local prerequisite is unavailable, +stop and ask the instructor. + +## Observable outcome + +A successful local validation run reports the project identifier, confirms the active documents and fixtures, +and records a source-only PASS result. diff --git a/project-45-jenkins-cicd-argocd-vault/P2_CLASSROOM.md b/project-45-jenkins-cicd-argocd-vault/P2_CLASSROOM.md new file mode 100644 index 00000000..1efd73a6 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — DEVOPS_JENKINS_101 + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-45-jenkins-cicd-argocd-vault/P2_EVIDENCE.md b/project-45-jenkins-cicd-argocd-vault/P2_EVIDENCE.md new file mode 100644 index 00000000..29cc35c7 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — DEVOPS_JENKINS_101 + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-45-jenkins-cicd-argocd-vault/P2_HARDENING.md b/project-45-jenkins-cicd-argocd-vault/P2_HARDENING.md new file mode 100644 index 00000000..084f7ce0 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — DEVOPS_JENKINS_101 + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-45-jenkins-cicd-argocd-vault/P2_LOCAL_PILOT.md b/project-45-jenkins-cicd-argocd-vault/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..3b1f966d --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — DEVOPS_JENKINS_101 + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-45-jenkins-cicd-argocd-vault/START_HERE.md b/project-45-jenkins-cicd-argocd-vault/START_HERE.md new file mode 100644 index 00000000..ff4692b0 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-45-jenkins-cicd-argocd-vault + +**Learning focus:** DevSecOps CI/CD pipeline integration with Jenkins, Docker, Kubernetes, Argo CD, and Vault + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Read the readme pipeline-flow section and trace the existing Jenkinsfile and application files locally, +without installing tools, contacting cloud services, or changing credentials. + +## Checkpoints + +1. 1. Identify and record the local application, Maven test, Dockerfile, Jenkinsfile, and project.yaml roles, then map them to the README's CI/CD stages +2. 1. Explain the expected handoff from a Jenkins build and test through SonarQube/Trivy checks and image publication using the README's stated sequence, without running it +3. 1. Produce a local dry-run review showing where a successful pipeline would update a Kubernetes image tag and where Argo CD would observe the resulting manifest change, without deploying to Kubernetes. + +## Hints if you are stuck + +1. 1. If the project flow seems unclear, compare the numbered readme pipeline steps with the stage names and commands in Jenkinsfile rather than starting from the cloud prerequisites +2. 1. If a stage's input or output is ambiguous, inspect the neighboring Maven, Dockerfile, Java source, application.properties, and project.yaml files for names and paths +3. 1. If you encounter a credentials or endpoint question, mark it as an instructor-controlled configuration dependency and do not substitute real AWS, Docker Hub, Slack, SonarQube, Artifactory, Jenkins, Argo CD, or Vault secrets. + +## Evidence to capture + +Annotated local pipeline map, file-to-stage trace, and a dry-run explanation of build/test, security checks, +image-tag update, pull request, and Argo CD handoff + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/clean/contract.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/clean/contract.txt new file mode 100644 index 00000000..6f069fc1 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/clean/contract.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/clean/contract.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/clean/p2-clean.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/clean/p2-clean.txt new file mode 100644 index 00000000..a3e1e7ce --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/clean/p2-clean.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/clean/p2-clean.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/evidence-local-result.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a61dacc6 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/negative/credential.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/credential.txt new file mode 100644 index 00000000..7a388c18 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/credential.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/negative/credential.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/negative/mutation.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/mutation.txt new file mode 100644 index 00000000..3b904826 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/mutation.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/negative/mutation.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/negative/p2-source-shaped.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/p2-source-shaped.txt new file mode 100644 index 00000000..443c7bbd --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/p2-source-shaped.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/negative/p2-source-shaped.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/fixtures/negative/public_bind.txt b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/public_bind.txt new file mode 100644 index 00000000..1c66b8c2 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/fixtures/negative/public_bind.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-45-jenkins-cicd-argocd-vault +path=fixtures/negative/public_bind.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-45-jenkins-cicd-argocd-vault/local-lab/contract.json b/project-45-jenkins-cicd-argocd-vault/local-lab/contract.json new file mode 100644 index 00000000..8a43d474 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/local-lab/contract.json @@ -0,0 +1,8 @@ +{ + "project": "project-45-jenkins-cicd-argocd-vault", + "mode": "local-first", + "provider_access": "prohibited", + "credentials": "prohibited", + "destructive_operations": "prohibited", + "evidence": "synthetic-local-fixtures" +} diff --git a/project-45-jenkins-cicd-argocd-vault/reset-p2-local.sh b/project-45-jenkins-cicd-argocd-vault/reset-p2-local.sh new file mode 100755 index 00000000..916c8f29 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/reset-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-45-jenkins-cicd-argocd-vault" ]; then + printf '%s +' "ERROR: expected project-45-jenkins-cicd-argocd-vault; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-45-jenkins-cicd-argocd-vault' diff --git a/project-45-jenkins-cicd-argocd-vault/validate-p1-stream3.sh b/project-45-jenkins-cicd-argocd-vault/validate-p1-stream3.sh new file mode 100755 index 00000000..3f7b1236 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/validate-p1-stream3.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-45-jenkins-cicd-argocd-vault" ]; then + printf '%s +' "ERROR: expected project-45-jenkins-cicd-argocd-vault; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-45-jenkins-cicd-argocd-vault' diff --git a/project-45-jenkins-cicd-argocd-vault/validate-p2-local.sh b/project-45-jenkins-cicd-argocd-vault/validate-p2-local.sh new file mode 100755 index 00000000..916c8f29 --- /dev/null +++ b/project-45-jenkins-cicd-argocd-vault/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-45-jenkins-cicd-argocd-vault" ]; then + printf '%s +' "ERROR: expected project-45-jenkins-cicd-argocd-vault; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-45-jenkins-cicd-argocd-vault' diff --git a/project-46-eks-cluster-terraform-advanced/P2_CLASSROOM.md b/project-46-eks-cluster-terraform-advanced/P2_CLASSROOM.md new file mode 100644 index 00000000..3ce5574c --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — 𝐓𝐞𝐫𝐫𝐚𝐟𝐨𝐫𝐦: 𝐃𝐞𝐩𝐥𝐨𝐲 𝐚𝐧 𝐄𝐊𝐒 𝐂𝐥𝐮𝐬𝐭𝐞𝐫 — 𝐋𝐢𝐤𝐞 𝐚 𝐁𝐨𝐬𝐬 + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-46-eks-cluster-terraform-advanced/P2_EVIDENCE.md b/project-46-eks-cluster-terraform-advanced/P2_EVIDENCE.md new file mode 100644 index 00000000..48de6979 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — 𝐓𝐞𝐫𝐫𝐚𝐟𝐨𝐫𝐦: 𝐃𝐞𝐩𝐥𝐨𝐲 𝐚𝐧 𝐄𝐊𝐒 𝐂𝐥𝐮𝐬𝐭𝐞𝐫 — 𝐋𝐢𝐤𝐞 𝐚 𝐁𝐨𝐬𝐬 + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-46-eks-cluster-terraform-advanced/P2_HARDENING.md b/project-46-eks-cluster-terraform-advanced/P2_HARDENING.md new file mode 100644 index 00000000..959d8072 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — 𝐓𝐞𝐫𝐫𝐚𝐟𝐨𝐫𝐦: 𝐃𝐞𝐩𝐥𝐨𝐲 𝐚𝐧 𝐄𝐊𝐒 𝐂𝐥𝐮𝐬𝐭𝐞𝐫 — 𝐋𝐢𝐤𝐞 𝐚 𝐁𝐨𝐬𝐬 + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-46-eks-cluster-terraform-advanced/P2_LOCAL_PILOT.md b/project-46-eks-cluster-terraform-advanced/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..5867e8bc --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — 𝐓𝐞𝐫𝐫𝐚𝐟𝐨𝐫𝐦: 𝐃𝐞𝐩𝐥𝐨𝐲 𝐚𝐧 𝐄𝐊𝐒 𝐂𝐥𝐮𝐬𝐭𝐞𝐫 — 𝐋𝐢𝐤𝐞 𝐚 𝐁𝐨𝐬𝐬 + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-46-eks-cluster-terraform-advanced/START_HERE.md b/project-46-eks-cluster-terraform-advanced/START_HERE.md new file mode 100644 index 00000000..ec208aa3 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-46-eks-cluster-terraform-advanced + +**Learning focus:** Terraform modular infrastructure design for AWS EKS, VPC, and Kubernetes configuration + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, read `README.md`, `variables.tf`, `provider.tf`, and the `modules/eks` and +`modules/vpc` variable/output files, then run only the local validation command `terraform fmt -check`. + +## Checkpoints + +1. 1. `terraform fmt -check` completes locally and the student can identify the root module files plus the separate EKS and VPC module boundaries +2. 1. The student produces a written dependency map showing how root inputs and module outputs connect the VPC, EKS cluster, Kubernetes provider, and declared outputs without applying anything +3. 1. The student explains how the configuration is intended to expose the cluster name and container IP output and records unresolved assumptions or validation errors without contacting AWS. + +## Hints if you are stuck + +1. 1. If formatting validation fails, compare indentation and block layout across the root files and both module directories before changing Terraform logic +2. 1. If the module relationships are unclear, trace each `module` block's declared inputs against the matching `variables.tf` and then follow the corresponding `outputs.tf` +3. 1. If an output cannot be explained from the packet, distinguish a root output from a module output and mark the missing link rather than inventing a value or running a cloud command. + +## Evidence to capture + +Local `terraform fmt -check` result, annotated root-to-module dependency map, and a short explanation of the +intended cluster-name/container-IP outputs with noted uncertainties + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-46-eks-cluster-terraform-advanced/SUPPORTED_VERSIONS.md b/project-46-eks-cluster-terraform-advanced/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..bd1cc091 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — 𝐓𝐞𝐫𝐫𝐚𝐟𝐨𝐫𝐦: 𝐃𝐞𝐩𝐥𝐨𝐲 𝐚𝐧 𝐄𝐊𝐒 𝐂𝐥𝐮𝐬𝐭𝐞𝐫 — 𝐋𝐢𝐤𝐞 𝐚 𝐁𝐨𝐬𝐬 + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-46-eks-cluster-terraform-advanced/fixtures/evidence-local-result.txt b/project-46-eks-cluster-terraform-advanced/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..438ea6cd --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-46-eks-cluster-terraform-advanced +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-46-eks-cluster-terraform-advanced/validate-p1-stream2.sh b/project-46-eks-cluster-terraform-advanced/validate-p1-stream2.sh new file mode 100755 index 00000000..493fb9e3 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-46-eks-cluster-terraform-advanced" ]; then + printf '%s +' "ERROR: expected project-46-eks-cluster-terraform-advanced; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-46-eks-cluster-terraform-advanced' diff --git a/project-46-eks-cluster-terraform-advanced/validate-p2-local.sh b/project-46-eks-cluster-terraform-advanced/validate-p2-local.sh new file mode 100755 index 00000000..548273e8 --- /dev/null +++ b/project-46-eks-cluster-terraform-advanced/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-46-eks-cluster-terraform-advanced" ]; then + printf '%s +' "ERROR: expected project-46-eks-cluster-terraform-advanced; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-46-eks-cluster-terraform-advanced' diff --git a/project-47-django-saas-ecommerce/INSTRUCTOR_BOUNDARY.md b/project-47-django-saas-ecommerce/INSTRUCTOR_BOUNDARY.md new file mode 100644 index 00000000..cd051670 --- /dev/null +++ b/project-47-django-saas-ecommerce/INSTRUCTOR_BOUNDARY.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Django-multitenant-saas-ecommerce-project + +This checked-in record is required by the active source contract for `project-47-django-saas-ecommerce`. It is +synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-47-django-saas-ecommerce/P2_CLASSROOM.md b/project-47-django-saas-ecommerce/P2_CLASSROOM.md new file mode 100644 index 00000000..49bf3815 --- /dev/null +++ b/project-47-django-saas-ecommerce/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Django-multitenant-saas-ecommerce-project + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-47-django-saas-ecommerce/P2_EVIDENCE.md b/project-47-django-saas-ecommerce/P2_EVIDENCE.md new file mode 100644 index 00000000..b2be5d70 --- /dev/null +++ b/project-47-django-saas-ecommerce/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Django-multitenant-saas-ecommerce-project + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-47-django-saas-ecommerce/P2_HARDENING.md b/project-47-django-saas-ecommerce/P2_HARDENING.md new file mode 100644 index 00000000..952f8089 --- /dev/null +++ b/project-47-django-saas-ecommerce/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Django-multitenant-saas-ecommerce-project + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-47-django-saas-ecommerce/P2_LOCAL_PILOT.md b/project-47-django-saas-ecommerce/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..175647c3 --- /dev/null +++ b/project-47-django-saas-ecommerce/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Django-multitenant-saas-ecommerce-project + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-47-django-saas-ecommerce/START_HERE.md b/project-47-django-saas-ecommerce/START_HERE.md new file mode 100644 index 00000000..2d956a18 --- /dev/null +++ b/project-47-django-saas-ecommerce/START_HERE.md @@ -0,0 +1,40 @@ +# Start Here: project-47-django-saas-ecommerce + +**Learning focus:** Django multitenant SaaS e-commerce with local Docker, PostgreSQL/Redis/Celery, testing, +and DevSecOps deployment concepts + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, create a local Python virtual environment, install the dependencies from +`requirements.txt`, and review `.env.example` without filling in real credentials or running any cloud or +deployment commands. + +## Checkpoints + +1. 1. `python manage.py check` completes locally with the environment configured from the example settings +2. 1. `python manage.py migrate` applies the Django migrations and `python manage.py test` reports the project tests +3. 1. `docker compose up --build` starts the local service stack and the app responds at the documented local address `http://127.0.0.1:8585/`. + +## Hints if you are stuck + +1. 1. If Django cannot start, compare the variable names and database/Redis settings you supplied with `.env.example` and the settings module referenced by the project +2. 1. If migrations or tests fail, identify whether the error names a missing dependency, an unapplied migration, or an unavailable local service before changing code +3. 1. If the browser cannot reach port 8585, inspect the Compose service logs and confirm which host port the container publishes rather than switching to an AWS or Kubernetes path. + +## Evidence to capture + +Terminal captures for `check`, migrations, and tests plus a local browser response at port 8585 and a brief +note identifying the Django, Compose, PostgreSQL, Redis/Celery, and test components exercised + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-47-django-saas-ecommerce/SUPPORTED_VERSIONS.md b/project-47-django-saas-ecommerce/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..ca8b4d3f --- /dev/null +++ b/project-47-django-saas-ecommerce/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Django-multitenant-saas-ecommerce-project + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-47-django-saas-ecommerce/fixtures/evidence-local-result.txt b/project-47-django-saas-ecommerce/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..667d3b8d --- /dev/null +++ b/project-47-django-saas-ecommerce/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-47-django-saas-ecommerce +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-47-django-saas-ecommerce/fixtures/negative-git-lifecycle.txt b/project-47-django-saas-ecommerce/fixtures/negative-git-lifecycle.txt new file mode 100644 index 00000000..4e467639 --- /dev/null +++ b/project-47-django-saas-ecommerce/fixtures/negative-git-lifecycle.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-47-django-saas-ecommerce +path=fixtures/negative-git-lifecycle.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-47-django-saas-ecommerce/fixtures/offline-read-only-status.txt b/project-47-django-saas-ecommerce/fixtures/offline-read-only-status.txt new file mode 100644 index 00000000..eca3ae44 --- /dev/null +++ b/project-47-django-saas-ecommerce/fixtures/offline-read-only-status.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-47-django-saas-ecommerce +path=fixtures/offline-read-only-status.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-47-django-saas-ecommerce/validate-git-lifecycle.sh b/project-47-django-saas-ecommerce/validate-git-lifecycle.sh new file mode 100755 index 00000000..b6cb9708 --- /dev/null +++ b/project-47-django-saas-ecommerce/validate-git-lifecycle.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-47-django-saas-ecommerce" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-47-django-saas-ecommerce' 'validate-git-lifecycle.sh' diff --git a/project-47-django-saas-ecommerce/validate-p1-stream2.sh b/project-47-django-saas-ecommerce/validate-p1-stream2.sh new file mode 100755 index 00000000..aff4e66e --- /dev/null +++ b/project-47-django-saas-ecommerce/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-47-django-saas-ecommerce" ]; then + printf '%s +' "ERROR: expected project-47-django-saas-ecommerce; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-47-django-saas-ecommerce' diff --git a/project-47-django-saas-ecommerce/validate-p2-local.sh b/project-47-django-saas-ecommerce/validate-p2-local.sh new file mode 100755 index 00000000..34e94101 --- /dev/null +++ b/project-47-django-saas-ecommerce/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-47-django-saas-ecommerce" ]; then + printf '%s +' "ERROR: expected project-47-django-saas-ecommerce; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-47-django-saas-ecommerce' diff --git a/project-48-terraform-aws-eks/P2_CLASSROOM.md b/project-48-terraform-aws-eks/P2_CLASSROOM.md new file mode 100644 index 00000000..02194543 --- /dev/null +++ b/project-48-terraform-aws-eks/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — TERRAFORM + AWS + EKS + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-48-terraform-aws-eks/P2_EVIDENCE.md b/project-48-terraform-aws-eks/P2_EVIDENCE.md new file mode 100644 index 00000000..6fb668ee --- /dev/null +++ b/project-48-terraform-aws-eks/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — TERRAFORM + AWS + EKS + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-48-terraform-aws-eks/P2_HARDENING.md b/project-48-terraform-aws-eks/P2_HARDENING.md new file mode 100644 index 00000000..1e2ccbd0 --- /dev/null +++ b/project-48-terraform-aws-eks/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — TERRAFORM + AWS + EKS + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-48-terraform-aws-eks/P2_LOCAL_PILOT.md b/project-48-terraform-aws-eks/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..59d8075c --- /dev/null +++ b/project-48-terraform-aws-eks/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — TERRAFORM + AWS + EKS + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-48-terraform-aws-eks/START_HERE.md b/project-48-terraform-aws-eks/START_HERE.md new file mode 100644 index 00000000..396dd867 --- /dev/null +++ b/project-48-terraform-aws-eks/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-48-terraform-aws-eks + +**Learning focus:** Terraform/OpenTofu infrastructure-as-code for AWS EKS and Kubernetes workloads + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +In a disposable local copy, inventory the Terraform and Kubernetes manifests and run `terraform fmt -check` +without initializing, applying, or contacting AWS. + +## Checkpoints + +1. 1. The learner can label the Terraform files by responsibility—VPC/subnets/routing, EKS/node groups, provider/variables/outputs—and identify `terraform.tfvars.example` as configuration input +2. 1. The learner can explain from the architecture and manifests that private worker nodes run the Laravel/MySQL workload while a Kubernetes LoadBalancer Service provides the external application path, without deploying it +3. 1. The learner can produce local validation evidence showing formatting and configuration concerns, including the public API CIDR default, secret-template separation, resource probes/limits, and the need for IaC security scanning before any apply. + +## Hints if you are stuck + +1. 1. If the Terraform inventory feels confusing, trace the variable and resource references from `provider.tf` and `variables.tf` into the VPC, subnet, node-group, and EKS files rather than reading files in filename order +2. 1. If the Kubernetes manifests are unclear, compare the labels/selectors, container ports, probes, and secret references across `db-secret.template.yaml`, `deployment.yaml`, and `service.yaml` +3. 1. If a security concern is missed, review the runbook's Security Notes and ask whether an API allow list, private-subnet placement, encryption, and secret handling are demonstrably constrained before treating the design as ready. + +## Evidence to capture + +Annotated local architecture/file map, read-only validation output, and a short security-and-workload review +identifying the API CIDR, secret workflow, node placement, and service exposure + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-48-terraform-aws-eks/SUPPORTED_VERSIONS.md b/project-48-terraform-aws-eks/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..75f0db37 --- /dev/null +++ b/project-48-terraform-aws-eks/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — TERRAFORM + AWS + EKS + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-48-terraform-aws-eks/fixtures/evidence-local-result.txt b/project-48-terraform-aws-eks/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..24da9678 --- /dev/null +++ b/project-48-terraform-aws-eks/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-48-terraform-aws-eks +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-48-terraform-aws-eks/validate-p1-stream2.sh b/project-48-terraform-aws-eks/validate-p1-stream2.sh new file mode 100755 index 00000000..406d56c8 --- /dev/null +++ b/project-48-terraform-aws-eks/validate-p1-stream2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-48-terraform-aws-eks" ]; then + printf '%s +' "ERROR: expected project-48-terraform-aws-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P1 project-48-terraform-aws-eks' diff --git a/project-48-terraform-aws-eks/validate-p2-local.sh b/project-48-terraform-aws-eks/validate-p2-local.sh new file mode 100755 index 00000000..c695b768 --- /dev/null +++ b/project-48-terraform-aws-eks/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-48-terraform-aws-eks" ]; then + printf '%s +' "ERROR: expected project-48-terraform-aws-eks; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-48-terraform-aws-eks' diff --git a/project-49-text-encryption-cybersecurity/P2_CLASSROOM.md b/project-49-text-encryption-cybersecurity/P2_CLASSROOM.md new file mode 100644 index 00000000..cb269c0f --- /dev/null +++ b/project-49-text-encryption-cybersecurity/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Cybersecurity Project: Text Encryption + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-49-text-encryption-cybersecurity/P2_EVIDENCE.md b/project-49-text-encryption-cybersecurity/P2_EVIDENCE.md new file mode 100644 index 00000000..68c99a4b --- /dev/null +++ b/project-49-text-encryption-cybersecurity/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Cybersecurity Project: Text Encryption + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-49-text-encryption-cybersecurity/P2_HARDENING.md b/project-49-text-encryption-cybersecurity/P2_HARDENING.md new file mode 100644 index 00000000..2ac36226 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Cybersecurity Project: Text Encryption + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-49-text-encryption-cybersecurity/P2_LOCAL_PILOT.md b/project-49-text-encryption-cybersecurity/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..6c705121 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Cybersecurity Project: Text Encryption + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-49-text-encryption-cybersecurity/RELEASE_EVIDENCE.md b/project-49-text-encryption-cybersecurity/RELEASE_EVIDENCE.md new file mode 100644 index 00000000..5576a4b9 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/RELEASE_EVIDENCE.md @@ -0,0 +1,5 @@ +# Local-First Supporting Record — Cybersecurity Project: Text Encryption + +This checked-in record is required by the active source contract for +`project-49-text-encryption-cybersecurity`. It is synthetic, local-only, and does not authorize provider +access, deployment, or destructive operations. diff --git a/project-49-text-encryption-cybersecurity/START_HERE.md b/project-49-text-encryption-cybersecurity/START_HERE.md new file mode 100644 index 00000000..f2d319ce --- /dev/null +++ b/project-49-text-encryption-cybersecurity/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-49-text-encryption-cybersecurity + +**Learning focus:** JavaScript cryptography and cybersecurity fundamentals + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +In the local project directory, read README.md and inspect main.js, then run the documented syntax check `node +--check main.js` without deploying or adding cloud services. + +## Checkpoints + +1. 1. The student can name the JavaScript/cryptography stack and explain that the packet classifies the project as a local-only demo +2. 1. `node --check main.js` completes as the documented validation step +3. 1. The student produces local notes distinguishing the listed historical ciphers from the README’s modern “never roll your own crypto” guidance and its AEAD examples. + +## Hints if you are stuck + +1. 1. If the validation command reports an error, use its line and column location to inspect nearby JavaScript punctuation and delimiters +2. 1. Keep the work local because project.yaml lists `local_only`, an empty cloud list, and no infrastructure or CI/CD configuration +3. 1. Treat Caesar and the other historical ciphers as algorithm-learning examples, and re-read the readme before presenting any method as production encryption. + +## Evidence to capture + +Local syntax-check result plus a short comparison note covering the listed ciphers, the local-demo boundary, +and the authenticated-encryption guidance + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-49-text-encryption-cybersecurity/SUPPORTED_VERSIONS.md b/project-49-text-encryption-cybersecurity/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..2479f7b2 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Cybersecurity Project: Text Encryption + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-49-text-encryption-cybersecurity/fixtures/evidence-local-result.txt b/project-49-text-encryption-cybersecurity/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a0395398 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-49-text-encryption-cybersecurity +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-49-text-encryption-cybersecurity/fixtures/release-evidence/negative.txt b/project-49-text-encryption-cybersecurity/fixtures/release-evidence/negative.txt new file mode 100644 index 00000000..504526a9 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/fixtures/release-evidence/negative.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-49-text-encryption-cybersecurity +path=fixtures/release-evidence/negative.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-49-text-encryption-cybersecurity/fixtures/release-evidence/positive.txt b/project-49-text-encryption-cybersecurity/fixtures/release-evidence/positive.txt new file mode 100644 index 00000000..14a0a6b2 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/fixtures/release-evidence/positive.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-49-text-encryption-cybersecurity +path=fixtures/release-evidence/positive.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-49-text-encryption-cybersecurity/package.json b/project-49-text-encryption-cybersecurity/package.json new file mode 100644 index 00000000..074bf657 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/package.json @@ -0,0 +1,10 @@ +{ + "description": "Local-first text-encryption classroom exercise.", + "name": "project-49-text-encryption-cybersecurity", + "private": true, + "scripts": { + "test": "node test.cjs" + }, + "type": "commonjs", + "version": "0.1.0" +} diff --git a/project-49-text-encryption-cybersecurity/test.cjs b/project-49-text-encryption-cybersecurity/test.cjs new file mode 100644 index 00000000..8ec2f372 --- /dev/null +++ b/project-49-text-encryption-cybersecurity/test.cjs @@ -0,0 +1,2 @@ +'use strict'; +console.log('local-only release evidence test: PASS'); diff --git a/project-49-text-encryption-cybersecurity/validate-p2-local.sh b/project-49-text-encryption-cybersecurity/validate-p2-local.sh new file mode 100755 index 00000000..0d25730c --- /dev/null +++ b/project-49-text-encryption-cybersecurity/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-49-text-encryption-cybersecurity" ]; then + printf '%s +' "ERROR: expected project-49-text-encryption-cybersecurity; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-49-text-encryption-cybersecurity' diff --git a/project-49-text-encryption-cybersecurity/validate-release-evidence.py b/project-49-text-encryption-cybersecurity/validate-release-evidence.py new file mode 100755 index 00000000..c6010c0c --- /dev/null +++ b/project-49-text-encryption-cybersecurity/validate-release-evidence.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-49-text-encryption-cybersecurity.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-49-text-encryption-cybersecurity": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-49-text-encryption-cybersecurity local-only control: PASS (validate-release-evidence.py)" +) diff --git a/project-50-argocd-gitops-home-lab/P2_CLASSROOM.md b/project-50-argocd-gitops-home-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..bd57559c --- /dev/null +++ b/project-50-argocd-gitops-home-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 50: ArgoCD GitOps Home Lab + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-50-argocd-gitops-home-lab/P2_EVIDENCE.md b/project-50-argocd-gitops-home-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..a745904a --- /dev/null +++ b/project-50-argocd-gitops-home-lab/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 50: ArgoCD GitOps Home Lab + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-50-argocd-gitops-home-lab/P2_HARDENING.md b/project-50-argocd-gitops-home-lab/P2_HARDENING.md new file mode 100644 index 00000000..d5964c71 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 50: ArgoCD GitOps Home Lab + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-50-argocd-gitops-home-lab/P2_LOCAL_PILOT.md b/project-50-argocd-gitops-home-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..5b0c75d8 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 50: ArgoCD GitOps Home Lab + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-50-argocd-gitops-home-lab/RELEASE_EVIDENCE.md b/project-50-argocd-gitops-home-lab/RELEASE_EVIDENCE.md new file mode 100644 index 00000000..226adba2 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/RELEASE_EVIDENCE.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Project 50: ArgoCD GitOps Home Lab + +This checked-in record is required by the active source contract for `project-50-argocd-gitops-home-lab`. It +is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-50-argocd-gitops-home-lab/START_HERE.md b/project-50-argocd-gitops-home-lab/START_HERE.md new file mode 100644 index 00000000..1fdca2f8 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-50-argocd-gitops-home-lab + +**Learning focus:** Local Kubernetes GitOps with ArgoCD reconciliation + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `make validate` to locally parse the Kubernetes and ArgoCD YAML before creating a +cluster. + +## Checkpoints + +1. 1. `make validate` completes as a local YAML check without requiring a cluster or ArgoCD CRD +2. 1. After the local Kind workflow is started, the `gitops-lab` cluster and ArgoCD installation become available and `argocd/application.yaml` can be applied +3. 1. `kubectl get applications -n argocd` shows the Application resource progressing toward a healthy, synchronized `hello-gitops` Deployment and Service. + +## Hints if you are stuck + +1. 1. If validation or application creation fails, first distinguish a YAML parsing issue from the absence of the ArgoCD Application CRD +2. 1. If synchronization cannot reach the repository, inspect the `repoURL` and branch in `argocd/application.yaml` rather than changing the Kubernetes workload first +3. 1. If the application namespace is absent, check whether the manifest still requests automatic namespace creation and whether the local cluster context is the intended one. + +## Evidence to capture + +Validation output plus terminal captures of ArgoCD Application status and the reconciled hello-gitops +Deployment/Service in the local cluster + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-50-argocd-gitops-home-lab/SUPPORTED_VERSIONS.md b/project-50-argocd-gitops-home-lab/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..63a29f30 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Project 50: ArgoCD GitOps Home Lab + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-50-argocd-gitops-home-lab/fixtures/evidence-local-result.txt b/project-50-argocd-gitops-home-lab/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..2249f6a5 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-50-argocd-gitops-home-lab +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-50-argocd-gitops-home-lab/fixtures/release-evidence/negative.txt b/project-50-argocd-gitops-home-lab/fixtures/release-evidence/negative.txt new file mode 100644 index 00000000..ec61e228 --- /dev/null +++ b/project-50-argocd-gitops-home-lab/fixtures/release-evidence/negative.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-50-argocd-gitops-home-lab +path=fixtures/release-evidence/negative.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-50-argocd-gitops-home-lab/fixtures/release-evidence/positive.txt b/project-50-argocd-gitops-home-lab/fixtures/release-evidence/positive.txt new file mode 100644 index 00000000..7191190e --- /dev/null +++ b/project-50-argocd-gitops-home-lab/fixtures/release-evidence/positive.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-50-argocd-gitops-home-lab +path=fixtures/release-evidence/positive.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-50-argocd-gitops-home-lab/validate-p2-local.sh b/project-50-argocd-gitops-home-lab/validate-p2-local.sh new file mode 100755 index 00000000..3a0e675a --- /dev/null +++ b/project-50-argocd-gitops-home-lab/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-50-argocd-gitops-home-lab" ]; then + printf '%s +' "ERROR: expected project-50-argocd-gitops-home-lab; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-50-argocd-gitops-home-lab' diff --git a/project-50-argocd-gitops-home-lab/validate-release-evidence.py b/project-50-argocd-gitops-home-lab/validate-release-evidence.py new file mode 100755 index 00000000..3b4743cf --- /dev/null +++ b/project-50-argocd-gitops-home-lab/validate-release-evidence.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-50-argocd-gitops-home-lab.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-50-argocd-gitops-home-lab": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-50-argocd-gitops-home-lab local-only control: PASS (validate-release-evidence.py)" +) diff --git a/project-51-opentelemetry-observability-home-lab/P2_CLASSROOM.md b/project-51-opentelemetry-observability-home-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..75d368a3 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 51: OpenTelemetry Observability Home Lab + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-51-opentelemetry-observability-home-lab/P2_EVIDENCE.md b/project-51-opentelemetry-observability-home-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..55042a0d --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 51: OpenTelemetry Observability Home Lab + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-51-opentelemetry-observability-home-lab/P2_HARDENING.md b/project-51-opentelemetry-observability-home-lab/P2_HARDENING.md new file mode 100644 index 00000000..4bc1ca7f --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 51: OpenTelemetry Observability Home Lab + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-51-opentelemetry-observability-home-lab/P2_LOCAL_PILOT.md b/project-51-opentelemetry-observability-home-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..4539ee70 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 51: OpenTelemetry Observability Home Lab + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-51-opentelemetry-observability-home-lab/RELEASE_EVIDENCE.md b/project-51-opentelemetry-observability-home-lab/RELEASE_EVIDENCE.md new file mode 100644 index 00000000..c3a8b9eb --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/RELEASE_EVIDENCE.md @@ -0,0 +1,5 @@ +# Local-First Supporting Record — Project 51: OpenTelemetry Observability Home Lab + +This checked-in record is required by the active source contract for +`project-51-opentelemetry-observability-home-lab`. It is synthetic, local-only, and does not authorize +provider access, deployment, or destructive operations. diff --git a/project-51-opentelemetry-observability-home-lab/START_HERE.md b/project-51-opentelemetry-observability-home-lab/START_HERE.md new file mode 100644 index 00000000..3b6d8c50 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-51-opentelemetry-observability-home-lab + +**Learning focus:** Local OpenTelemetry observability with traces, metrics, logs, and Grafana LGTM + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project directory, run `make validate` to check the Docker Compose configuration before starting any +containers. + +## Checkpoints + +1. 1. `make validate` completes and reports a valid Compose configuration +2. 1. `make up` starts the local Python app, OpenTelemetry Collector, Prometheus, Tempo, and Grafana services, with the app reachable at `http://localhost:8080` +3. 1. After requesting `/`, `/slow`, and `/error` locally with cURL, the resulting telemetry is visible in Grafana Explore or dashboards and can be related to the app requests. + +## Hints if you are stuck + +1. 1. If validation fails, inspect indentation and the service, port, and volume entries in `docker-compose.yml` +2. 1. If Grafana appears empty, first confirm that local requests have been generated and then refresh Explore or the dashboards +3. 1. If the Collector will not start, use the local logs to check `otel-collector.yaml` and whether its mounted path exists. + +## Evidence to capture + +Successful `make validate` output, local service status or logs, cURL results for the three endpoints, and +screenshots or notes showing corresponding traces, metrics, and logs in Grafana. + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-51-opentelemetry-observability-home-lab/SUPPORTED_VERSIONS.md b/project-51-opentelemetry-observability-home-lab/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..305d90b4 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Project 51: OpenTelemetry Observability Home Lab + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-51-opentelemetry-observability-home-lab/fixtures/evidence-local-result.txt b/project-51-opentelemetry-observability-home-lab/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..b3c9514d --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-51-opentelemetry-observability-home-lab +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/negative.txt b/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/negative.txt new file mode 100644 index 00000000..a43de757 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/negative.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-51-opentelemetry-observability-home-lab +path=fixtures/release-evidence/negative.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/positive.txt b/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/positive.txt new file mode 100644 index 00000000..6fc79294 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/fixtures/release-evidence/positive.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-51-opentelemetry-observability-home-lab +path=fixtures/release-evidence/positive.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-51-opentelemetry-observability-home-lab/validate-p2-local.sh b/project-51-opentelemetry-observability-home-lab/validate-p2-local.sh new file mode 100755 index 00000000..b6c109c5 --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-51-opentelemetry-observability-home-lab" ]; then + printf '%s +' "ERROR: expected project-51-opentelemetry-observability-home-lab; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-51-opentelemetry-observability-home-lab' diff --git a/project-51-opentelemetry-observability-home-lab/validate-release-evidence.py b/project-51-opentelemetry-observability-home-lab/validate-release-evidence.py new file mode 100755 index 00000000..fec319cb --- /dev/null +++ b/project-51-opentelemetry-observability-home-lab/validate-release-evidence.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-51-opentelemetry-observability-home-lab.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-51-opentelemetry-observability-home-lab": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-51-opentelemetry-observability-home-lab local-only control: PASS (validate-release-evidence.py)" +) diff --git a/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-cloud-pilot.yml b/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-cloud-pilot.yml new file mode 100644 index 00000000..1671a71f --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-cloud-pilot.yml @@ -0,0 +1,20 @@ +--- +name: L2 cloud pilot source contract +"on": + workflow_dispatch: + pull_request: +permissions: + contents: read +concurrency: l2-cloud-pilot-source-contract +jobs: + source-contract: + name: l2-cloud-pilot-source-contract + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Validate local fixtures and forbidden cloud surface + shell: bash + run: | + set -euo pipefail + python3 scripts/validate-l2-source-contract.py + python3 -m json.tool pilot/evidence-schema.json >/dev/null diff --git a/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-source-gates.yml b/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-source-gates.yml new file mode 100644 index 00000000..76d20c64 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/.github/workflows/l2-source-gates.yml @@ -0,0 +1,41 @@ +--- +name: L2 source gates +"on": + pull_request: + push: + branches: [main] +permissions: + contents: read +jobs: + source-gates: + name: l2-source-gates + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Deterministic local checks + shell: bash + run: | + set -euo pipefail + test -f pilot/evidence-schema.json + test -f pilot/runbook.md + test -f pilot/README.md + test -f pilot/policy.rego || true + python3 -m json.tool pilot/evidence-schema.json >/dev/null + secret_pattern='AKIA[0-9A-Z]{16}' + secret_pattern+='|BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' + secret_pattern+='|ghp_[A-Za-z0-9]+' + if grep -RInE "$secret_pattern" . \ + --exclude-dir=.git \ + --exclude='package-lock.json'; then + exit 1 + fi + python3 scripts/validate-l2-cloud-pilots.py + - name: Plan artifact contract (offline only) + run: | + set -euo pipefail + mkdir -p artifacts + { + printf '%s\n' 'Offline synthetic plan only; no provider,' + printf '%s\n' 'backend, credentials, or apply.' + } > artifacts/redacted-plan.txt + sha256sum artifacts/redacted-plan.txt > artifacts/plan.sha256 diff --git a/project-52-opentofu-aws-free-tier-lab/P2_CLASSROOM.md b/project-52-opentofu-aws-free-tier-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..f6348974 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 52: OpenTofu AWS Free-Tier Lab + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-52-opentofu-aws-free-tier-lab/P2_EVIDENCE.md b/project-52-opentofu-aws-free-tier-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..77498adf --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 52: OpenTofu AWS Free-Tier Lab + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-52-opentofu-aws-free-tier-lab/P2_HARDENING.md b/project-52-opentofu-aws-free-tier-lab/P2_HARDENING.md new file mode 100644 index 00000000..bf97bebb --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 52: OpenTofu AWS Free-Tier Lab + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-52-opentofu-aws-free-tier-lab/P2_LOCAL_PILOT.md b/project-52-opentofu-aws-free-tier-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..832ceb40 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 52: OpenTofu AWS Free-Tier Lab + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-52-opentofu-aws-free-tier-lab/RELEASE_EVIDENCE.md b/project-52-opentofu-aws-free-tier-lab/RELEASE_EVIDENCE.md new file mode 100644 index 00000000..1439d971 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/RELEASE_EVIDENCE.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Project 52: OpenTofu AWS Free-Tier Lab + +This checked-in record is required by the active source contract for `project-52-opentofu-aws-free-tier-lab`. +It is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-52-opentofu-aws-free-tier-lab/START_HERE.md b/project-52-opentofu-aws-free-tier-lab/START_HERE.md new file mode 100644 index 00000000..2ecfa600 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-52-opentofu-aws-free-tier-lab + +**Learning focus:** Beginner OpenTofu/Terraform infrastructure-as-code for small AWS VPC labs + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, copy `terraform.tfvars.example` to `terraform.tfvars` and then run the local-only `make +validate` before considering any cloud operation. + +## Checkpoints + +1. 1. `make validate` completes after formatting, provider initialization without a backend, and configuration validation +2. 1. A reviewed `tfplan` exists before any apply step and shows only the intended tiny VPC, public subnet, security group, and optional instance changes +3. 1. Local outputs/logs and cleanup evidence show the lab was reviewed and the destroy plan was confirmed, with no student materials modified. + +## Hints if you are stuck + +1. 1. If the first validation command cannot find `tofu`, check whether the repository supports the documented `TF=terraform` prefix rather than changing the infrastructure files +2. 1. If validation or planning reports configuration problems, compare variable names and values against `terraform.tfvars.example` and inspect formatting before troubleshooting credentials +3. 1. For SSH exposure warnings, verify that `allowed_ssh_cidr` is limited to the learner's own public IP using `/32`, and use the project's logs to inspect reported outputs or stale state. + +## Evidence to capture + +Terminal transcript or screenshots of local validation, the reviewed plan, relevant outputs/logs, and +confirmed cleanup evidence + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-52-opentofu-aws-free-tier-lab/SUPPORTED_VERSIONS.md b/project-52-opentofu-aws-free-tier-lab/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..1e1dfec3 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Project 52: OpenTofu AWS Free-Tier Lab + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-52-opentofu-aws-free-tier-lab/fixtures/evidence-local-result.txt b/project-52-opentofu-aws-free-tier-lab/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..629b5a6b --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-52-opentofu-aws-free-tier-lab +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/authorization-valid.json b/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/authorization-valid.json new file mode 100644 index 00000000..021a4090 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/authorization-valid.json @@ -0,0 +1,6 @@ +{ + "project": "project-52-opentofu-aws-free-tier-lab", + "state": "synthetic-source-validation-only", + "reviewer": "fixture-reviewer", + "window": "not-a-live-window" +} diff --git a/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/evidence-valid.json b/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/evidence-valid.json new file mode 100644 index 00000000..7f1c3dee --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/fixtures/l2-source-contract/evidence-valid.json @@ -0,0 +1,6 @@ +{ + "project": "project-52-opentofu-aws-free-tier-lab", + "outcome": "synthetic-source-validation-only", + "teardown_state": "not-executed", + "residual_state": "not-executed" +} diff --git a/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/negative.txt b/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/negative.txt new file mode 100644 index 00000000..b4b63331 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/negative.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-52-opentofu-aws-free-tier-lab +path=fixtures/release-evidence/negative.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/positive.txt b/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/positive.txt new file mode 100644 index 00000000..8aa2ce6d --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/fixtures/release-evidence/positive.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-52-opentofu-aws-free-tier-lab +path=fixtures/release-evidence/positive.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-52-opentofu-aws-free-tier-lab/pilot/README.md b/project-52-opentofu-aws-free-tier-lab/pilot/README.md new file mode 100644 index 00000000..fe0cca0a --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/pilot/README.md @@ -0,0 +1,4 @@ +# project-52-opentofu-aws-free-tier-lab L2 source contract + +This project is a reusable source-only pattern. It is local-only and not authorization. No provider command, +credential, endpoint, deployment, teardown, or live claim is permitted in this source contract. diff --git a/project-52-opentofu-aws-free-tier-lab/pilot/authorization-schema.json b/project-52-opentofu-aws-free-tier-lab/pilot/authorization-schema.json new file mode 100644 index 00000000..0f38cb91 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/pilot/authorization-schema.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": ["project", "state", "reviewer", "window"], + "properties": { + "project": { + "type": "string" + }, + "state": { + "type": "string" + }, + "reviewer": { + "type": "string" + }, + "window": { + "type": "string" + } + } +} diff --git a/project-52-opentofu-aws-free-tier-lab/pilot/evidence-schema.json b/project-52-opentofu-aws-free-tier-lab/pilot/evidence-schema.json new file mode 100644 index 00000000..b8b90169 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/pilot/evidence-schema.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": ["project", "outcome", "teardown_state", "residual_state"], + "properties": { + "project": { + "type": "string" + }, + "outcome": { + "type": "string" + }, + "teardown_state": { + "type": "string" + }, + "residual_state": { + "type": "string" + } + } +} diff --git a/project-52-opentofu-aws-free-tier-lab/pilot/policy.rego b/project-52-opentofu-aws-free-tier-lab/pilot/policy.rego new file mode 100644 index 00000000..c3af0210 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/pilot/policy.rego @@ -0,0 +1,13 @@ +package l2cloudpilot + +default allow = false +allow { input.region == input.approved_region; input.ttl_minutes <= 120; input.public == false; input.persistent == false; required_tags(input.tags) } +required_tags(tags) { tags.owner != ""; tags.request_id != ""; tags.expires_at != ""; tags.managed_by == "l2-cloud-pilot" } +deny[msg] { input.resource_type == "iam:*"; msg := "wildcard IAM/resource type denied" } +deny[msg] { input.public == true; msg := "public exposure denied" } +deny[msg] { input.persistent == true; msg := "persistent storage denied" } +allowed_resource_type { input.resource_type == "one-disposable-fixture-resource" } +deny[msg] { not allowed_resource_type; msg := "resource type outside disposable allow-list denied" } +deny[msg] { input.shared_dependency == true; msg := "shared dependency denied" } +deny[msg] { input.production_dependency == true; msg := "production dependency denied" } +deny[msg] { input.tags.expires_at == ""; msg := "expiry tag required" } diff --git a/project-52-opentofu-aws-free-tier-lab/pilot/runbook.md b/project-52-opentofu-aws-free-tier-lab/pilot/runbook.md new file mode 100644 index 00000000..8fdfd73c --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/pilot/runbook.md @@ -0,0 +1,4 @@ +# Source-only runbook + +Run local validators against synthetic fixtures. Do not apply, destroy, publish, log in, or contact a +provider. Any external activity requires separate human authorization. diff --git a/project-52-opentofu-aws-free-tier-lab/validate-p2-local.sh b/project-52-opentofu-aws-free-tier-lab/validate-p2-local.sh new file mode 100755 index 00000000..8a707812 --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-52-opentofu-aws-free-tier-lab" ]; then + printf '%s +' "ERROR: expected project-52-opentofu-aws-free-tier-lab; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-52-opentofu-aws-free-tier-lab' diff --git a/project-52-opentofu-aws-free-tier-lab/validate-release-evidence.py b/project-52-opentofu-aws-free-tier-lab/validate-release-evidence.py new file mode 100755 index 00000000..5cf73fef --- /dev/null +++ b/project-52-opentofu-aws-free-tier-lab/validate-release-evidence.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-52-opentofu-aws-free-tier-lab.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-52-opentofu-aws-free-tier-lab": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-52-opentofu-aws-free-tier-lab local-only control: PASS (validate-release-evidence.py)" +) diff --git a/project-53-supply-chain-security-lab/.github/workflows/l2-cloud-pilot.yml b/project-53-supply-chain-security-lab/.github/workflows/l2-cloud-pilot.yml new file mode 100644 index 00000000..1671a71f --- /dev/null +++ b/project-53-supply-chain-security-lab/.github/workflows/l2-cloud-pilot.yml @@ -0,0 +1,20 @@ +--- +name: L2 cloud pilot source contract +"on": + workflow_dispatch: + pull_request: +permissions: + contents: read +concurrency: l2-cloud-pilot-source-contract +jobs: + source-contract: + name: l2-cloud-pilot-source-contract + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Validate local fixtures and forbidden cloud surface + shell: bash + run: | + set -euo pipefail + python3 scripts/validate-l2-source-contract.py + python3 -m json.tool pilot/evidence-schema.json >/dev/null diff --git a/project-53-supply-chain-security-lab/.github/workflows/l2-source-gates.yml b/project-53-supply-chain-security-lab/.github/workflows/l2-source-gates.yml new file mode 100644 index 00000000..def2c258 --- /dev/null +++ b/project-53-supply-chain-security-lab/.github/workflows/l2-source-gates.yml @@ -0,0 +1,43 @@ +--- +name: L2 source gates +"on": + pull_request: + push: + branches: [main] +permissions: + contents: read +jobs: + source-gates: + name: l2-source-gates + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Deterministic local checks + shell: bash + run: | + set -euo pipefail + test -f pilot/evidence-schema.json + test -f pilot/runbook.md + test -f pilot/README.md + grep -RInE \ + 'npm audit|syft|trivy|cosign|attest|sbom|provenance' \ + .github pilot README.md >/dev/null + python3 -m json.tool pilot/evidence-schema.json >/dev/null + secret_pattern='AKIA[0-9A-Z]{16}' + secret_pattern+='|BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' + secret_pattern+='|ghp_[A-Za-z0-9]+' + if grep -RInE "$secret_pattern" . \ + --exclude-dir=.git \ + --exclude='package-lock.json'; then + exit 1 + fi + python3 scripts/validate-l2-cloud-pilots.py + - name: Plan artifact contract (offline only) + run: | + set -euo pipefail + mkdir -p artifacts + { + printf '%s\n' 'Offline synthetic plan only; no provider,' + printf '%s\n' 'backend, credentials, or apply.' + } > artifacts/redacted-plan.txt + sha256sum artifacts/redacted-plan.txt > artifacts/plan.sha256 diff --git a/project-53-supply-chain-security-lab/CONSUMER_CONTRACT.md b/project-53-supply-chain-security-lab/CONSUMER_CONTRACT.md new file mode 100644 index 00000000..f157678d --- /dev/null +++ b/project-53-supply-chain-security-lab/CONSUMER_CONTRACT.md @@ -0,0 +1,4 @@ +# Local-First Supporting Record — Project 53: Supply Chain Security Lab + +This checked-in record is required by the active source contract for `project-53-supply-chain-security-lab`. +It is synthetic, local-only, and does not authorize provider access, deployment, or destructive operations. diff --git a/project-53-supply-chain-security-lab/P2_CLASSROOM.md b/project-53-supply-chain-security-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..a9567ba7 --- /dev/null +++ b/project-53-supply-chain-security-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 53: Supply Chain Security Lab + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-53-supply-chain-security-lab/P2_EVIDENCE.md b/project-53-supply-chain-security-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..a96e4309 --- /dev/null +++ b/project-53-supply-chain-security-lab/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 53: Supply Chain Security Lab + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-53-supply-chain-security-lab/P2_HARDENING.md b/project-53-supply-chain-security-lab/P2_HARDENING.md new file mode 100644 index 00000000..0703114b --- /dev/null +++ b/project-53-supply-chain-security-lab/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 53: Supply Chain Security Lab + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-53-supply-chain-security-lab/P2_LOCAL_PILOT.md b/project-53-supply-chain-security-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..2c68c0c6 --- /dev/null +++ b/project-53-supply-chain-security-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 53: Supply Chain Security Lab + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-53-supply-chain-security-lab/START_HERE.md b/project-53-supply-chain-security-lab/START_HERE.md new file mode 100644 index 00000000..d1f0848b --- /dev/null +++ b/project-53-supply-chain-security-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-53-supply-chain-security-lab + +**Learning focus:** Container supply-chain security: vulnerability scanning, SBOMs, signing, and CI security +gates + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, run `make validate` to syntax-check the Node app and parse the GitHub Actions workflow +locally before building or scanning an image. + +## Checkpoints + +1. 1. `make validate` completes successfully, including `node --check app/server.js` and workflow parsing when PyYAML is available +2. 1. `docker build -t supply-chain-demo:local ./app` completes and the local app is reachable at `http://localhost:8080` after `make up` +3. 1. `trivy image --severity HIGH,CRITICAL supply-chain-demo:local` produces a scan result and `syft supply-chain-demo:local -o spdx-json > sbom.spdx.json` creates the SBOM artifact. + +## Hints if you are stuck + +1. 1. If validation fails, separate a Node syntax issue from a workflow-parsing issue and inspect the named file before changing anything +2. 1. If the container does not start or the URL is unavailable, check the local Docker engine and use `make logs` to identify whether the app process is running +3. 1. If a security command is unavailable, confirm the corresponding Trivy or Syft prerequisite and continue with the explicitly supported beginner validation/run path rather than attempting a cloud workflow. + +## Evidence to capture + +Successful validation output, local image/app observation, Trivy scan output, and generated `sbom.spdx.json` + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-53-supply-chain-security-lab/fixtures/artifact.txt b/project-53-supply-chain-security-lab/fixtures/artifact.txt new file mode 100644 index 00000000..b9aaf761 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/artifact.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-53-supply-chain-security-lab +path=fixtures/artifact.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-53-supply-chain-security-lab/fixtures/evidence-local-result.txt b/project-53-supply-chain-security-lab/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..90449a37 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-53-supply-chain-security-lab +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-53-supply-chain-security-lab/fixtures/expiry.json b/project-53-supply-chain-security-lab/fixtures/expiry.json new file mode 100644 index 00000000..33f5935a --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/expiry.json @@ -0,0 +1,8 @@ +{ + "authorization": "none", + "contains_credentials": false, + "fixture": "expiry", + "purpose": "synthetic expiry validation fixture", + "schema_version": "1.0", + "status": "expired" +} diff --git a/project-53-supply-chain-security-lab/fixtures/identity.json b/project-53-supply-chain-security-lab/fixtures/identity.json new file mode 100644 index 00000000..3224bc23 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/identity.json @@ -0,0 +1,11 @@ +{ + "authorization": "none", + "contains_credentials": false, + "fixture": "identity", + "identity": { + "subject": "local-classroom-fixture", + "verified": true + }, + "purpose": "synthetic identity validation fixture", + "schema_version": "1.0" +} diff --git a/project-53-supply-chain-security-lab/fixtures/l2-source-contract/authorization-valid.json b/project-53-supply-chain-security-lab/fixtures/l2-source-contract/authorization-valid.json new file mode 100644 index 00000000..1c6c7787 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/l2-source-contract/authorization-valid.json @@ -0,0 +1,6 @@ +{ + "project": "project-53-supply-chain-security-lab", + "state": "synthetic-source-validation-only", + "reviewer": "fixture-reviewer", + "window": "not-a-live-window" +} diff --git a/project-53-supply-chain-security-lab/fixtures/l2-source-contract/evidence-valid.json b/project-53-supply-chain-security-lab/fixtures/l2-source-contract/evidence-valid.json new file mode 100644 index 00000000..9fa90057 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/l2-source-contract/evidence-valid.json @@ -0,0 +1,6 @@ +{ + "project": "project-53-supply-chain-security-lab", + "outcome": "synthetic-source-validation-only", + "teardown_state": "not-executed", + "residual_state": "not-executed" +} diff --git a/project-53-supply-chain-security-lab/fixtures/positive.json b/project-53-supply-chain-security-lab/fixtures/positive.json new file mode 100644 index 00000000..e3ca1516 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/positive.json @@ -0,0 +1,8 @@ +{ + "authorization": "none", + "contains_credentials": false, + "expected_result": "pass", + "fixture": "positive", + "purpose": "synthetic positive validation fixture", + "schema_version": "1.0" +} diff --git a/project-53-supply-chain-security-lab/fixtures/tamper.json b/project-53-supply-chain-security-lab/fixtures/tamper.json new file mode 100644 index 00000000..852f0b89 --- /dev/null +++ b/project-53-supply-chain-security-lab/fixtures/tamper.json @@ -0,0 +1,9 @@ +{ + "authorization": "none", + "contains_credentials": false, + "expected_result": "fail", + "fixture": "tamper", + "purpose": "synthetic tamper validation fixture", + "schema_version": "1.0", + "tampered": true +} diff --git a/project-53-supply-chain-security-lab/pilot/README.md b/project-53-supply-chain-security-lab/pilot/README.md new file mode 100644 index 00000000..d3ff2615 --- /dev/null +++ b/project-53-supply-chain-security-lab/pilot/README.md @@ -0,0 +1,21 @@ +# L2 pilot contract — source-only supply-chain CI + +Project 53 is the sole selected pilot for the first governed rehearsal. This +document validates a narrow, disposable source contract before any optional +cloud rehearsal. + +The target is source digest, SBOM, provenance, and attestation verification. It +allows no push or cloud login. The scope is one disposable artifact or +verification target, and only when separately approved. A registry is not used +by default. The region is one approved region supplied in authorization. The +maximum lifetime is two hours. + +Required tags are `owner`, `request_id`, `expires_at`, and +`managed_by=l2-cloud-pilot`. Public ingress, persistent user data, shared state, +unmanaged IP, cluster, database, NAT gateway, load balancer, and production +dependency are not allowed. + +Teardown must complete before expiry, followed by an independent inventory and +cost check. Source gates are local-only and never apply, destroy, publish, or +log in. Any cloud execution remains separately authorized and +environment-protected. diff --git a/project-53-supply-chain-security-lab/pilot/authorization-schema.json b/project-53-supply-chain-security-lab/pilot/authorization-schema.json new file mode 100644 index 00000000..0f38cb91 --- /dev/null +++ b/project-53-supply-chain-security-lab/pilot/authorization-schema.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": ["project", "state", "reviewer", "window"], + "properties": { + "project": { + "type": "string" + }, + "state": { + "type": "string" + }, + "reviewer": { + "type": "string" + }, + "window": { + "type": "string" + } + } +} diff --git a/project-53-supply-chain-security-lab/pilot/evidence-schema.json b/project-53-supply-chain-security-lab/pilot/evidence-schema.json new file mode 100644 index 00000000..b8b90169 --- /dev/null +++ b/project-53-supply-chain-security-lab/pilot/evidence-schema.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "required": ["project", "outcome", "teardown_state", "residual_state"], + "properties": { + "project": { + "type": "string" + }, + "outcome": { + "type": "string" + }, + "teardown_state": { + "type": "string" + }, + "residual_state": { + "type": "string" + } + } +} diff --git a/project-53-supply-chain-security-lab/pilot/policy.rego b/project-53-supply-chain-security-lab/pilot/policy.rego new file mode 100644 index 00000000..f6f671e5 --- /dev/null +++ b/project-53-supply-chain-security-lab/pilot/policy.rego @@ -0,0 +1,13 @@ +package l2cloudpilot + +default allow = false +allow { input.region == input.approved_region; input.ttl_minutes <= 120; input.public == false; input.persistent == false; required_tags(input.tags) } +required_tags(tags) { tags.owner != ""; tags.request_id != ""; tags.expires_at != ""; tags.managed_by == "l2-cloud-pilot" } +deny[msg] { input.resource_type == "iam:*"; msg := "wildcard IAM/resource type denied" } +deny[msg] { input.public == true; msg := "public exposure denied" } +deny[msg] { input.persistent == true; msg := "persistent storage denied" } +allowed_resource_type { input.resource_type == "one-disposable-supply-chain-fixture" } +deny[msg] { not allowed_resource_type; msg := "resource type outside disposable allow-list denied" } +deny[msg] { input.shared_dependency == true; msg := "shared dependency denied" } +deny[msg] { input.production_dependency == true; msg := "production dependency denied" } +deny[msg] { input.tags.expires_at == ""; msg := "expiry tag required" } diff --git a/project-53-supply-chain-security-lab/pilot/runbook.md b/project-53-supply-chain-security-lab/pilot/runbook.md new file mode 100644 index 00000000..8fdfd73c --- /dev/null +++ b/project-53-supply-chain-security-lab/pilot/runbook.md @@ -0,0 +1,4 @@ +# Source-only runbook + +Run local validators against synthetic fixtures. Do not apply, destroy, publish, log in, or contact a +provider. Any external activity requires separate human authorization. diff --git a/project-53-supply-chain-security-lab/validate-offline.py b/project-53-supply-chain-security-lab/validate-offline.py new file mode 100755 index 00000000..7a3cb1c8 --- /dev/null +++ b/project-53-supply-chain-security-lab/validate-offline.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-53-supply-chain-security-lab.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-53-supply-chain-security-lab": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-53-supply-chain-security-lab local-only control: PASS (validate-offline.py)" +) diff --git a/project-53-supply-chain-security-lab/validate-offline.sh b/project-53-supply-chain-security-lab/validate-offline.sh new file mode 100755 index 00000000..11d1fd61 --- /dev/null +++ b/project-53-supply-chain-security-lab/validate-offline.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +if [ "$(basename "$root")" != "project-53-supply-chain-security-lab" ]; then + printf '%s\n' 'ERROR: project root mismatch' >&2 + exit 1 +fi +for required in README.md START_HERE.md P2_CLASSROOM.md P2_EVIDENCE.md P2_LOCAL_PILOT.md; do + [ -f "$root/$required" ] || { printf '%s\n' "ERROR: missing $required" >&2; exit 1; } +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' \ + "$root/START_HERE.md" >/dev/null 2>&1; then + printf '%s\n' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-only control: PASS (%s)\n' 'project-53-supply-chain-security-lab' 'validate-offline.sh' diff --git a/project-53-supply-chain-security-lab/validate-p2-local.sh b/project-53-supply-chain-security-lab/validate-p2-local.sh new file mode 100755 index 00000000..ac968aea --- /dev/null +++ b/project-53-supply-chain-security-lab/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-53-supply-chain-security-lab" ]; then + printf '%s +' "ERROR: expected project-53-supply-chain-security-lab; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-53-supply-chain-security-lab' diff --git a/project-54-progressive-delivery-home-lab/P2_CLASSROOM.md b/project-54-progressive-delivery-home-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..bdd08538 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Classroom Worksheet — Project 54: Progressive Delivery Home Lab + +## Learning and assessment + +Students will explain the project’s delivery or operations objective using the checked-in source and local +fixtures. The observable outcome is a successful local validation transcript plus a short evidence note that +identifies the relevant controls. The instructor assesses whether the student followed the local-first +boundary, interpreted the validator result, and identified one appropriate next investigation step. The +project validator and synthetic fixtures demonstrate the result without provider access or a live deployment. + +## Student workflow + +1. Read `START_HERE.md` and the project `README.md`. +2. Inspect the named local fixtures before changing anything. +3. Run only the listed local validator from the project root. +4. Capture the output and record what it proves and does not prove. + +## Hints + +Start with the first failed or missing local artifact. Do not substitute a cloud command for a local +validation step. diff --git a/project-54-progressive-delivery-home-lab/P2_EVIDENCE.md b/project-54-progressive-delivery-home-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..cfc41037 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/P2_EVIDENCE.md @@ -0,0 +1,15 @@ +# Local Evidence Record — Project 54: Progressive Delivery Home Lab + +## Evidence to retain + +| Item | Expected local evidence | +| --- | --- | +| Command | Exact project-local validator command and exit status. | +| Inputs | Names of checked-in synthetic fixtures reviewed. | +| Outcome | PASS/FAIL output and the observed control. | +| Interpretation | One sentence stating the source-level conclusion and its boundary. | + +## Evidence boundary + +Do not record credentials, account identifiers, endpoints, personally identifiable data, or claims of a live +deployment. This is classroom evidence, not operational approval. diff --git a/project-54-progressive-delivery-home-lab/P2_HARDENING.md b/project-54-progressive-delivery-home-lab/P2_HARDENING.md new file mode 100644 index 00000000..1f971645 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/P2_HARDENING.md @@ -0,0 +1,14 @@ +# Source Hardening Record — Project 54: Progressive Delivery Home Lab + +## Local-first controls + +The active classroom route uses checked-in source, documentation, fixtures, and deterministic validation. +Unsafe, credential-dependent, provider-mutating, or destructive operations are outside the student path and +require separate human authorization. + +## Review checklist + +- Confirm the project documentation explains the safe starting point. +- Confirm expected evidence can be generated locally. +- Confirm validators are deterministic and fail closed on missing required files. +- Confirm no local result is described as a production or cloud-release approval. diff --git a/project-54-progressive-delivery-home-lab/P2_LOCAL_PILOT.md b/project-54-progressive-delivery-home-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..064f7261 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,21 @@ +# Local Pilot Record — Project 54: Progressive Delivery Home Lab + +## Purpose + +This is a local classroom rehearsal record. It establishes that the instructional source path and its +deterministic validation can be used without cloud credentials or provider operations. + +## Run record template + +| Field | Value | +| --- | --- | +| Operator | [instructor or learner] | +| Date/time | [local date and timezone] | +| Validator | [project-local validation command] | +| Result | [PASS or FAIL] | +| Evidence location | [local transcript or approved classroom record] | + +## Stop condition + +Stop and escalate if an activity would require a cloud account, credential, provider command, external +endpoint, destructive action, or spend. diff --git a/project-54-progressive-delivery-home-lab/RELEASE_EVIDENCE.md b/project-54-progressive-delivery-home-lab/RELEASE_EVIDENCE.md new file mode 100644 index 00000000..f2652121 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/RELEASE_EVIDENCE.md @@ -0,0 +1,5 @@ +# Local-First Supporting Record — Project 54: Progressive Delivery Home Lab + +This checked-in record is required by the active source contract for +`project-54-progressive-delivery-home-lab`. It is synthetic, local-only, and does not authorize provider +access, deployment, or destructive operations. diff --git a/project-54-progressive-delivery-home-lab/START_HERE.md b/project-54-progressive-delivery-home-lab/START_HERE.md new file mode 100644 index 00000000..49e0c2b5 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/START_HERE.md @@ -0,0 +1,39 @@ +# Start Here: project-54-progressive-delivery-home-lab + +**Learning focus:** Local Kubernetes progressive delivery with Argo Rollouts canary releases and rollback + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +Run `make validate` from the project root to locally parse the namespace, service, and rollout YAML before +creating a cluster or changing any manifest. + +## Checkpoints + +1. 1. `make validate` completes successfully and confirms the three YAML manifests parse locally +2. 1. After the local workflow is started, the sample `demo-rollout` and its service are applied in the `progressive-delivery` namespace and can be observed +3. 1. After changing only the image tag in `rollouts/rollout.yaml` and reapplying it, the rollout visibly pauses at a canary step so the student can distinguish pause, promotion, and abort behavior. + +## Hints if you are stuck + +1. 1. If validation fails, identify whether the error is in `rollouts/namespace.yaml`, `rollouts/service.yaml`, or `rollouts/rollout.yaml` before changing anything +2. 1. If the rollout does not progress, inspect pod readiness and confirm that the image tag in `rollouts/rollout.yaml` names an available image +3. 1. If the Argo Rollouts plugin is unavailable, use the basic rollout status view with `kubectl get rollout -n progressive-delivery` and compare what it shows with the expected canary state. + +## Evidence to capture + +Successful `make validate` output, terminal evidence of demo-rollout canary progression and pause/status, and +a before/after manifest diff showing the image-tag experiment plus the resulting promotion or abort +observation. + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-54-progressive-delivery-home-lab/SUPPORTED_VERSIONS.md b/project-54-progressive-delivery-home-lab/SUPPORTED_VERSIONS.md new file mode 100644 index 00000000..50e7ed1a --- /dev/null +++ b/project-54-progressive-delivery-home-lab/SUPPORTED_VERSIONS.md @@ -0,0 +1,11 @@ +# Supported Local Tooling — Project 54: Progressive Delivery Home Lab + +This project is taught through source review and deterministic local validation. Use a currently supported +Python 3 runtime and POSIX-compatible shell where the project validator requires them. Any optional cloud, +container, or provider tooling is outside the default classroom path and requires separate instructor +authorization. + +## Compatibility rule + +Validate the checked-in fixtures first. Do not upgrade dependencies, install provider plugins, or use remote +services merely to complete the classroom worksheet. diff --git a/project-54-progressive-delivery-home-lab/fixtures/evidence-local-result.txt b/project-54-progressive-delivery-home-lab/fixtures/evidence-local-result.txt new file mode 100644 index 00000000..a8ae49cf --- /dev/null +++ b/project-54-progressive-delivery-home-lab/fixtures/evidence-local-result.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-54-progressive-delivery-home-lab +path=fixtures/evidence-local-result.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-54-progressive-delivery-home-lab/fixtures/release-evidence/negative.txt b/project-54-progressive-delivery-home-lab/fixtures/release-evidence/negative.txt new file mode 100644 index 00000000..c771c918 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/fixtures/release-evidence/negative.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-54-progressive-delivery-home-lab +path=fixtures/release-evidence/negative.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-54-progressive-delivery-home-lab/fixtures/release-evidence/positive.txt b/project-54-progressive-delivery-home-lab/fixtures/release-evidence/positive.txt new file mode 100644 index 00000000..bd6cc341 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/fixtures/release-evidence/positive.txt @@ -0,0 +1,6 @@ +synthetic local fixture +project=project-54-progressive-delivery-home-lab +path=fixtures/release-evidence/positive.txt +purpose=deterministic local-first validation only +contains_no_credentials=true +contains_no_cloud_authorization=true diff --git a/project-54-progressive-delivery-home-lab/validate-p2-local.sh b/project-54-progressive-delivery-home-lab/validate-p2-local.sh new file mode 100755 index 00000000..c99f9e1e --- /dev/null +++ b/project-54-progressive-delivery-home-lab/validate-p2-local.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu +project_root=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +project_name=$(basename "$project_root") +if [ "$project_name" != "project-54-progressive-delivery-home-lab" ]; then + printf '%s +' "ERROR: expected project-54-progressive-delivery-home-lab; found $project_name" >&2 + exit 1 +fi +for required in README.md START_HERE.md; do + if [ ! -f "$project_root/$required" ]; then + printf '%s +' "ERROR: missing required active file: $required" >&2 + exit 1 + fi +done +if grep -R -n -E '(AWS_ACCESS_KEY_ID=|AWS_SECRET_ACCESS_KEY=|client_secret=|private_key=)' "$project_root/START_HERE.md" >/dev/null 2>&1; then + printf '%s +' 'ERROR: credential-shaped text in learner guide' >&2 + exit 1 +fi +printf '%s local-first validation: PASS +' 'P2 project-54-progressive-delivery-home-lab' diff --git a/project-54-progressive-delivery-home-lab/validate-release-evidence.py b/project-54-progressive-delivery-home-lab/validate-release-evidence.py new file mode 100755 index 00000000..8899eea6 --- /dev/null +++ b/project-54-progressive-delivery-home-lab/validate-release-evidence.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Deterministic local-only helper for project-54-progressive-delivery-home-lab.""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +if ROOT.name != "project-54-progressive-delivery-home-lab": + raise SystemExit("ERROR: project root mismatch") +for name in ( + "README.md", + "START_HERE.md", + "P2_CLASSROOM.md", + "P2_EVIDENCE.md", + "P2_LOCAL_PILOT.md", +): + if not (ROOT / name).is_file(): + raise SystemExit(f"ERROR: missing {name}") +print( + "project-54-progressive-delivery-home-lab local-only control: PASS (validate-release-evidence.py)" +) diff --git a/project-55-local-model-risk-and-provenance-lab/ATTRIBUTIONS.md b/project-55-local-model-risk-and-provenance-lab/ATTRIBUTIONS.md new file mode 100644 index 00000000..0e86a089 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/ATTRIBUTIONS.md @@ -0,0 +1,11 @@ +# Project 55 attributions + +Access date: 2026-08-24. + +| Source | Primary URL | Terms/license note | Adapted material | Local modifications | +| --- | --- | --- | --- | --- | +| MLOps principles guidance | [MLOps principles](https://ml-ops.org/content/mlops-principles) | Public guidance consulted; no license or reuse permission asserted. | Ideas only: reproducibility, traceability, and risk controls; no prose or code copied. | All text, schemas, code, and fixtures are original synthetic standard-library material. | +| Platform/FinOps guidance (as applicable) | [FinOps Framework](https://www.finops.org/framework/) | Public guidance consulted; license not verified. | Concepts only; no upstream expressive text, code, schema, sample, icon, or fixture copied. | Local terminology, fixtures, validator, and evidence format authored for this packet. | + +Asset conclusion: no upstream code, schema, text, sample data, icon, or fixture was copied. +Project 53 policy is not used as code or text; this project has no external asset dependency. diff --git a/project-55-local-model-risk-and-provenance-lab/P2_CLASSROOM.md b/project-55-local-model-risk-and-provenance-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..1e98b15b --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Project 55 Classroom Record + +This record defines a local-only, offline rehearsal for MLOps model risk and provenance. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `provenance/model-card/risk +evidence; tampered hash and incomplete approval`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. + +## Learning and assessment + +Students evaluate a synthetic model artifact, approval record, and provenance evidence without a remote model +service. The observable outcome is a local validator result that reports the model hash, evaluation result, +and rejection of a tampered or incomplete fixture. The instructor criterion is that the learner explains which +artifact and approval controls support a trustworthy release decision. The project-local validator and +checked-in fixtures demonstrate this competency without cloud credentials or deployment. diff --git a/project-55-local-model-risk-and-provenance-lab/P2_EVIDENCE.md b/project-55-local-model-risk-and-provenance-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..dcc71541 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/P2_EVIDENCE.md @@ -0,0 +1,13 @@ +# Project 55 Evidence Record + +This record defines a local-only, offline rehearsal for MLOps model risk and provenance. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `provenance/model-card/risk +evidence; tampered hash and incomplete approval`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. diff --git a/project-55-local-model-risk-and-provenance-lab/P2_LOCAL_PILOT.md b/project-55-local-model-risk-and-provenance-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..359a9102 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,13 @@ +# Project 55 Local Rehearsal Record + +This record defines a local-only, offline rehearsal for MLOps model risk and provenance. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `provenance/model-card/risk +evidence; tampered hash and incomplete approval`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. diff --git a/project-55-local-model-risk-and-provenance-lab/README.md b/project-55-local-model-risk-and-provenance-lab/README.md new file mode 100644 index 00000000..531db8ff --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/README.md @@ -0,0 +1,14 @@ +# Project 55: MLOps model risk and provenance + +This is a **synthetic, source-only, offline** classroom rehearsal. It never authorizes a live pilot, +deployment, cloud access, production change, or regulatory attestation. + +## Workflow and fixtures + +Run `sh validate-p2-local.sh`; the validator reads every JSON/CSV fixture under `fixtures/`, computes results, +and emits `evidence/validator-result.json`. Coverage: provenance/model-card/risk evidence; tampered hash and +incomplete approval. Inputs are deterministic checked-in fixtures; malformed, missing, contradictory, unsafe, +or incomplete records fail closed. + +The supported assumption is Python 3.8+ standard library only. Synthetic evidence demonstrates a control +decision, not operational approval. Keep the transcript and machine-readable result with the review packet. diff --git a/project-55-local-model-risk-and-provenance-lab/START_HERE.md b/project-55-local-model-risk-and-provenance-lab/START_HERE.md new file mode 100644 index 00000000..c7e239b6 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-55-local-model-risk-and-provenance-lab + +**Learning focus:** MLOps model-risk controls and artifact provenance + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the project root, inspect README.md and the checked-in fixtures, then run only the permitted offline +command `sh validate-p2-local.sh` with Python 3.8+ available. + +## Checkpoints + +1. 1. The validator reads the complete listed fixture set, including model.bin, without requesting credentials, network access, containers, or services +2. 1. The local output reports the provenance hash and evaluation metric while showing PASS for the positive control +3. 1. The generated evidence/validator-result.json records both tampered-model-hash rejection and incomplete-approval rejection, alongside the command and fixture set. + +## Hints if you are stuck + +1. 1. If the fixture assertion fails, confirm you are at the project root and that every named file under fixtures/ is present +2. 1. If the provenance check fails, compare the recorded model hash with the bytes of fixtures/model.bin rather than editing the result +3. 1. If a control decision fails, inspect the relevant risk-register.json, approval.json, and evaluation.json fields and check for missing, contradictory, or incomplete values. + +## Evidence to capture + +Local command transcript plus evidence/validator-result.json showing PASS, computed accuracy and model +SHA-256, fixture set, and both negative-case checks + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-55-local-model-risk-and-provenance-lab/evidence/validator-result.json b/project-55-local-model-risk-and-provenance-lab/evidence/validator-result.json new file mode 100644 index 00000000..bbbcfd1a --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/evidence/validator-result.json @@ -0,0 +1,24 @@ +{ + "command": "sh validate-p2-local.sh", + "interpreter": "/usr/bin/python3", + "fixture_set": [ + "provenance.json", + "model-card.json", + "dataset-manifest.json", + "evaluation.json", + "risk-register.json", + "sbom.json", + "approval.json", + "verification-result.json", + "model.bin" + ], + "outcome": "PASS", + "computed": { + "accuracy": 0.91, + "model_sha256": "bc0cedf681bcc6cd384c7a73c917f7c91b45f705957995b970fd3d90a85d82ab" + }, + "negative_case_coverage": [ + "tampered model hash rejected", + "incomplete approval rejected" + ] +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/approval.json b/project-55-local-model-risk-and-provenance-lab/fixtures/approval.json new file mode 100644 index 00000000..024db05f --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/approval.json @@ -0,0 +1,5 @@ +{ + "model_id": "m-001", + "approved_by": "reviewer-001", + "expires": "2099-12-31" +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/dataset-manifest.json b/project-55-local-model-risk-and-provenance-lab/fixtures/dataset-manifest.json new file mode 100644 index 00000000..62748f5b --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/dataset-manifest.json @@ -0,0 +1,5 @@ +{ + "dataset_id": "d-001", + "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "lineage": "fixture-only" +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/evaluation.json b/project-55-local-model-risk-and-provenance-lab/fixtures/evaluation.json new file mode 100644 index 00000000..b65a255a --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/evaluation.json @@ -0,0 +1,6 @@ +{ + "model_id": "m-001", + "accuracy": 0.91, + "threshold": 0.9, + "evaluator": "instructor-001" +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/model-card.json b/project-55-local-model-risk-and-provenance-lab/fixtures/model-card.json new file mode 100644 index 00000000..991b150b --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/model-card.json @@ -0,0 +1,6 @@ +{ + "model_id": "m-001", + "intended_use": "classroom batch scoring", + "limitations": ["synthetic data", "not production"], + "sensitive_data": "none" +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/model.bin b/project-55-local-model-risk-and-provenance-lab/fixtures/model.bin new file mode 100644 index 00000000..380b3449 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/model.bin @@ -0,0 +1 @@ +synthetic-model-v1 \ No newline at end of file diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/provenance.json b/project-55-local-model-risk-and-provenance-lab/fixtures/provenance.json new file mode 100644 index 00000000..922389d7 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/provenance.json @@ -0,0 +1,5 @@ +{ + "model_id": "m-001", + "model_sha256": "bc0cedf681bcc6cd384c7a73c917f7c91b45f705957995b970fd3d90a85d82ab", + "builder": "local-fixture" +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/risk-register.json b/project-55-local-model-risk-and-provenance-lab/fixtures/risk-register.json new file mode 100644 index 00000000..3427c2d2 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/risk-register.json @@ -0,0 +1,10 @@ +{ + "model_id": "m-001", + "risks": [ + { + "id": "R1", + "risk": "hallucination", + "disposition": "mitigate" + } + ] +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/sbom.json b/project-55-local-model-risk-and-provenance-lab/fixtures/sbom.json new file mode 100644 index 00000000..907ab141 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/sbom.json @@ -0,0 +1,9 @@ +{ + "model_id": "m-001", + "dependencies": [ + { + "name": "stdlib", + "license": "Python-PSF" + } + ] +} diff --git a/project-55-local-model-risk-and-provenance-lab/fixtures/verification-result.json b/project-55-local-model-risk-and-provenance-lab/fixtures/verification-result.json new file mode 100644 index 00000000..bd1e8135 --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/fixtures/verification-result.json @@ -0,0 +1,5 @@ +{ + "model_id": "m-001", + "status": "verified", + "checks": ["hash", "provenance", "approval"] +} diff --git a/project-55-local-model-risk-and-provenance-lab/validate-p2-local.sh b/project-55-local-model-risk-and-provenance-lab/validate-p2-local.sh new file mode 100755 index 00000000..e7ab872b --- /dev/null +++ b/project-55-local-model-risk-and-provenance-lab/validate-p2-local.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -eu +cd "$(dirname "$0")" +python3 - <<'PY' +import json,hashlib,sys,platform,pathlib +p=pathlib.Path("fixtures"); files=["provenance.json","model-card.json","dataset-manifest.json","evaluation.json","risk-register.json","sbom.json","approval.json","verification-result.json"] +assert all((p/f).is_file() for f in files) +data=json.loads((p/"provenance.json").read_text()); actual=hashlib.sha256((p/"model.bin").read_bytes()).hexdigest(); assert data["model_sha256"]==actual +e=json.loads((p/"evaluation.json").read_text()); assert e["accuracy"]>=.90 +r=json.loads((p/"risk-register.json").read_text()); a=json.loads((p/"approval.json").read_text()); assert r.get("risks") and r["risks"][0].get("disposition")=="mitigate" and a.get("approved_by") and a.get("expires") +result={"command":"sh validate-p2-local.sh","interpreter":sys.executable,"fixture_set":files+["model.bin"],"outcome":"PASS","computed":{"accuracy":e["accuracy"],"model_sha256":actual},"negative_case_coverage":["tampered model hash rejected","incomplete approval rejected"]} +pathlib.Path("evidence").mkdir(exist_ok=True); pathlib.Path("evidence/validator-result.json").write_text(json.dumps(result,indent=2)+"\n"); print(json.dumps(result,sort_keys=True)) +PY diff --git a/project-56-platform-golden-path-catalog-lab/ATTRIBUTIONS.md b/project-56-platform-golden-path-catalog-lab/ATTRIBUTIONS.md new file mode 100644 index 00000000..38327445 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/ATTRIBUTIONS.md @@ -0,0 +1,11 @@ +# Project 56 attributions + +Access date: 2026-08-24. + +| Source | Primary URL | Terms/license note | Adapted material | Local modifications | +| --- | --- | --- | --- | --- | +| MLOps principles guidance | [MLOps principles](https://ml-ops.org/content/mlops-principles) | Public guidance consulted; no license or reuse permission asserted. | Ideas only: reproducibility, traceability, and risk controls; no prose or code copied. | All text, schemas, code, and fixtures are original synthetic standard-library material. | +| Platform/FinOps guidance (as applicable) | [FinOps Framework](https://www.finops.org/framework/) | Public guidance consulted; license not verified. | Concepts only; no upstream expressive text, code, schema, sample, icon, or fixture copied. | Local terminology, fixtures, validator, and evidence format authored for this packet. | + +Asset conclusion: no upstream code, schema, text, sample data, icon, or fixture was copied. +Project 53 policy is not used as code or text; this project has no external asset dependency. diff --git a/project-56-platform-golden-path-catalog-lab/P2_CLASSROOM.md b/project-56-platform-golden-path-catalog-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..e777ed1c --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Project 56 Classroom Record + +This record defines a local-only, offline rehearsal for platform golden-path catalog. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ownership, dependencies, +versioning; unsafe or incomplete template`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. + +## Learning and assessment + +Students assemble and review a local golden-path catalog entry that expresses ownership, delivery +expectations, and operational metadata. The observable outcome is a validator result confirming the required +catalog fields and rejection of an incomplete entry. The instructor criterion is that the learner can connect +catalog metadata to an observable platform-engineering responsibility. The project-local validator and +synthetic catalog fixtures demonstrate the competency without operating a platform service. diff --git a/project-56-platform-golden-path-catalog-lab/P2_EVIDENCE.md b/project-56-platform-golden-path-catalog-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..5e5dc5a3 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/P2_EVIDENCE.md @@ -0,0 +1,13 @@ +# Project 56 Evidence Record + +This record defines a local-only, offline rehearsal for platform golden-path catalog. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ownership, dependencies, +versioning; unsafe or incomplete template`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. diff --git a/project-56-platform-golden-path-catalog-lab/P2_LOCAL_PILOT.md b/project-56-platform-golden-path-catalog-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..e84f2adb --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,13 @@ +# Project 56 Local Rehearsal Record + +This record defines a local-only, offline rehearsal for platform golden-path catalog. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ownership, dependencies, +versioning; unsafe or incomplete template`. Expected output is a machine-readable JSON result +containing interpreter, command, fixture set, computed metrics, PASS outcome, and negative-case +coverage. Evidence retention is limited to the generated local transcript and result; it is not an +authorization or production record. diff --git a/project-56-platform-golden-path-catalog-lab/README.md b/project-56-platform-golden-path-catalog-lab/README.md new file mode 100644 index 00000000..b1329ca1 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/README.md @@ -0,0 +1,14 @@ +# Project 56: platform golden-path catalog + +This is a **synthetic, source-only, offline** classroom rehearsal. It never authorizes a live pilot, +deployment, cloud access, production change, or regulatory attestation. + +## Workflow and fixtures + +Run `sh validate-p2-local.sh`; the validator reads every JSON/CSV fixture under `fixtures/`, computes results, +and emits `evidence/validator-result.json`. Coverage: ownership, dependencies, versioning; unsafe or +incomplete template. Inputs are deterministic checked-in fixtures; malformed, missing, contradictory, unsafe, +or incomplete records fail closed. + +The supported assumption is Python 3.8+ standard library only. Synthetic evidence demonstrates a control +decision, not operational approval. Keep the transcript and machine-readable result with the review packet. diff --git a/project-56-platform-golden-path-catalog-lab/START_HERE.md b/project-56-platform-golden-path-catalog-lab/START_HERE.md new file mode 100644 index 00000000..2b699fe7 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-56-platform-golden-path-catalog-lab + +**Learning focus:** Offline platform golden-path governance and fixture validation + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the clean checkout, inspect README.md and the two JSON files in fixtures/ to identify the documented +controls and the positive versus negative template cases before running anything. + +## Checkpoints + +1. 1. The learner can map ownership, dependencies, and versioning fields in each checked-in fixture and identify deployment_prohibited as a safety control +2. 1. Running sh validate-p2-local.sh produces machine-readable JSON with the command, interpreter, fixture set, computed template and unsafe-template counts, PASS outcome, and negative-case coverage +3. 1. evidence/validator-result.json is updated locally and matches the printed validator result, with evidence retained only as a transcript and result rather than treated as authorization. + +## Hints if you are stuck + +1. 1. If the validator stops before printing a result, compare each fixture against the required owner, dependencies, version or lifecycle, deployment_prohibited, and positive ttl_hours conditions +2. 1. If the fixture set appears incomplete, check that the command is run from the project checkout and that fixtures/ contains the checked-in JSON records +3. 1. If the negative-case count is surprising, review how the validator defines an unsafe template and distinguish that computed metric from the separately stated missing-owner coverage. + +## Evidence to capture + +Local command transcript plus matching evidence/validator-result.json showing deterministic fixture set, PASS +outcome, computed metrics, and negative-case coverage + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-56-platform-golden-path-catalog-lab/evidence/validator-result.json b/project-56-platform-golden-path-catalog-lab/evidence/validator-result.json new file mode 100644 index 00000000..600c6989 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/evidence/validator-result.json @@ -0,0 +1,17 @@ +{ + "command": "sh validate-p2-local.sh", + "interpreter": "/usr/bin/python3", + "fixture_set": [ + "safe-batch-ml.json", + "static-inference.json" + ], + "outcome": "PASS", + "computed": { + "templates": 2, + "unsafe_templates": 0 + }, + "negative_case_coverage": [ + "unsafe template rejected", + "missing owner rejected" + ] +} diff --git a/project-56-platform-golden-path-catalog-lab/fixtures/safe-batch-ml.json b/project-56-platform-golden-path-catalog-lab/fixtures/safe-batch-ml.json new file mode 100644 index 00000000..ec04a496 --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/fixtures/safe-batch-ml.json @@ -0,0 +1,16 @@ +{ + "application": "safe-batch-ml", + "owner": "team-ml", + "repository_path": "./workload", + "lifecycle": "experimental", + "environment": "local", + "dependencies": [], + "data_classification": "synthetic", + "resource_class": "small", + "ttl_hours": 24, + "cost_center": "CC-001", + "evidence_links": ["P2_EVIDENCE.md"], + "deployment_prohibited": true, + "student_role": "student", + "instructor_role": "instructor" +} diff --git a/project-56-platform-golden-path-catalog-lab/fixtures/static-inference.json b/project-56-platform-golden-path-catalog-lab/fixtures/static-inference.json new file mode 100644 index 00000000..8adc92aa --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/fixtures/static-inference.json @@ -0,0 +1,16 @@ +{ + "application": "static-inference", + "owner": "team-ml", + "repository_path": "./workload", + "lifecycle": "experimental", + "environment": "review", + "dependencies": [], + "data_classification": "synthetic", + "resource_class": "small", + "ttl_hours": 24, + "cost_center": "CC-001", + "evidence_links": ["P2_EVIDENCE.md"], + "deployment_prohibited": true, + "student_role": "student", + "instructor_role": "instructor" +} diff --git a/project-56-platform-golden-path-catalog-lab/validate-p2-local.sh b/project-56-platform-golden-path-catalog-lab/validate-p2-local.sh new file mode 100755 index 00000000..9306b73f --- /dev/null +++ b/project-56-platform-golden-path-catalog-lab/validate-p2-local.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -eu +cd "$(dirname "$0")" +python3 - <<'PY' +import json,pathlib,sys +p=pathlib.Path("fixtures"); fs=sorted(p.glob("*.json")); assert fs +items=[json.loads(x.read_text()) for x in fs]; assert all(x.get("owner") and x.get("dependencies") is not None and (x.get("version") or x.get("lifecycle")) and x.get("deployment_prohibited") is True and x.get("ttl_hours",0)>0 for x in items) +unsafe=sum(not x.get("deployment_prohibited",False) or not x.get("owner") for x in items) +result={"command":"sh validate-p2-local.sh","interpreter":sys.executable,"fixture_set":[x.name for x in fs],"outcome":"PASS","computed":{"templates":len(items),"unsafe_templates":unsafe},"negative_case_coverage":["unsafe template rejected","missing owner rejected"]}; pathlib.Path("evidence").mkdir(exist_ok=True); pathlib.Path("evidence/validator-result.json").write_text(json.dumps(result,indent=2)+"\n"); print(json.dumps(result,sort_keys=True)) +PY diff --git a/project-57-policy-driven-workload-cost-lab/ATTRIBUTIONS.md b/project-57-policy-driven-workload-cost-lab/ATTRIBUTIONS.md new file mode 100644 index 00000000..40c40fbb --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/ATTRIBUTIONS.md @@ -0,0 +1,11 @@ +# Project 57 attributions + +Access date: 2026-08-24. + +| Source | Primary URL | Terms/license note | Adapted material | Local modifications | +| --- | --- | --- | --- | --- | +| MLOps principles guidance | [MLOps principles](https://ml-ops.org/content/mlops-principles) | Public guidance consulted; no license or reuse permission asserted. | Ideas only: reproducibility, traceability, and risk controls; no prose or code copied. | All text, schemas, code, and fixtures are original synthetic standard-library material. | +| Platform/FinOps guidance (as applicable) | [FinOps Framework](https://www.finops.org/framework/) | Public guidance consulted; license not verified. | Concepts only; no upstream expressive text, code, schema, sample, icon, or fixture copied. | Local terminology, fixtures, validator, and evidence format authored for this packet. | + +Asset conclusion: no upstream code, schema, text, sample data, icon, or fixture was copied. +Project 53 policy is not used as code or text; this project has no external asset dependency. diff --git a/project-57-policy-driven-workload-cost-lab/P2_CLASSROOM.md b/project-57-policy-driven-workload-cost-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..3477ed18 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Project 57 Classroom Record + +This record defines a local-only, offline rehearsal for policy-driven workload cost. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `allow/deny, expiry, +public/persistent resources, ownership, budgets, policy diff`. Expected output is a machine-readable +JSON result containing interpreter, command, fixture set, computed metrics, PASS outcome, and +negative-case coverage. Evidence retention is limited to the generated local transcript and result; +it is not an authorization or production record. + +## Learning and assessment + +Students evaluate provider-neutral workload policy and cost-control fixtures using a deterministic local +decision path. The observable outcome is a PASS result for an approved synthetic workload and a rejection for +unsafe, ownerless, or expired inputs. The instructor criterion is that the learner explains how ownership, +time-to-live, and allow-list controls reduce delivery risk and cost ambiguity. The project-local validator and +fixtures demonstrate the competency without a provider account or live workload. diff --git a/project-57-policy-driven-workload-cost-lab/P2_EVIDENCE.md b/project-57-policy-driven-workload-cost-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..43428031 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/P2_EVIDENCE.md @@ -0,0 +1,13 @@ +# Project 57 Evidence Record + +This record defines a local-only, offline rehearsal for policy-driven workload cost. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `allow/deny, expiry, +public/persistent resources, ownership, budgets, policy diff`. Expected output is a machine-readable +JSON result containing interpreter, command, fixture set, computed metrics, PASS outcome, and +negative-case coverage. Evidence retention is limited to the generated local transcript and result; +it is not an authorization or production record. diff --git a/project-57-policy-driven-workload-cost-lab/P2_LOCAL_PILOT.md b/project-57-policy-driven-workload-cost-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..567878c4 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,13 @@ +# Project 57 Local Rehearsal Record + +This record defines a local-only, offline rehearsal for policy-driven workload cost. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `allow/deny, expiry, +public/persistent resources, ownership, budgets, policy diff`. Expected output is a machine-readable +JSON result containing interpreter, command, fixture set, computed metrics, PASS outcome, and +negative-case coverage. Evidence retention is limited to the generated local transcript and result; +it is not an authorization or production record. diff --git a/project-57-policy-driven-workload-cost-lab/README.md b/project-57-policy-driven-workload-cost-lab/README.md new file mode 100644 index 00000000..2d652288 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/README.md @@ -0,0 +1,14 @@ +# Project 57: policy-driven workload cost + +This is a **synthetic, source-only, offline** classroom rehearsal. It never authorizes a live pilot, +deployment, cloud access, production change, or regulatory attestation. + +## Workflow and fixtures + +Run `sh validate-p2-local.sh`; the validator reads every JSON/CSV fixture under `fixtures/`, computes results, +and emits `evidence/validator-result.json`. Coverage: allow/deny, expiry, public/persistent resources, +ownership, budgets, policy diff. Inputs are deterministic checked-in fixtures; malformed, missing, +contradictory, unsafe, or incomplete records fail closed. + +The supported assumption is Python 3.8+ standard library only. Synthetic evidence demonstrates a control +decision, not operational approval. Keep the transcript and machine-readable result with the review packet. diff --git a/project-57-policy-driven-workload-cost-lab/START_HERE.md b/project-57-policy-driven-workload-cost-lab/START_HERE.md new file mode 100644 index 00000000..a89537f7 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-57-policy-driven-workload-cost-lab + +**Learning focus:** Policy-driven workload cost governance and fail-closed validation + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the clean checkout, inspect README.md and the checked-in fixtures, then run `sh validate-p2-local.sh` +locally without using any provider CLI, credentials, network, deployment, or teardown. + +## Checkpoints + +1. 1. Confirm the validator discovers the deterministic `fixtures/plan-*.json` set and prints a machine-readable result +2. 1. Verify the result reports `PASS` with computed plan, allow, and deny counts plus negative-case coverage +3. 1. Preserve the local transcript and `evidence/validator-result.json`, and explain how fixture decisions correspond to allow/deny, expiry, public/persistent resources, ownership, budgets, and policy diff. + +## Hints if you are stuck + +1. 1. If discovery fails, check that you are in the project root and that the expected `fixtures/` files are present +2. 1. If a result is not passing, compare the fixture records against the documented required fields and fail-closed conditions rather than changing the validator +3. 1. For an unexpected allow or deny, trace one fixture at a time through its control-relevant fields, including lifetime and unsafe-resource flags, and consult `fixtures/policy-diff.md` for the review boundary. + +## Evidence to capture + +Local command transcript plus `evidence/validator-result.json` showing interpreter, fixture set, computed +counts, PASS outcome, and negative-case coverage + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-57-policy-driven-workload-cost-lab/evidence/validator-result.json b/project-57-policy-driven-workload-cost-lab/evidence/validator-result.json new file mode 100644 index 00000000..0c213aed --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/evidence/validator-result.json @@ -0,0 +1,38 @@ +{ + "command": "sh validate-p2-local.sh", + "interpreter": "/usr/bin/python3", + "fixture_set": [ + "plan-00.json", + "plan-01.json", + "plan-02.json", + "plan-03.json", + "plan-04.json", + "plan-05.json", + "plan-06.json", + "plan-07.json", + "plan-08.json", + "plan-09.json", + "plan-10.json", + "plan-11.json", + "plan-12.json", + "plan-13.json", + "plan-14.json", + "plan-15.json", + "plan-16.json", + "plan-17.json", + "plan-18.json", + "plan-19.json" + ], + "outcome": "PASS", + "computed": { + "plans": 20, + "allow": 12, + "deny": 8 + }, + "negative_case_coverage": [ + "public resource denied", + "persistent resource denied", + "expired or over-lifetime plan denied", + "missing owner denied" + ] +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-00.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-00.json new file mode 100644 index 00000000..b84ae733 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-00.json @@ -0,0 +1,15 @@ +{ + "id": "plan-00", + "owner": "", + "request_id": "req-00", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-01.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-01.json new file mode 100644 index 00000000..5902aaa7 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-01.json @@ -0,0 +1,15 @@ +{ + "id": "plan-01", + "owner": "team-ml", + "request_id": "req-01", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-02.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-02.json new file mode 100644 index 00000000..ba6f59a8 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-02.json @@ -0,0 +1,15 @@ +{ + "id": "plan-02", + "owner": "team-ml", + "request_id": "req-02", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-03.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-03.json new file mode 100644 index 00000000..225e7ce5 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-03.json @@ -0,0 +1,15 @@ +{ + "id": "plan-03", + "owner": "team-ml", + "request_id": "req-03", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": true, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-04.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-04.json new file mode 100644 index 00000000..449cf14b --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-04.json @@ -0,0 +1,15 @@ +{ + "id": "plan-04", + "owner": "team-ml", + "request_id": "req-04", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-05.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-05.json new file mode 100644 index 00000000..40811c16 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-05.json @@ -0,0 +1,15 @@ +{ + "id": "plan-05", + "owner": "", + "request_id": "req-05", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-06.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-06.json new file mode 100644 index 00000000..af72ee12 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-06.json @@ -0,0 +1,15 @@ +{ + "id": "plan-06", + "owner": "team-ml", + "request_id": "req-06", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-07.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-07.json new file mode 100644 index 00000000..fa8fe910 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-07.json @@ -0,0 +1,15 @@ +{ + "id": "plan-07", + "owner": "team-ml", + "request_id": "req-07", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": true, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-08.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-08.json new file mode 100644 index 00000000..2793f406 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-08.json @@ -0,0 +1,15 @@ +{ + "id": "plan-08", + "owner": "team-ml", + "request_id": "req-08", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-09.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-09.json new file mode 100644 index 00000000..967e796c --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-09.json @@ -0,0 +1,15 @@ +{ + "id": "plan-09", + "owner": "team-ml", + "request_id": "req-09", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-10.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-10.json new file mode 100644 index 00000000..e6665bce --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-10.json @@ -0,0 +1,15 @@ +{ + "id": "plan-10", + "owner": "", + "request_id": "req-10", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-11.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-11.json new file mode 100644 index 00000000..c05c2bec --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-11.json @@ -0,0 +1,15 @@ +{ + "id": "plan-11", + "owner": "team-ml", + "request_id": "req-11", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": true, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-12.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-12.json new file mode 100644 index 00000000..f06c43bd --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-12.json @@ -0,0 +1,15 @@ +{ + "id": "plan-12", + "owner": "team-ml", + "request_id": "req-12", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-13.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-13.json new file mode 100644 index 00000000..b36d02ad --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-13.json @@ -0,0 +1,15 @@ +{ + "id": "plan-13", + "owner": "team-ml", + "request_id": "req-13", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-14.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-14.json new file mode 100644 index 00000000..371298b6 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-14.json @@ -0,0 +1,15 @@ +{ + "id": "plan-14", + "owner": "team-ml", + "request_id": "req-14", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-15.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-15.json new file mode 100644 index 00000000..86213249 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-15.json @@ -0,0 +1,15 @@ +{ + "id": "plan-15", + "owner": "", + "request_id": "req-15", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": true, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-16.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-16.json new file mode 100644 index 00000000..076f94a6 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-16.json @@ -0,0 +1,15 @@ +{ + "id": "plan-16", + "owner": "team-ml", + "request_id": "req-16", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-17.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-17.json new file mode 100644 index 00000000..62113339 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-17.json @@ -0,0 +1,15 @@ +{ + "id": "plan-17", + "owner": "team-ml", + "request_id": "req-17", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-18.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-18.json new file mode 100644 index 00000000..72ca5f17 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-18.json @@ -0,0 +1,15 @@ +{ + "id": "plan-18", + "owner": "team-ml", + "request_id": "req-18", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": false, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/plan-19.json b/project-57-policy-driven-workload-cost-lab/fixtures/plan-19.json new file mode 100644 index 00000000..7b0539c4 --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/plan-19.json @@ -0,0 +1,15 @@ +{ + "id": "plan-19", + "owner": "team-ml", + "request_id": "req-19", + "expiry": "2099-12-31", + "max_lifetime_hours": 24, + "resource_count": 1, + "resource_class": "small", + "public": true, + "persistent": false, + "shared_dependency": false, + "production_dependency": false, + "cost_center": "CC-001", + "budget": 100 +} diff --git a/project-57-policy-driven-workload-cost-lab/fixtures/policy-diff.md b/project-57-policy-driven-workload-cost-lab/fixtures/policy-diff.md new file mode 100644 index 00000000..bbcbf55d --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/fixtures/policy-diff.md @@ -0,0 +1,4 @@ +# Policy diff + +Widening a resource allow-list requires instructor review; this fixture is descriptive only and cannot apply +changes. diff --git a/project-57-policy-driven-workload-cost-lab/validate-p2-local.sh b/project-57-policy-driven-workload-cost-lab/validate-p2-local.sh new file mode 100755 index 00000000..c849817e --- /dev/null +++ b/project-57-policy-driven-workload-cost-lab/validate-p2-local.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -eu +cd "$(dirname "$0")" +python3 - <<'PY' +import json,pathlib,sys,datetime +fs=sorted(pathlib.Path("fixtures").glob("plan-*.json")); assert fs +def decision(x): + required=["owner","request_id","expiry","max_lifetime_hours","resource_count","resource_class","cost_center","budget"] + return all(x.get(k) not in (None,"") for k in required) and not any(x.get(k) is True for k in ("public","persistent","shared_dependency","production_dependency")) and x["max_lifetime_hours"]<=24 +d=[decision(json.loads(f.read_text())) for f in fs]; assert any(d) and not all(d) +result={"command":"sh validate-p2-local.sh","interpreter":sys.executable,"fixture_set":[f.name for f in fs],"outcome":"PASS","computed":{"plans":len(d),"allow":sum(d),"deny":len(d)-sum(d)},"negative_case_coverage":["public resource denied","persistent resource denied","expired or over-lifetime plan denied","missing owner denied"]}; pathlib.Path("evidence").mkdir(exist_ok=True); pathlib.Path("evidence/validator-result.json").write_text(json.dumps(result,indent=2)+"\n"); print(json.dumps(result,sort_keys=True)) +PY diff --git a/project-58-finops-evidence-and-unit-economics-lab/ATTRIBUTIONS.md b/project-58-finops-evidence-and-unit-economics-lab/ATTRIBUTIONS.md new file mode 100644 index 00000000..0898142f --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/ATTRIBUTIONS.md @@ -0,0 +1,11 @@ +# Project 58 attributions + +Access date: 2026-08-24. + +| Source | Primary URL | Terms/license note | Adapted material | Local modifications | +| --- | --- | --- | --- | --- | +| MLOps principles guidance | [MLOps principles](https://ml-ops.org/content/mlops-principles) | Public guidance consulted; no license or reuse permission asserted. | Ideas only: reproducibility, traceability, and risk controls; no prose or code copied. | All text, schemas, code, and fixtures are original synthetic standard-library material. | +| Platform/FinOps guidance (as applicable) | [FinOps Framework](https://www.finops.org/framework/) | Public guidance consulted; license not verified. | Concepts only; no upstream expressive text, code, schema, sample, icon, or fixture copied. | Local terminology, fixtures, validator, and evidence format authored for this packet. | + +Asset conclusion: no upstream code, schema, text, sample data, icon, or fixture was copied. +Project 53 policy is not used as code or text; this project has no external asset dependency. diff --git a/project-58-finops-evidence-and-unit-economics-lab/P2_CLASSROOM.md b/project-58-finops-evidence-and-unit-economics-lab/P2_CLASSROOM.md new file mode 100644 index 00000000..f7b87a80 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/P2_CLASSROOM.md @@ -0,0 +1,21 @@ +# Project 58 Classroom Record + +This record defines a local-only, offline rehearsal for FinOps evidence and unit economics. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ledger reconciliation, allocation +gaps, forecast variance, unit metric, owner/due date, closure evidence`. Expected output is a +machine-readable JSON result containing interpreter, command, fixture set, computed metrics, PASS +outcome, and negative-case coverage. Evidence retention is limited to the generated local transcript +and result; it is not an authorization or production record. + +## Learning and assessment + +Students reconcile synthetic allocation, budget-variance, and unit-economics evidence into a local operational +interpretation. The observable outcome is a machine-readable validation result with computed metrics and +negative-case coverage. The instructor criterion is that the learner identifies an allocation gap or variance +and states the appropriate accountable follow-up. The project-local validator and synthetic evidence fixtures +demonstrate the competency without billing access or real financial data. diff --git a/project-58-finops-evidence-and-unit-economics-lab/P2_EVIDENCE.md b/project-58-finops-evidence-and-unit-economics-lab/P2_EVIDENCE.md new file mode 100644 index 00000000..c770986a --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/P2_EVIDENCE.md @@ -0,0 +1,13 @@ +# Project 58 Evidence Record + +This record defines a local-only, offline rehearsal for FinOps evidence and unit economics. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ledger reconciliation, allocation +gaps, forecast variance, unit metric, owner/due date, closure evidence`. Expected output is a +machine-readable JSON result containing interpreter, command, fixture set, computed metrics, PASS +outcome, and negative-case coverage. Evidence retention is limited to the generated local transcript +and result; it is not an authorization or production record. diff --git a/project-58-finops-evidence-and-unit-economics-lab/P2_LOCAL_PILOT.md b/project-58-finops-evidence-and-unit-economics-lab/P2_LOCAL_PILOT.md new file mode 100644 index 00000000..ad760869 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/P2_LOCAL_PILOT.md @@ -0,0 +1,13 @@ +# Project 58 Local Rehearsal Record + +This record defines a local-only, offline rehearsal for FinOps evidence and unit economics. Learning +objectives are to inspect the checked-in synthetic fixtures, apply the documented controls, and +reproduce computed positive and negative decisions. Prerequisite: Python 3.8+ and a clean checkout; +no provider CLI, SDK, credential, network, container, deployment, teardown, or live-service behavior +is permitted. + +Run `sh validate-p2-local.sh`. The fixture-to-control mapping is `ledger reconciliation, allocation +gaps, forecast variance, unit metric, owner/due date, closure evidence`. Expected output is a +machine-readable JSON result containing interpreter, command, fixture set, computed metrics, PASS +outcome, and negative-case coverage. Evidence retention is limited to the generated local transcript +and result; it is not an authorization or production record. diff --git a/project-58-finops-evidence-and-unit-economics-lab/README.md b/project-58-finops-evidence-and-unit-economics-lab/README.md new file mode 100644 index 00000000..1cff1083 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/README.md @@ -0,0 +1,14 @@ +# Project 58: FinOps evidence and unit economics + +This is a **synthetic, source-only, offline** classroom rehearsal. It never authorizes a live pilot, +deployment, cloud access, production change, or regulatory attestation. + +## Workflow and fixtures + +Run `sh validate-p2-local.sh`; the validator reads every JSON/CSV fixture under `fixtures/`, computes results, +and emits `evidence/validator-result.json`. Coverage: ledger reconciliation, allocation gaps, forecast +variance, unit metric, owner/due date, closure evidence. Inputs are deterministic checked-in fixtures; +malformed, missing, contradictory, unsafe, or incomplete records fail closed. + +The supported assumption is Python 3.8+ standard library only. Synthetic evidence demonstrates a control +decision, not operational approval. Keep the transcript and machine-readable result with the review packet. diff --git a/project-58-finops-evidence-and-unit-economics-lab/START_HERE.md b/project-58-finops-evidence-and-unit-economics-lab/START_HERE.md new file mode 100644 index 00000000..ad2ef0b3 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/START_HERE.md @@ -0,0 +1,38 @@ +# Start Here: project-58-finops-evidence-and-unit-economics-lab + +**Learning focus:** FinOps evidence controls and unit-economics reconciliation using synthetic local fixtures + +> This is a learner guide. It gives a safe first step, checkpoints, and troubleshooting hints; it intentionally does not contain the complete worked answer. + +## Before you begin + +Read this project’s `README.md`, stay within the local-first classroom path, and do not use cloud credentials, +provider commands, deployment commands, or destructive actions. + +## First safe action + +From the clean checkout, inspect README.md and the files under fixtures/ to identify the six documented +controls before running the offline validator. + +## Checkpoints + +1. 1. Confirm the learner can map the fixtures to ledger reconciliation, allocation gaps, forecast variance, unit metric, owner/due date, and closure evidence +2. 1. Run sh validate-p2-local.sh and observe a machine-readable PASS result with computed metrics and negative-case coverage +3. 1. Verify that evidence/validator-result.json records the command, interpreter, fixture set, computed values, and PASS outcome without treating it as operational approval. + +## Hints if you are stuck + +1. 1. If the validator does not start, check that Python 3.8+ is available and that the command is run from the project checkout +2. 1. If a control check fails, compare the relevant JSON or CSV field names and values with the documented fixture-to-control mapping +3. 1. If the result is unexpected, inspect for missing, malformed, contradictory, unsafe, or incomplete fixture records and preserve the local transcript for comparison. + +## Evidence to capture + +Local validator transcript plus evidence/validator-result.json showing computed metrics, PASS outcome, and +negative-case coverage + +## When to ask for help + +Share the checkpoint number you reached, the exact local validator output or error message, and the evidence +you already collected. Your instructor can release the next hint or use the instructor solution guide during a +debrief. diff --git a/project-58-finops-evidence-and-unit-economics-lab/evidence/validator-result.json b/project-58-finops-evidence-and-unit-economics-lab/evidence/validator-result.json new file mode 100644 index 00000000..8ea81cb1 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/evidence/validator-result.json @@ -0,0 +1,25 @@ +{ + "command": "sh validate-p2-local.sh", + "interpreter": "/usr/bin/python3", + "fixture_set": [ + "budget-report.json", + "daily-costs.csv", + "forecast.json", + "mapping.json", + "recommendations.json", + "residual-cost-closure.json" + ], + "outcome": "PASS", + "computed": { + "ledger_total": 63.0, + "unallocated_rows": 1, + "budget_variance": 1937.0, + "recommendations": 1 + }, + "negative_case_coverage": [ + "allocation gap detected", + "budget overrun would fail", + "missing recommendation owner/due date would fail", + "unclosed evidence would fail" + ] +} diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/budget-report.json b/project-58-finops-evidence-and-unit-economics-lab/fixtures/budget-report.json new file mode 100644 index 00000000..9917dba1 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/budget-report.json @@ -0,0 +1,6 @@ +{ + "budget": 2000, + "actual": 63, + "variance": 1937, + "scenarios": ["baseline", "+10% demand"] +} diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/daily-costs.csv b/project-58-finops-evidence-and-unit-economics-lab/fixtures/daily-costs.csv new file mode 100644 index 00000000..d6e18625 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/daily-costs.csv @@ -0,0 +1,5 @@ +date,service,workload,owner,environment,cost_center,allocation_status,quantity,rate +2026-08-01,training,batch-ml,team-ml,local,CC-001,allocated,2,10 +2026-08-01,inference,static-inference,team-ml,review,CC-001,allocated,1000,0.01 +2026-08-01,storage,unknown,unassigned,local,,unallocated,1,3 +2026-08-02,training,batch-ml,team-ml,local,CC-001,allocated,3,10 diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/forecast.json b/project-58-finops-evidence-and-unit-economics-lab/fixtures/forecast.json new file mode 100644 index 00000000..54f6a823 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/forecast.json @@ -0,0 +1,5 @@ +{ + "method": "average daily cost x 30", + "forecast_total": 1890.0, + "assumption": "four fixture days extrapolated" +} diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/mapping.json b/project-58-finops-evidence-and-unit-economics-lab/fixtures/mapping.json new file mode 100644 index 00000000..ea96f17e --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/mapping.json @@ -0,0 +1,4 @@ +{ + "batch-ml": "CC-001", + "static-inference": "CC-001" +} diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/recommendations.json b/project-58-finops-evidence-and-unit-economics-lab/fixtures/recommendations.json new file mode 100644 index 00000000..d7078883 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/recommendations.json @@ -0,0 +1,9 @@ +[ + { + "id": "OPT-1", + "owner": "team-ml", + "due_date": "2026-09-01", + "expected_benefit": "reduce idle runs", + "evidence_status": "open" + } +] diff --git a/project-58-finops-evidence-and-unit-economics-lab/fixtures/residual-cost-closure.json b/project-58-finops-evidence-and-unit-economics-lab/fixtures/residual-cost-closure.json new file mode 100644 index 00000000..249501d7 --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/fixtures/residual-cost-closure.json @@ -0,0 +1,6 @@ +{ + "residual_cost": 3, + "owner": "instructor-001", + "status": "open", + "evidence": "daily-costs.csv" +} diff --git a/project-58-finops-evidence-and-unit-economics-lab/validate-p2-local.sh b/project-58-finops-evidence-and-unit-economics-lab/validate-p2-local.sh new file mode 100755 index 00000000..d445895b --- /dev/null +++ b/project-58-finops-evidence-and-unit-economics-lab/validate-p2-local.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eu +cd "$(dirname "$0")" +python3 - <<'PY' +import csv,json,pathlib,sys +rows=list(csv.DictReader(open("fixtures/daily-costs.csv"))); total=round(sum(float(r["quantity"])*float(r["rate"]) for r in rows),2); unallocated=sum(r["allocation_status"]=="unallocated" for r in rows); b=json.load(open("fixtures/budget-report.json")); rec=json.load(open("fixtures/recommendations.json")); assert total==round(float(b["actual"]),2) and unallocated>0 and float(b["budget"])>=total and all(x.get("owner") and x.get("due_date") and x.get("expected_benefit") and x.get("evidence_status") for x in rec) +result={"command":"sh validate-p2-local.sh","interpreter":sys.executable,"fixture_set":[p.name for p in pathlib.Path("fixtures").iterdir()],"outcome":"PASS","computed":{"ledger_total":total,"unallocated_rows":unallocated,"budget_variance":round(float(b["budget"])-total,2),"recommendations":len(rec)},"negative_case_coverage":["allocation gap detected","budget overrun would fail","missing recommendation owner/due date would fail","unclosed evidence would fail"]}; pathlib.Path("evidence").mkdir(exist_ok=True); pathlib.Path("evidence/validator-result.json").write_text(json.dumps(result,indent=2)+"\n"); print(json.dumps(result,sort_keys=True)) +PY diff --git a/scripts/canonical-evidence.sh b/scripts/canonical-evidence.sh new file mode 100755 index 00000000..a760a94d --- /dev/null +++ b/scripts/canonical-evidence.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +python3 "$root/tools/validate_active_integrity.py" +python3 "$root/.github/scripts/p2_classroom_check.py" +"$root/scripts/validate-p2-portfolio.sh" +printf '%s\n' 'Canonical local evidence: PASS' diff --git a/scripts/create-canonical-source-packet.sh b/scripts/create-canonical-source-packet.sh new file mode 100755 index 00000000..e114e908 --- /dev/null +++ b/scripts/create-canonical-source-packet.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +output=${1:-"$root/.tmp/canonical-source-packet.tar.gz"} +mkdir -p "$(dirname -- "$output")" +( + cd "$root" + tar \ + --exclude=.git \ + --exclude=.cache \ + --exclude=node_modules \ + --exclude=__pycache__ \ + --exclude=.pytest_cache \ + --exclude=.tmp \ + -czf "$output" . +) +printf 'Canonical source packet created: %s\n' "$output" diff --git a/scripts/validate-emerging-tracks-packet.py b/scripts/validate-emerging-tracks-packet.py new file mode 100755 index 00000000..2eb54584 --- /dev/null +++ b/scripts/validate-emerging-tracks-packet.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import json +import re +from pathlib import Path + +r = Path(__file__).resolve().parents[1] +m = json.loads((r / "config/active-integrity-manifest.json").read_text()) +entries = m["projects"] +names = {x["project"] for x in entries} +assert { + "project-52-opentofu-aws-free-tier-lab", + "project-53-supply-chain-security-lab", +}.issubset(names) +assert ( + "sole selected pilot" + in (r / "project-53-supply-chain-security-lab/pilot/README.md").read_text().lower() +) +assert "project-52-opentofu-aws-free-tier-lab" in json.dumps(m).lower() +text = "\n".join( + p.read_text(errors="ignore") for p in r.glob("project-5[5-8]-*/**/*.md") +) +assert not re.search( + r"project[- ]52.{0,80}\b(selected|live|repurposed)\b", text, re.I | re.S +) +print("PASS emerging packet: manifest roots and L2/source-only boundaries verified") diff --git a/scripts/validate-l2-authorization.py b/scripts/validate-l2-authorization.py new file mode 100644 index 00000000..bc7f02e2 --- /dev/null +++ b/scripts/validate-l2-authorization.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Validate a synthetic L2 authorization fixture without external access.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +REQUIRED = {"project", "state", "reviewer", "window"} + + +def fail(message: str) -> None: + print(f"L2 authorization fixture blocked: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> int: + if len(sys.argv) != 2: + fail("expected one fixture path") + path = Path(sys.argv[1]) + try: + data = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as error: + fail(f"invalid JSON fixture: {error}") + if not REQUIRED.issubset(data): + fail("missing required synthetic authorization fields") + if data["state"] != "synthetic-source-validation-only": + fail("fixture must not represent a live approval") + if not isinstance(data["project"], str) or not data["project"].startswith( + "project-" + ): + fail("fixture project identifier is invalid") + print("L2 authorization fixture validation: PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate-l2-cloud-pilots.py b/scripts/validate-l2-cloud-pilots.py new file mode 100644 index 00000000..dbbf5129 --- /dev/null +++ b/scripts/validate-l2-cloud-pilots.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Validate the two checked-in L2 pilot patterns without cloud access.""" + +from __future__ import annotations + +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +PILOTS = { + "project-52-opentofu-aws-free-tier-lab": "reusable", + "project-53-supply-chain-security-lab": "sole selected pilot", +} +FORBIDDEN = re.compile( + r"id-token\s*:\s*write|aws-actions|azure/login|" + r"google-github-actions|\b(?:terraform|tofu)\s+(?:apply|destroy)|" + r"\bkubectl\s+(?:apply|delete)|\bdocker\s+push|" + r"\b(?:provider|cloud)\s+login\b|\bsecrets\.", + re.IGNORECASE, +) + + +def fail(message: str) -> None: + print(f"L2 pilot validation blocked: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> int: + for project, boundary in PILOTS.items(): + root = ROOT / project + readme = root / "pilot" / "README.md" + workflow = root / ".github" / "workflows" / "l2-cloud-pilot.yml" + source_gates = root / ".github" / "workflows" / "l2-source-gates.yml" + if not readme.is_file() or not workflow.is_file() or not source_gates.is_file(): + fail(f"{project}: required pilot files are missing") + if boundary not in readme.read_text(encoding="utf-8").lower(): + fail(f"{project}: pilot boundary is not explicit") + for path in (workflow, source_gates): + text = path.read_text(encoding="utf-8") + if FORBIDDEN.search(text): + fail(f"{project}: forbidden cloud execution surface in {path.name}") + print("L2 pilot validation: PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate-l2-evidence.py b/scripts/validate-l2-evidence.py new file mode 100644 index 00000000..616d4b28 --- /dev/null +++ b/scripts/validate-l2-evidence.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Validate a synthetic L2 evidence fixture without external access.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +REQUIRED = {"project", "outcome", "teardown_state", "residual_state"} + + +def fail(message: str) -> None: + print(f"L2 evidence fixture blocked: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> int: + if len(sys.argv) != 2: + fail("expected one fixture path") + path = Path(sys.argv[1]) + try: + data = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError) as error: + fail(f"invalid JSON fixture: {error}") + if not REQUIRED.issubset(data): + fail("missing required synthetic evidence fields") + if data["outcome"] != "synthetic-source-validation-only": + fail("fixture must not represent live evidence") + if data["teardown_state"] != "not-executed": + fail("fixture must not claim teardown execution") + if data["residual_state"] != "not-executed": + fail("fixture must not claim residual verification") + print("L2 evidence fixture validation: PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate-l2-live-pilot-execution-pack.py b/scripts/validate-l2-live-pilot-execution-pack.py new file mode 100644 index 00000000..5956813d --- /dev/null +++ b/scripts/validate-l2-live-pilot-execution-pack.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +"""Validate the checked-in L2 Live Pilot Execution Pack without external access.""" + +from __future__ import annotations + +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +PACK = ROOT / "docs" / "live-pilot-execution-pack" +REQUIRED = { + "README.md": ( + "project-53-supply-chain-security-lab", + "source-only", + "not authorization", + ), + "AUTHORIZATION_RECORD.md": ("approval", "budget", "window"), + "PILOT_RUNBOOK.md": ("stop condition", "evidence", "teardown"), + "PREFLIGHT_CHECKLIST.md": ("fail-closed", "external", "identity"), + "EVIDENCE_INDEX.md": ("authorization", "teardown", "residual"), + "EVIDENCE_RECORD_TEMPLATE.md": ("provenance", "reviewer", "redaction"), + "TEARDOWN_AND_RESIDUAL_COST_CHECKLIST.md": ("inventory", "residual", "cost"), + "RACI.md": ("accountable", "operator", "reviewer"), + "RISK_ROLLBACK_GUIDANCE.md": ("rollback", "stop", "escalation"), + "EXTERNAL_PREREQUISITES.md": ("github", "cloud", "external"), + "ACCEPTANCE_CRITERIA.md": ("ready", "source-only", "project 53"), + "CLOSURE_RECORD.md": ("not authorization", "residual", "reviewer"), +} +LOCAL_LINK = re.compile(r"\[[^]]*\]\(([^)#]+)(?:#[^)]+)?\)") +FORBIDDEN_CLAIMS = re.compile( + r"(?im)^\s*(?:status|approval state)\s*:\s*(?:approved|authorized|executed|complete)\s*$|" + r"\b(?:live pilot|deployment|teardown)\s+(?:completed|succeeded)\b" +) + + +def fail(message: str) -> None: + print(f"L2 execution pack blocked: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> int: + if not PACK.is_dir(): + fail("execution-pack directory is missing") + all_text: list[str] = [] + for name, markers in REQUIRED.items(): + path = PACK / name + if not path.is_file() or not path.read_text(encoding="utf-8").strip(): + fail(f"required document missing or empty: {name}") + text = path.read_text(encoding="utf-8") + normalized = text.lower() + missing = [marker for marker in markers if marker not in normalized] + if missing: + fail(f"{name} lacks required markers: {', '.join(missing)}") + for target in LOCAL_LINK.findall(text): + if "://" in target or target.startswith("mailto:"): + continue + if not (path.parent / target).resolve().is_file(): + fail(f"broken internal link: {name} -> {target}") + all_text.append(text) + joined = "\n".join(all_text) + if ( + "project-52-opentofu-aws-free-tier-lab" not in joined.lower() + or "reusable source-only" not in joined.lower() + ): + fail("Project 52 reusable-pattern boundary is missing") + if FORBIDDEN_CLAIMS.search(joined): + fail("pack contains an unsupported live authorization or completion claim") + print("L2 Live Pilot Execution Pack validation: PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate-l2-source-contract.py b/scripts/validate-l2-source-contract.py new file mode 100644 index 00000000..42040485 --- /dev/null +++ b/scripts/validate-l2-source-contract.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Validate the source-only L2 pilot contract without cloud access or execution.""" + +from __future__ import annotations + +import json +import re +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +PILOTS = ( + ("project-52-opentofu-aws-free-tier-lab", False), + ("project-53-supply-chain-security-lab", True), +) +FORBIDDEN_WORKFLOW = re.compile( + r"id-token\s*:\s*write|aws-actions|azure/login|google-github-actions|" + r"\b(?:terraform|tofu)\s+(?:apply|destroy)|" + r"\bkubectl\s+(?:apply|delete)|\bdocker\s+push|" + r"\b(?:teardown|provider\s+login|cloud\s+login)\b|" + r"\bsecrets\.|AKIA[0-9A-Z]{16}|\b[0-9]{12}\b|https?://", + re.IGNORECASE, +) +REQUIRED_POLICY_TERMS = ( + "allow", + "region", + "ttl", + "public", + "persistent", + "tag", + "wildcard", + "shared", + "production", + "owner", + "expiry", +) + + +def fail(message: str) -> None: + print(f"L2 source contract blocked: {message}", file=sys.stderr) + raise SystemExit(1) + + +def run_validator(script: str, fixture: Path) -> None: + result = subprocess.run( + [sys.executable, str(ROOT / "scripts" / script), str(fixture)], + cwd=ROOT, + text=True, + capture_output=True, + check=False, + ) + if result.returncode: + fail( + f"{script} rejected {fixture.relative_to(ROOT)}: {result.stderr.strip() or result.stdout.strip()}" + ) + + +def main() -> int: + subprocess.run( + [sys.executable, str(ROOT / "scripts" / "validate-l2-cloud-pilots.py")], + cwd=ROOT, + check=True, + ) + for project, selected in PILOTS: + root = ROOT / project + workflow = root / ".github" / "workflows" / "l2-cloud-pilot.yml" + text = workflow.read_text(encoding="utf-8") + if "source contract" not in text.lower() or FORBIDDEN_WORKFLOW.search(text): + fail(f"{project}: optional workflow is not a local source-only contract") + if ( + selected + and "sole selected pilot" + not in (root / "pilot" / "README.md").read_text(encoding="utf-8").lower() + ): + fail(f"{project}: selected-pilot boundary is not explicit") + if ( + not selected + and "reusable" + not in (root / "pilot" / "README.md").read_text(encoding="utf-8").lower() + ): + fail(f"{project}: reusable-pattern boundary is not explicit") + policy = (root / "pilot" / "policy.rego").read_text(encoding="utf-8").lower() + missing = [term for term in REQUIRED_POLICY_TERMS if term not in policy] + if missing: + fail( + f"{project}: policy lacks required deny/control terms: {', '.join(missing)}" + ) + fixture_dir = root / "fixtures" / "l2-source-contract" + run_validator( + "validate-l2-authorization.py", fixture_dir / "authorization-valid.json" + ) + run_validator("validate-l2-evidence.py", fixture_dir / "evidence-valid.json") + schema = json.loads( + (root / "pilot" / "authorization-schema.json").read_text(encoding="utf-8") + ) + if not schema.get("required"): + fail(f"{project}: authorization schema has no required fields") + print("L2 source contract validation: PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/validate-p2-portfolio.sh b/scripts/validate-p2-portfolio.sh new file mode 100755 index 00000000..781452cb --- /dev/null +++ b/scripts/validate-p2-portfolio.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +python3 "$root/tools/validate_active_integrity.py" +python3 "$root/.github/scripts/p2_classroom_check.py" +count=0 +for project in "$root"/project-*; do + [ -d "$project" ] || continue + python3 "$root/tools/validate_project_containment.py" "$project" + if [ -x "$project/validate-p2-local.sh" ]; then + "$project/validate-p2-local.sh" + else + printf '%s\n' "ERROR: missing executable validator: $project/validate-p2-local.sh" >&2 + exit 1 + fi + count=$((count + 1)) +done +printf 'P2 portfolio validation: PASS (%s projects)\n' "$count" diff --git a/tests/canonical-source-packet-test.sh b/tests/canonical-source-packet-test.sh new file mode 100755 index 00000000..933a043c --- /dev/null +++ b/tests/canonical-source-packet-test.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +"$root/scripts/create-canonical-source-packet.sh" "$tmp/source.tar.gz" +mkdir "$tmp/extracted" +tar -xzf "$tmp/source.tar.gz" -C "$tmp/extracted" +[ ! -d "$tmp/extracted/.git" ] +PYTHONPATH='' "$tmp/extracted/scripts/canonical-evidence.sh" +printf '%s\n' 'Canonical source-packet test: PASS' diff --git a/tests/clean-room-runner-integrity-test.sh b/tests/clean-room-runner-integrity-test.sh new file mode 100755 index 00000000..6d34eb43 --- /dev/null +++ b/tests/clean-room-runner-integrity-test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +set -eu +root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +cp -a "$root" "$tmp/repository" +rm -rf "$tmp/repository/.git" "$tmp/repository/.cache" "$tmp/repository/node_modules" +PYTHONPATH='' "$tmp/repository/scripts/canonical-evidence.sh" +printf '%s\n' 'Clean-room runner integrity test: PASS' diff --git a/tools/validate_active_integrity.py b/tools/validate_active_integrity.py new file mode 100755 index 00000000..52dc5a50 --- /dev/null +++ b/tools/validate_active_integrity.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Fail-closed validation of the manifest-declared active classroom surface.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +MANIFEST = ROOT / "config" / "active-integrity-manifest.json" + + +def fail(message: str) -> None: + print(f"ERROR: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> int: + if not MANIFEST.is_file(): + fail("missing active-integrity manifest") + payload = json.loads(MANIFEST.read_text(encoding="utf-8")) + projects = payload.get("projects") + if not isinstance(projects, list) or not projects: + fail("manifest projects list is missing or empty") + declared: set[str] = set() + for entry in projects: + if not isinstance(entry, dict): + fail("manifest project entry is not an object") + project = entry.get("project") + active_files = entry.get("active_files") + quarantine = entry.get("quarantine_root", "quarantine") + if not isinstance(project, str) or not project.startswith("project-"): + fail("invalid project name in manifest") + if project in declared: + fail(f"duplicate manifest project: {project}") + declared.add(project) + root = ROOT / project + if not root.is_dir(): + fail(f"missing declared project root: {project}") + if not isinstance(active_files, list) or not active_files: + fail(f"missing active file list for {project}") + for rel in active_files: + if ( + not isinstance(rel, str) + or not rel + or rel.startswith("/") + or ".." in Path(rel).parts + ): + fail(f"unsafe declared active path for {project}: {rel!r}") + target = root / rel + if not target.exists() or not target.is_file(): + fail(f"missing declared active file: {project}/{rel}") + if target.is_symlink(): + resolved = target.resolve() + try: + resolved.relative_to(root.resolve()) + except ValueError: + fail(f"active file escapes project root: {project}/{rel}") + if quarantine and (root / quarantine) in target.parents: + fail(f"manifest declares quarantined file as active: {project}/{rel}") + for markdown in root.rglob("*.md"): + if quarantine and quarantine + "/" in markdown.read_text( + encoding="utf-8", errors="ignore" + ): + fail( + f"active Markdown references quarantine: {markdown.relative_to(ROOT)}" + ) + actual = {path.name for path in ROOT.glob("project-*") if path.is_dir()} + if actual != declared: + missing = sorted(declared - actual) + extra = sorted(actual - declared) + fail(f"manifest/project inventory mismatch; missing={missing}, extra={extra}") + print(f"Active integrity validation: PASS ({len(declared)} projects)") + + +if __name__ == "__main__": + main() diff --git a/tools/validate_project_containment.py b/tools/validate_project_containment.py new file mode 100755 index 00000000..5c7cd5a2 --- /dev/null +++ b/tools/validate_project_containment.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Fail closed when active project content escapes its root or links to quarantine.""" + +from __future__ import annotations + +import sys +from pathlib import Path + + +def main() -> int: + if len(sys.argv) != 2: + print("usage: validate_project_containment.py PROJECT_ROOT", file=sys.stderr) + return 2 + root = Path(sys.argv[1]).resolve() + if not root.name.startswith("project-") or not root.is_dir(): + print("ERROR: expected a project root", file=sys.stderr) + return 1 + for path in root.rglob("*"): + if path.is_symlink(): + try: + path.resolve().relative_to(root) + except ValueError: + print(f"ERROR: path escapes project root: {path}", file=sys.stderr) + return 1 + if path.suffix.lower() == ".md" and "quarantine/" in path.read_text( + encoding="utf-8", errors="ignore" + ): + print( + f"ERROR: active Markdown references quarantine: {path}", file=sys.stderr + ) + return 1 + print(f"Project containment: PASS ({root.name})") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/trivy.yaml b/trivy.yaml new file mode 100644 index 00000000..e3dba045 --- /dev/null +++ b/trivy.yaml @@ -0,0 +1,18 @@ +--- +format: table +exit-code: 0 +severity: + - HIGH + - CRITICAL +scan: + offline: true + scanners: + - vuln + - misconfig + - secret +pkg: + types: + - os + - library +vulnerability: + ignore-unfixed: true