Skip to content

feat(workflows): mirror signed images to acr and seed dr secrets - #31

Merged
EstebanGZam merged 8 commits into
mainfrom
feat/dr-registry-mirror-and-secret-seed
Sep 21, 2026
Merged

EstebanGZam merged 8 commits into
mainfrom
feat/dr-registry-mirror-and-secret-seed

Conversation

@EstebanGZam

Copy link
Copy Markdown
Contributor

What changes

Adds the disaster-recovery registry mirror and the secret seed as reusable workflows. None of them rebuilds, re-signs, or stores a credential.

  • mirror-to-acr.yml copies one production-validated service image's complete OCI graph (image, signatures, SBOM attestations) from ECR to ACR without rebuilding it. It proves the manifest digests are equal and verifies the signature in ACR against the service CI identity.
  • mirror-platform-images.yml now also copies the complete, already-signed, locked platform graph from ECR to ACR. The copy uses AWS and Azure OIDC, runs no build and adds no re-signature, and the image, signature, and attestation digests stay equal.
  • sync-dr-secrets.yml seeds exactly the four mapped secrets into Azure Key Vault inside a GitHub environment. It masks early and disables tracing. Files are mode 0600 and removed by an EXIT trap. It keeps no cache, artifact, environment variable, or value output. The production-JWT equality check is an in-process boolean with no digest.
  • promote.yml routes a promotion by destination, so only the production/full/aks-dr paths trigger the DR mirror.

Why

Constitution principle 12 requires Azure to hold the same immutable production digest and off-provider recovery copies. These workflows move the artifacts and the secrets that the AKS disaster-recovery destination needs, without breaking the build-once, promote-by-digest chain.

Tasks

  • gitops specs/009-full-platform-rollout T121: tests/workflows/{mirror-to-acr,mirror-platform-images,sync-dr-secrets}.bats, committed red in 2fc0f31.
  • gitops specs/009-full-platform-rollout T131: the three workflows and the promote.yml integration; all three contracts now pass.

Register: gitops specs/009-full-platform-rollout/tasks.md, updated in the companion microservice-app-gitops pull request opened by the lead (conventions §8). This pull request is the .github half of that cross-repository change.

  • The task register is updated in this pull request (it lives in gitops; see above)
  • Every task ticked here was verified by locating its artifact (nothing is ticked here)

How it is verified

Run locally, offline, from this branch's head:

bash tests/workflows/mirror-to-acr.bats               -> rc=0 mirror-to-acr-contract: OK
bash tests/workflows/mirror-platform-images.bats      -> rc=0 mirror-contract: OK
bash tests/workflows/sync-dr-secrets.bats             -> rc=0 sync-dr-secrets-contract: OK
bash tests/workflows/reusable-workflow-contract.bats  -> rc=0
bash tests/workflows/continuous-security.bats         -> rc=0
bash tests/workflows/stack-tests-contract.bats        -> rc=0

One test correction, recorded here openly. The first red commit's service-mirror contract required id-token: write and also forbade the literal token:, which that permission contains, so no workflow could satisfy both. 949bd92 narrows the rule to what its comment states: the public GitOps checkout takes no token: input. It now forbids a key named exactly token (^[[:space:]]*token:) and still requires persist-credentials: false. No other assertion changed.

Documentation consulted through the MCP servers (aws-knowledge, microsoft-learn, terraform):

No workflow was run, and no cloud or GitHub setting was touched.

  • Infrastructure changes: the documentation consulted through the required MCP servers is listed above (microservice-app-ai-agents/rules/mcp.md)

Risk and rollback

The new workflows run only when called. promote.yml gains destination routing, and the reusable-workflow contract still passes for the existing prod/staging paths. The DR paths need ACR and Key Vault, which do not exist until T128. Rollback is a revert.

What this PR does not do

  • It does not configure the GitHub-to-Azure federated credentials or environments (T132).
  • It does not run the seed or the mirror (T133).
  • It does not create any Azure resource.

🤖 Generated with Claude Code

EstebanGZam and others added 8 commits September 21, 2026 14:26
Capture the production digest, signed platform graph, and four-secret transfer requirements before implementing the DR workflows. The offline contracts fail against the current workflow set as required by spec 009 T121.
…ting a value

Adds the reusable sync-dr-secrets workflow (gitops spec 009 T131, research
Decision 14): short-lived AWS and Azure OIDC sessions in a GitHub environment
copy exactly four Secrets Manager values byte-exact into the DR Key Vault.
Tracing is disabled, values are masked before any other use, the one CLI file
is mode 0600 in a 0700 directory removed by an EXIT trap, and the only output
is an in-process jwt-value-match boolean. A self-test runs the contract.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Preserve the existing AWS promotion tuples while routing the explicit prod/full/aks-dr/dr-rolling tuple through a separate mirror and secret seed chain. The companion workflows are being added in the same pull request.
The two DR identities receive reviewed tenant and subscription inputs from the caller. Runtime metadata stays explicit while the AWS promotion path keeps its previous inputs.
…mission

The service-mirror contract required `id-token: write` and also forbade the
literal `token:`, which that permission contains, so no workflow could
satisfy it. The rule's intent is that the public GitOps checkout takes no
token; it now forbids a key named exactly `token` instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add the reusable DR service mirror for gitops spec 009 T131 (research.md
Decision 13, release-promotion-contract.md rules 8 and 9). It accepts only
the repository and digest the GitOps production overlay declares, reaches
AWS and Azure through OIDC alone, reads the public GitOps repository with no
persisted credential, installs oras, crane and cosign by checksum from the
toolchain lock, copies the signed OCI graph by digest with any tag-scheme
signature, attestation and SBOM, fails unless the ACR manifest digest equals
the ECR one, and verifies the Cosign signature and SPDX attestation in ACR
against the service CI identity. Nothing is rebuilt or re-signed.

The self-test runs tests/workflows/mirror-to-acr.bats on changes to the
mirror, its self-test, promote.yml and the test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Extend mirror-platform-images.yml for gitops spec 009 T131 (research
Decision 13). An optional mirror-to-acr job, gated on acr-name and run
after the unchanged ECR mirror, validates the whole lock and every ECR
digest first, then copies each locked image by digest with oras cp -r,
plus tag-scheme .sig/.att/.sbom when present. It proves image, referrer
and tag digests are equal in ACR and verifies the platform-mirror Cosign
identity there. AWS and Azure use OIDC only, tools come checksum-locked
from the toolchain lock, and nothing is rebuilt or re-signed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EstebanGZam
EstebanGZam marked this pull request as ready for review September 21, 2026 21:40
@EstebanGZam
EstebanGZam merged commit 0624824 into main Sep 21, 2026
5 checks passed
@EstebanGZam
EstebanGZam deleted the feat/dr-registry-mirror-and-secret-seed branch September 21, 2026 21:40
EstebanGZam added a commit to MicroTodoSuite/microservice-app-gitops that referenced this pull request Sep 22, 2026
…228)

## What changes

The full-platform register now distinguishes the AWS foundations that
were
created from the evidence that was actually retained. It records the
redacted
T052 preflight, the first-creation and lifecycle re-up facts for every
rebuilt
root, the hub half-apply and repair, and the still-missing proof for
T053-T067.

The disaster-recovery register now follows the governing IaC layout:
Azure
modules belong in `terraform-azure-modules`, live Azure state is split
into the
six `fprd` domain roots, and T122 belongs to the rebuilt `shd/dns` and
`fprd/security-irsa` owners. It also records the six-vCPU warm-standby
scope,
the Azure for Students ownership boundary, the economical backup-only
Azure
boundary, and follow-up tasks for ops#128 and the AKS inventory
contract.

T121 and T131 are recorded complete against the merged organization
workflows.
The preflight and per-root summaries contain counts, result lines,
checksums,
backup paths, and recorded Infracost figures only; no plan JSON, state,
secret,
resource ID, or ARN is copied into Git.

## Why

The register still described legacy foundation and Azure layouts after
the AWS
estate was rebuilt and the DR workflows landed. Leaving those tasks
unchanged
would make successful applies look more complete than their retained
evidence,
would direct Azure work toward a forbidden local module and monolithic
root,
and would require an AKS capability inventory that cannot fit the
verified
student-subscription quota.

This reconciliation applies constitution principles 12 and 13: DR scope
stays
truthful about quota and function, and tasks are ticked only against
located and
inspected artifacts. Successful infrastructure creation is annotated
without
claiming missing topology, economical-baseline, or acceptance evidence.

## Tasks

- gitops `specs/009-full-platform-rollout` T052: completed against
`evidence/runs/20260921T192300Z-full-profile-foundations/infrastructure/preflight.json`.
- gitops `specs/009-full-platform-rollout` T053: partial;
plan/cost/checksum records exist, topology and rollback-acceptance proof
does not.
- gitops `specs/009-full-platform-rollout` T054: partial; apply and
backup records exist, output/route/flow-log/NAT/economical proof does
not.
- gitops `specs/009-full-platform-rollout` T055: partial; the three
spoke plan records exist, the named network-topology proof does not.
- gitops `specs/009-full-platform-rollout` T057: partial; exact-plan
re-up and backups exist, route/flow-log/economical proof does not.
- gitops `specs/009-full-platform-rollout` T058: partial; security roots
were created, but Infracost and the named security/no-secret proof were
not retained.
- gitops `specs/009-full-platform-rollout` T059: partial;
apply/checksum/receipt records exist, 2026-09-14 approval provenance,
named outputs, and economical proof do not.
- gitops `specs/009-full-platform-rollout` T060: partial; workload and
IRSA passes exist, but the complete readiness/identity/lifecycle
baseline does not.
- gitops `specs/009-full-platform-rollout` T063: partial; root files
exist, but the current gate's review/check/golden-render evidence does
not.
- gitops `specs/009-full-platform-rollout` T064: open; no audited
bootstrap transcript exists.
- gitops `specs/009-full-platform-rollout` T065: open; no post-bootstrap
read-only root proof exists.
- gitops `specs/009-full-platform-rollout` T066: open; no
network-isolation evidence exists.
- gitops `specs/009-full-platform-rollout` T067: open; no validated
`evidence.json` or US2 acceptance exists.
- gitops `specs/009-full-platform-rollout` T118: re-targeted to
per-resource module tests in `terraform-azure-modules`; remains
unchecked.
- gitops `specs/009-full-platform-rollout` T119: re-targeted to the six
Azure `fprd` domain-root tests; remains unchecked.
- gitops `specs/009-full-platform-rollout` T120: completed artifact
retained; its superseded complete-inventory assertion is assigned to
T179.
- gitops `specs/009-full-platform-rollout` T121: completed against the
three merged workflow tests on MicroTodoSuite/.github `main`.
- gitops `specs/009-full-platform-rollout` T122: re-targeted to the
existing `shd/dns` and `fprd/security-irsa` roots; remains unchecked.
- gitops `specs/009-full-platform-rollout` T125: re-targeted to
independently released per-resource modules; remains unchecked.
- gitops `specs/009-full-platform-rollout` T126: re-targeted to
domain-split live roots consuming exact module tags; remains unchecked.
- gitops `specs/009-full-platform-rollout` T131: completed against
`mirror-to-acr.yml`, `mirror-platform-images.yml`,
`sync-dr-secrets.yml`, and the DR routing in `promote.yml` on
MicroTodoSuite/.github `main`.
- gitops `specs/009-full-platform-rollout` T133: remains unchecked; its
activation scope is reconciled to the minimum six-vCPU warm-standby
inventory.
- gitops `specs/009-full-platform-rollout` T178: added for the
microservice-app-ops#128 rule-compliant rework.
- gitops `specs/009-full-platform-rollout` T179: added for the
test-first AKS inventory and planned-inventory update.

T056, T061, and T062 remain unticked and unchanged as superseded work.

The located artifacts for every task newly ticked by this pull request
are:

- T052:
`evidence/runs/20260921T192300Z-full-profile-foundations/infrastructure/preflight.json`.
- T121:
`tests/workflows/{mirror-to-acr,mirror-platform-images,sync-dr-secrets}.bats`
at MicroTodoSuite/.github merge `0624824`.
- T131:
`.github/workflows/{mirror-to-acr,mirror-platform-images,sync-dr-secrets,promote}.yml`
at MicroTodoSuite/.github merge `0624824`.

This pull request is the section 8 companion of

[MicroTodoSuite/.github#31](MicroTodoSuite/.github#31).
The preserved, closed prior attempt remains documented in

[terraform-azure-modules#2](MicroTodoSuite/terraform-azure-modules#2),

[terraform-azure-modules#3](MicroTodoSuite/terraform-azure-modules#3),

[microservice-app-ops#124](MicroTodoSuite/microservice-app-ops#124),
and
[microservice-app-ops#127](MicroTodoSuite/microservice-app-ops#127).
Those pull requests are not reopened. The currently open local-module

[microservice-app-ops#128](MicroTodoSuite/microservice-app-ops#128)
is reworked through T178.

- [x] The task register is updated in this pull request
- [x] Every task ticked here was verified by locating its artifact

## How it is verified

The branch and carried work were inspected before editing:

```text
git status --short --branch
## docs/reconcile-full-foundations-and-dr-scope...origin/docs/reconcile-full-foundations-and-dr-scope

git log --oneline origin/main..HEAD
52417a1 docs(specs): reconcile the full-profile foundations and the dr scope
da5454d docs(evidence): record the per-root full-profile foundation summaries
d1849f6 docs(evidence): record the redacted full-profile preflight snapshot
```

The 13 first-creation plan JSON files and apply logs were inspected
without
copying their contents. Their managed action/result summaries are:

```text
shd-networking: create=24; Apply complete! Resources: 24 added, 0 changed, 0 destroyed.
fdev/fstg/fprd networking: create=28 each; 28 added, 0 changed, 0 destroyed.
fdev/fstg/fprd security: create=31 each; 31 added, 0 changed, 0 destroyed.
fdev/fstg/fprd workload: create=26 each; 26 added, 0 changed, 0 destroyed.
fdev/fstg/fprd security-irsa: create=15 each; 15 added, 0 changed, 0 destroyed.
```

Every saved-plan and JSON checksum in the three 2026-09-21 lifecycle
bundles
was verified with `sha256sum -c`. The decisive action summaries were:

```text
full-up-20260921T192817Z: shd-networking create=24
full-up-20260921T195633Z: shd create=2/no-op=22; each spoke create=7/no-op=21; each workload create=26
full-up-20260921T210444Z: each security-irsa create=15; every other root no-op
```

All committed evidence JSON files parse with `jq -e .`. The merged
workflow
contracts were then run from the MicroTodoSuite/.github checkout:

```text
bash tests/workflows/mirror-to-acr.bats
mirror-to-acr-contract: OK: production-validated input only ...

bash tests/workflows/mirror-platform-images.bats
mirror-contract: OK — OIDC-only dedicated-role mirror ...

bash tests/workflows/sync-dr-secrets.bats
sync-dr-secrets-contract: OK: OIDC-only AWS/Azure sessions ...
```

`git diff --check` is clean. A path guard confirms this pull request
does not
change `tests/profiles/aks-dr.bats`, `clusters/aks-dr`, or
`experiments/`.

MTS-IAC-102, PC-IAC-015, PC-IAC-022, constitution principles 12/13, the
pull
request/task conventions sections 7/8, ADR-0001, and the
plan-reconciliation
worked example were read before the register was changed.

After the quota decision merges, T179 must change these exact
`tests/profiles/aks-dr.bats` assertions in a separate test-first pull
request:

- `required_capabilities` must require only Istio, cert-manager, and
External Secrets; the root's existing ArgoCD assertion remains.
- The 18 deferred capabilities must be absent from the planned and
activated AKS inventory, through `forbidden_capabilities` or an
equivalent exact-inventory assertion.
- The exact Prometheus destination-path assertion must be removed.
- The Prometheus/Grafana `managed-csi` persistence loop must be removed
because both capabilities are deferred.
- The header comments and final PASS text that claim a complete
equivalent full inventory must describe the minimum warm-standby
inventory instead.
- `clusters/aks-dr/planned-inventory.yaml` must match the revised
assertions before T133 activation.

The conventions validator was run locally with `PR_TITLE`,
`PR_HEAD_BRANCH`,
`PR_BODY`, and `CHANGED_FILES_FILE`; it returned `conventions: PASS`.

- [ ] Infrastructure changes: the documentation consulted through the
required MCP servers is listed above (N/A: this pull request changes
evidence and the task register only, not Terraform, tfvars, or
Kubernetes manifests)

## Risk and rollback

The risk is documentary: a mistaken tick or scope decision could
authorize
later work from an inaccurate register. The conservative annotations
keep
tasks unchecked wherever their full text lacks retained proof, and the
Azure
implementation tasks remain unchecked until compliant artifacts merge.

Rollback is a Git revert of this pull request. No live resource,
cluster,
workflow, or GitOps-managed path changes when these commits are
reverted.

## What this PR does not do

- It does not run a cloud command, mutate AWS or Azure, call `kubectl`,
bootstrap ArgoCD, dispatch a workflow, or apply a Terraform plan.
- It does not edit `tests/profiles/aks-dr.bats`, `clusters/aks-dr`, or
`experiments/`.
- It does not provide the missing T053-T067 topology, baseline,
bootstrap, reachability, schema-validation, or acceptance evidence.
- It does not merge, reopen, or modify terraform-azure-modules#2/#3 or
microservice-app-ops#124/#127/#128.
- It does not implement T118/T119/T125/T126, run T133, enable production
traffic, or claim full-profile or DR acceptance.
- It does not approve or merge this pull request;
microservice-app-gitops requires one human approval.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant