@@ -403,9 +403,102 @@ spec:
403403- Add support for capsule dependency resolution.
404404
405405
406+ ## Experimental Verification on Azure AKS — April 29, 2026
407+
408+ All four ADR-001 claims were formally verified by running
409+ ` scripts/verify-adr-001.sh` against a live AKS cluster
410+ (`basic-docker-aks`, East US, Kubernetes v1.34.4, single node `Standard_B2s`).
411+
412+ # ## Test environment
413+
414+ | Item | Value |
415+ |---|---|
416+ | Cloud | Azure for Students |
417+ | Cluster | `basic-docker-aks` (East US) |
418+ | Kubernetes version | v1.34.4 |
419+ | Node | `aks-nodepool1-22820865-vmss000000` (Standard_B2s) |
420+ | Go version | 1.24 |
421+ | Run date | 2026-04-29 |
422+ | Script | `scripts/verify-adr-001.sh` |
423+
424+ # ## Results
425+
426+ **16 checks passed, 0 failed.**
427+
428+ | Claim | Check | On-cluster result |
429+ |---|---|---|
430+ | **C1 Versioning** | v1.0 ConfigMap carries correct `capsule.docker.io/version` label | ✔ |
431+ | | v2.0 ConfigMap carries correct label | ✔ |
432+ | | v1.0 and v2.0 ConfigMap data are independent (no bleed-through) | ✔ |
433+ | | CRD `ResourceCapsule` object persists `spec.version` field | ✔ |
434+ | | CRD object persists `spec.rollback.enabled` flag | ✔ |
435+ | | Unit : ` TestKubernetesConfigMapCapsule` | ✔ |
436+ | **C2 Dynamic Attachment** | Baseline Deployment `app-a` is `Available` before any capsule is attached | ✔ |
437+ | | Unit : ` TestAttachCapsuleToDeployment` — volume and VolumeMount verified | ✔ |
438+ | | Live Deployment spec shows volume `capsule-attach-cap-1-0` after patch | ✔ |
439+ | | Live container spec shows matching VolumeMount | ✔ |
440+ | **C3 Isolation** | Capsules in test namespace are invisible from a second namespace | ✔ |
441+ | | Cross-namespace `kubectl get` returns `NotFound` | ✔ |
442+ | **C4 Reusability** | Deployment `app-b` mounts `mylib-1.0` and becomes `Available` | ✔ |
443+ | | Deployment `app-c` mounts `mylib-1.0` and becomes `Available` | ✔ |
444+ | | Single ConfigMap object backs both Deployments (no duplication) | ✔ |
445+ | | Unit : ` TestResourceCapsuleCRDTypes` , `TestResourceCapsuleCRDDeepCopy`, `TestResourceCapsuleOperatorCreation` | ✔ |
446+
447+ # ## Technical observations
448+
449+ **C1 — Versioning holds solid value.**
450+ Two ConfigMap-backed capsules (`mylib-1.0`, `mylib-2.0`) coexisted in the same
451+ namespace without conflict. The `capsule.docker.io/version` label was correctly
452+ stored and retrievable. The CRD `ResourceCapsule` object persisted both the
453+ ` spec.version` string and the `spec.rollback.enabled` boolean through the
454+ Kubernetes API server. Versioning is implemented cleanly and is directly
455+ queryable via label selectors (`kubectl get cm -l capsule.docker.io/name=mylib`).
456+
457+ **C2 — Dynamic Attachment is real but has an implementation constraint.**
458+ The `AttachCapsuleToDeployment` function correctly adds a volume and VolumeMount
459+ to a live Deployment via a Kubernetes API `Update` call. However, a bug was
460+ discovered and fixed during this verification : version strings containing dots
461+ (e.g. `1.0`) produced volume names like `capsule-attach-cap-1.0`, which
462+ Kubernetes rejects (DNS subdomain rules prohibit dots in volume names). The fix
463+ replaces dots with dashes in the generated volume name while keeping the mount
464+ path (`/capsules/attach-cap/1.0`) unchanged. The "without restarting" claim in
465+ the ADR requires clarification — Kubernetes rolling-restarts pods when a
466+ Deployment spec is updated; the capsule attach operation does not bypass this.
467+
468+ **C3 — Isolation is enforced by Kubernetes RBAC and namespace scoping, not by
469+ capsule-specific logic.** ConfigMaps and Secrets are namespace-scoped objects;
470+ the capsule system inherits this isolation for free. The claim holds, but its
471+ strength comes from the platform rather than from any capsule-specific access
472+ control. Adding dedicated RBAC `Role`/`RoleBinding` objects would make this
473+ capsule-owned rather than platform-inherited.
474+
475+ **C4 — Reusability holds solid value.** Two separate Deployments mounting the
476+ same ConfigMap-backed capsule both reached `Available` state. Kubernetes
477+ confirmed a single ConfigMap object (one API resource) backing multiple consumers
478+ simultaneously. This is the strongest validated claim — it works exactly as
479+ described in the ADR with zero additional mechanism needed.
480+
481+ # ## Bug fixed
482+
483+ ` kubernetes.go` ` AttachCapsuleToDeployment` generated Kubernetes volume names
484+ containing dots (e.g. `capsule-name-1.0`). Kubernetes volume names must comply
485+ with DNS label syntax and may not contain dots. Fixed by sanitizing the version
486+ string : ` strings.ReplaceAll(capsuleVersion, ".", "-")` in the volume name only;
487+ the mount path retains the original version string.
488+
489+ # ## Artifacts produced
490+
491+ | File | Purpose |
492+ |---|---|
493+ | `scripts/setup-azure-aks.sh` | Provision AKS cluster + app registration + set GitHub secrets |
494+ | `scripts/verify-adr-001.sh` | Automated ADR-001 claim verification on a live cluster |
495+ | `.github/workflows/aks-lifecycle.yml` | `workflow_dispatch` with `deploy` / `verify` / `deploy-and-verify` / `destroy` options |
496+ | `.github/workflows/azure-aks-verify.yml` | Existing focused verify-only workflow |
497+
406498# # Status
407499April 12, 2025 - Planned
408500August 2, 2025 - Implementation with Kubernetes done
501+ April 29, 2026 - All four claims verified on Azure AKS (see Experimental Verification section above)
409502
410503# # Date
411504April 12, 2025
0 commit comments