From d9878548be4a2543b54aee17e1a60c04c5874cc0 Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:37:27 +0100 Subject: [PATCH 1/7] Document actual AWS provider drift execution with precise proof boundary --- content/projects/driftguard.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/content/projects/driftguard.md b/content/projects/driftguard.md index f452c5c..aac7ac1 100644 --- a/content/projects/driftguard.md +++ b/content/projects/driftguard.md @@ -77,6 +77,31 @@ The repository states the current gaps explicitly: These limitations are part of the engineering evidence. Hiding them would make the case study weaker, not stronger. +## Executed AWS drift proof — September 18, 2026 + +The repository also has an [actual AWS-backed GitHub Actions execution](https://github.com/EdwinJdevops/driftguard/actions/runs/35343278654), separate from the inventory-failure unit tests. + +That completed run used temporary AWS credentials and Terraform to create a disposable **AWS Systems Manager parameter**. It then changed the parameter through the AWS API outside Terraform, ran `terraform plan -refresh-only`, converted the resulting provider plan to a DriftGuard evidence bundle, verified sensitive values were omitted, and destroyed the test resource. + +The job logs recorded: + +```json +{ + "resource_address": "aws_ssm_parameter.proof", + "actions": ["update"], + "changed_paths": ["/value", "/version"], + "redaction_verified": true +} +``` + +The excerpt contains selected fields from the run's output, **not a claim that the exact JSON object above is a separately published artifact**. The run concluded successfully, including the cleanup step that checked the disposable parameter no longer existed. + +**What it establishes:** one real Terraform AWS provider refresh, one deliberately introduced out-of-band parameter change, successful evidence generation and value redaction, and cleanup under the tested environment. + +**What it does not establish:** that the entire FastAPI collector successfully scans live multi-account infrastructure, that every AWS resource type is supported end to end, or that production scheduling, throughput and recovery guarantees exist. In particular, the SSM parameter exercised the *provider-native evidence path*; it is not proof of the application's separate EC2/S3/RDS inventory collection. + +[Examine the executed AWS workflow and its logs](https://github.com/EdwinJdevops/driftguard/actions/runs/35343278654). + ## Failure case: incomplete AWS inventory An AWS collector that fails midway through enumeration must not return an empty resource list. An empty result can mean "no resources exist", while an exception or partial API response means "the system does not know". Conflating those states can produce false deletion findings. From 5db5368dfb12857e63e2c9ae413fbfa8f6212692 Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:37:52 +0100 Subject: [PATCH 2/7] Feature executed AWS provider proof alongside DriftGuard failure regression --- layouts/index.html | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/layouts/index.html b/layouts/index.html index f37b070..aafd207 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -64,14 +64,20 @@

{{ .Title }}

DriftGuard's AWS collector could not safely treat an incomplete inventory as an empty account. A missed resource and an unknown result have different meanings.

-

MERGED CODE / REGRESSION COVERAGE

+

01 / EXECUTED AWS PROVIDER DRIFT

+

An out-of-band AWS change, detected and redacted.

+

A successful GitHub Actions run created a disposable AWS Systems Manager parameter with Terraform, changed it outside Terraform, detected the change using a refresh-only plan, and verified a redacted evidence record before cleanup.

+ Examine actual AWS execution logs ↗ +
+
-

This is a public project implementation, not a client testimonial. The tests establish the specified failure behavior—not a production availability guarantee.

+

This is public engineering evidence, not a client testimonial. The AWS proof exercises a bounded provider-native workflow; PR #3 tests inventory-failure handling. Neither constitutes a production availability guarantee.

Full DriftGuard case study ↗
From d5bc17c64c3b79f8d4a983905156055597623769 Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:38:13 +0100 Subject: [PATCH 3/7] Document CV-backed Azure Fundamentals and completed ALX training without inventing verification links --- layouts/portfolio/list.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/layouts/portfolio/list.html b/layouts/portfolio/list.html index 28fdfc1..e161114 100644 --- a/layouts/portfolio/list.html +++ b/layouts/portfolio/list.html @@ -39,6 +39,24 @@

About the work.

06 / SECURITY

OIDC · IAM/RBAC · Scanning

Permission boundaries, Trivy, Kubescape, Falco and reviewable remediation proposals.

+
+
+

CREDENTIALS / STRUCTURED TRAINING

Education and certification.

+
+
+
+

MICROSOFT / FUNDAMENTALS

+

Microsoft Certified: Azure Fundamentals (AZ-900)

+

Certification reported as earned in my CV. A public credential-verification link has not yet been added.

+
+
+

ALX AFRICA / COMPLETED PROGRAMME

+

Cloud DevOps Engineering Programme

+

Completed project-based training in cloud infrastructure, Linux, containers, CI/CD and infrastructure as code, with team-coordination responsibilities.

+
+
+

These entries reflect my declared CV record; they are not presented as independently authenticated issuer records. No Cisco certification or uncompleted exam is listed here.

+

PROFESSIONAL EXPERIENCE

Work and responsibilities.

Discuss a role ↗
    From 27cdcd6c8cb791b2bfc5deae0e1606a3a45dac08 Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:38:47 +0100 Subject: [PATCH 4/7] Reduce old portrait prominence and style factual credential entries --- static/css/main.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/static/css/main.css b/static/css/main.css index 0e8b5a8..6dadfc7 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -638,3 +638,18 @@ a:focus-visible,summary:focus-visible{outline:3px solid var(--accent);outline-of .work-research-list article>.editorial-read{margin-top:10px} .home-availability{font-size:12px} } + +/* Credentials: factual, non-decorative CV record with clear validation boundary. */ +.profile-credentials{border-top:1px solid var(--line)} +.credential-entries{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0;border-top:1px solid var(--line);border-left:1px solid var(--line)} +.credential-entries article{min-width:0;padding:25px;border-right:1px solid var(--line);border-bottom:1px solid var(--line)} +.credential-entries h3{font-size:clamp(22px,2.5vw,33px);font-weight:550;line-height:1.15;letter-spacing:-.045em;margin:16px 0} +.credential-entries article>p:last-child,.credential-source-note{font-size:13px;line-height:1.7;color:var(--muted)} +.credential-source-note{max-width:850px;margin-top:18px} +/* Retain the authentic portrait but let technical work, not an old photograph, dominate. */ +.home-portrait{width:min(100%,225px);max-width:225px;align-self:center;margin-inline:auto} +.home-portrait img{width:100%;height:auto;max-height:315px;aspect-ratio:4/5;object-fit:cover;object-position:center 22%;border-radius:3px} +.home-intro:has(.home-portrait) .infra-scene{min-height:290px} +@media(min-width:821px){.home-intro:has(.home-portrait){grid-template-columns:minmax(0,1fr) 235px}} +@media(max-width:820px){.home-portrait{width:175px;max-width:175px;margin:0}.home-portrait img{max-height:220px;aspect-ratio:4/5}.home-intro:has(.home-portrait) .infra-scene{min-height:280px}} +@media(max-width:640px){.credential-entries{grid-template-columns:1fr}.credential-entries article{padding:20px}} From 08133e05e578ead394acb592a0ec471be17ec20e Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:39:08 +0100 Subject: [PATCH 5/7] Verify live AWS proof, unlinked CV credentials and restrained portrait layout --- scripts/visual_audit.cjs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/visual_audit.cjs b/scripts/visual_audit.cjs index b65169d..67ca139 100644 --- a/scripts/visual_audit.cjs +++ b/scripts/visual_audit.cjs @@ -257,11 +257,20 @@ const fs = require("node:fs"); if (await introLink.count() !== 1) failures.push("About route missing from hero"); const homepageEmail = identity.locator('.footer-email[href^="mailto:edwinjonathanchibuike123@gmail.com"]').first(); if (await homepageEmail.count() !== 1) failures.push("Verified contact link missing from footer"); + const portraitWidth = await identity.locator(".home-portrait").evaluate(el => el.getBoundingClientRect().width); + if (portraitWidth > 230) + failures.push("Legacy portrait still dominates the homepage: "+viewport.width+"px viewport, "+portraitWidth+"px photo"); const homeOverflow = await identity.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); if (homeOverflow > 2) failures.push("Identity homepage overflow at "+viewport.width+"px: "+homeOverflow); await identity.goto("http://127.0.0.1:4173/portfolio/", {waitUntil:"domcontentloaded"}); if (await identity.locator(".tech-stack-grid > div").count() !== 6) failures.push("Expected six technical stack groups: "+viewport.width); + const credentialItems = identity.locator(".credential-entries article"); + if (await credentialItems.count() !== 2) + failures.push("Expected CV-recorded Microsoft and ALX entries: "+viewport.width); + const credentialText = await identity.locator(".profile-credentials").innerText(); + if (!credentialText.includes("Azure Fundamentals (AZ-900)") || !credentialText.includes("Cloud DevOps Engineering Programme") || !credentialText.includes("verification link")) + failures.push("Credentials or missing public-verification disclosure absent: "+viewport.width); if (await identity.locator(".career-timeline > li").count() !== 4) failures.push("Expected four CV-reported professional roles: "+viewport.width); const aboutText = await identity.locator(".profile-confidential").innerText(); @@ -278,8 +287,10 @@ const fs = require("node:fs"); const publicEvidence = await browser.newPage({ viewport, reducedMotion:"reduce" }); publicEvidence.on("pageerror", error => failures.push("Public evidence "+viewport.width+" JS exception: "+error.message)); await publicEvidence.goto("http://127.0.0.1:4173/", {waitUntil:"domcontentloaded"}); - if (await publicEvidence.locator(".public-record-grid article").count() !== 1) - failures.push("Only independent DriftGuard failure case should lead homepage: "+viewport.width); + if (await publicEvidence.locator(".public-record-grid article").count() !== 2) + failures.push("Both executed AWS drift proof and independent inventory regression must appear: "+viewport.width); + if (await publicEvidence.locator('.home-public-record a[href="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/EdwinJdevops/driftguard/actions/runs/35343278654"]').count() !== 1) + failures.push("Executed AWS provider evidence run missing: "+viewport.width); if (await publicEvidence.locator('.home-public-record a[href="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/EdwinJdevops/driftguard/pull/3"]').count() < 1) failures.push("Missing merged external DriftGuard PR evidence: "+viewport.width); const evidenceText = await publicEvidence.locator(".home-public-record").innerText(); From 7056275c5d765b678ab49cf2eef920e1692366ae Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:42:46 +0100 Subject: [PATCH 6/7] Resolve pa11y contrast regression from caption and highlighted evidence --- static/css/main.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/css/main.css b/static/css/main.css index 6dadfc7..00ac5fb 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -648,6 +648,7 @@ a:focus-visible,summary:focus-visible{outline:3px solid var(--accent);outline-of .credential-source-note{max-width:850px;margin-top:18px} /* Retain the authentic portrait but let technical work, not an old photograph, dominate. */ .home-portrait{width:min(100%,225px);max-width:225px;align-self:center;margin-inline:auto} +.home-portrait figcaption{background:#09131d;color:#fff} .home-portrait img{width:100%;height:auto;max-height:315px;aspect-ratio:4/5;object-fit:cover;object-position:center 22%;border-radius:3px} .home-intro:has(.home-portrait) .infra-scene{min-height:290px} @media(min-width:821px){.home-intro:has(.home-portrait){grid-template-columns:minmax(0,1fr) 235px}} From a173f5e6a7474ecd041e73c3f5b672af0f092f8d Mon Sep 17 00:00:00 2001 From: Edwin Jonathan Date: Sun, 11 Oct 2026 17:42:52 +0100 Subject: [PATCH 7/7] Resolve pa11y contrast regression from caption and highlighted evidence --- content/projects/driftguard.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/content/projects/driftguard.md b/content/projects/driftguard.md index aac7ac1..e83875d 100644 --- a/content/projects/driftguard.md +++ b/content/projects/driftguard.md @@ -83,18 +83,14 @@ The repository also has an [actual AWS-backed GitHub Actions execution](https:// That completed run used temporary AWS credentials and Terraform to create a disposable **AWS Systems Manager parameter**. It then changed the parameter through the AWS API outside Terraform, ran `terraform plan -refresh-only`, converted the resulting provider plan to a DriftGuard evidence bundle, verified sensitive values were omitted, and destroyed the test resource. -The job logs recorded: - -```json -{ - "resource_address": "aws_ssm_parameter.proof", - "actions": ["update"], - "changed_paths": ["/value", "/version"], - "redaction_verified": true -} -``` - -The excerpt contains selected fields from the run's output, **not a claim that the exact JSON object above is a separately published artifact**. The run concluded successfully, including the cleanup step that checked the disposable parameter no longer existed. +The job logs reported the following selected evidence fields: + +- Resource address: `aws_ssm_parameter.proof` +- Change action: `update` +- Changed paths: `/value` and `/version` +- Redaction verification: `true` + +These are fields from the run's output, **not a claim that this list is a separately published artifact**. The run concluded successfully, including the cleanup step that checked the disposable parameter no longer existed. **What it establishes:** one real Terraform AWS provider refresh, one deliberately introduced out-of-band parameter change, successful evidence generation and value redaction, and cleanup under the tested environment.