Skip to content

feat(model): admit the Release Gate's own requests to every gate member - #606

Merged
ExtraToast merged 3 commits into
mainfrom
feat/602-gate-reaches-members
Oct 26, 2026
Merged

ExtraToast merged 3 commits into
mainfrom
feat/602-gate-reaches-members

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

Closes #602. Part of #315.

Summary

The Release Gate now sends its own requests to each member's new copy during analysis (JorisJonkers-dev/delivery#82, merged). The derived allow set admitted neither half of that traffic: the gate's policy allowed only DNS and the API server, and a member's admitted only its tier, the metrics stack and its consumers. Policies are still render-only, so nothing is blocked today, but every check would time out once enforcement lands.

This adds the rule the maintainer chose, the member label:

  • The member label. Every pod of a gate member, a Process its Application's release-gate inputs name, carries gated.deploy-kit.jorisjonkers.dev/release-gate: "true". It goes on pod templates only, never in a selector.
  • The member's half. A new ingress rule, release-gate, admits every Process of the gate the Platform document's delivery.gate names, on the port of the member's first surface. That is the port its Canary service targets.
  • The gate's half. A new egress peer, { rule: gate-members }, which the networking adapter spells as every pod carrying the member label, in any namespace deploy-kit manages, on any port. Members serve on many ports, and the member's own ingress names the one it admits.
  • No Project names another's Processes. A member added, changed or removed re-renders its own share and never the delivery Project's. A new test holds that.
  • The Resolved Deployment. IngressRule gains release-gate. A Process's egress admits a GateMembersPeer beside an EgressPeer, and a named EgressPeer type is exported for the places that read a peer's namespace and port. The published schemas are regenerated.
  • Records.
    • Chapter 16 gains "The member label" and two allow-set rows, and chapter 55's check paragraph points at it.
    • Chapter 20's projection text and class drawing follow.
    • Chapter 10's label set admits the label, as do 0039 and 0035. 0035 also records why the gate does not reach every pod the model manages, as a new alternative.
    • CONTEXT.md defines Member label.
  • Oracles.
    • In every example with a gated Application (minimal, auth, identity's four, hindsight), each member's policy admits the gate and its pods carry the label.
    • The delivery example's gate policy reaches labelled pods.
    • Revisions move with them, and so does everything named by one: Canaries, migration Jobs, sync objects.

To know

  • One rollout per gated Application. The label changes each member's pod template once, and the new revision renames revision-named objects. So the first delivery rolls every gated Application once, and its migration Job runs again under the new name.
  • emf/ is frozen at mde-task-3, so this lands in TypeScript only. The model-driven build runs by hand only, and its hand-written minimal model keeps the old revision until the post-1.0 catch-up.
  • Trust is the same as the consumer label's: only the model renders the label, in namespaces only it manages.
  • The warmup after promotion (the rest of Release Gate: send test traffic to the Canary, and warm the public caches after promotion delivery#12) reaches public addresses, not members. It is the gate's own internet egress, declared in the delivery repository's project file, not here.

Checks

  • Full suite: 2106 tests pass. New tests:
    • every member admits the gate on its first surface, and a stop-start Process admits nothing;
    • only the gate's own Processes carry gate-members, Flagger's do not;
    • a member's pods carry the label and a blue-green Process with no readiness does not;
    • a Process that stops being a member, or becomes one again, moves only its own Project.
  • Lint, format, typecheck and every contract lint pass: ADRs, links, meaning, docs, manifests (314 resources valid), boundaries, rules, requirements, agents.
  • Stryker on the changed lines: 100% after the two survivors were fixed. One was an optional chain no member can reach, now a cast with its reason; the other was the non-member case, now tested.

Each member's pods carry a member label and admit the gate on the port its Canary service targets; the gate's policy reaches every labelled pod. Neither half names the other's Project. Closes #602.
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: deploy homelab-deploy, deploy-v2, manifests, and rollout flow. labels Oct 25, 2026
@ExtraToast
ExtraToast enabled auto-merge (squash) October 25, 2026 14:14
…-members

# Conflicts:
#	spec/v1/examples/auth/expected/resolved.json
#	spec/v1/examples/delivery/expected/resolved.json
#	spec/v1/examples/identity/expected/resolved.grafana.json
#	spec/v1/examples/identity/expected/resolved.identity.json
#	spec/v1/examples/identity/expected/resolved.portal.json
#	spec/v1/examples/identity/expected/resolved.whoami.json
#	spec/v1/examples/knowledge-platform/expected/resolved.hindsight.json
#	spec/v1/examples/minimal/expected/resolved.json
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Shape

bucket files additions deletions
production code 7 +116 -18
tests 3 +119 -9
specification 6 +83 -8
decision records 2 +18 -0
documentation 1 +5 -0
examples 43 +196 -57

Coverage

Baseline: main @ 50ea3b3.

metric this branch main diff
statements 99.71% 99.71% 0.00
branches 98.48% 98.47% +0.01
functions 100.00% 100.00% 0.00
lines 99.68% 99.68% 0.00

Lines this pull request changed: 16/16 covered (100.00%).

…-members

# Conflicts:
#	spec/v1/examples/auth/expected/resolved.json
#	spec/v1/examples/auth/rendered/apps/auth/auth/canary.yaml
#	spec/v1/examples/auth/rendered/apps/auth/auth/migration.yaml
#	spec/v1/examples/auth/rendered/apps/auth/auth/workload.yaml
#	spec/v1/examples/delivery/expected/resolved.json
#	spec/v1/examples/identity/expected/resolved.grafana.json
#	spec/v1/examples/identity/expected/resolved.identity.json
#	spec/v1/examples/identity/expected/resolved.portal.json
#	spec/v1/examples/identity/expected/resolved.whoami.json
#	spec/v1/examples/identity/rendered/apps/identity/grafana/canary.yaml
#	spec/v1/examples/identity/rendered/apps/identity/grafana/vso.yaml
#	spec/v1/examples/identity/rendered/apps/identity/identity/canary.yaml
#	spec/v1/examples/identity/rendered/apps/identity/portal/canary.yaml
#	spec/v1/examples/identity/rendered/apps/identity/whoami/canary.yaml
#	spec/v1/examples/knowledge-platform/expected/resolved.hindsight.json
#	spec/v1/examples/knowledge-platform/rendered/apps/knowledge-platform/hindsight/canary.yaml
#	spec/v1/examples/knowledge-platform/rendered/apps/knowledge-platform/hindsight/vso.yaml
#	spec/v1/examples/minimal/expected/resolved.json
#	spec/v1/examples/minimal/rendered/apps/notes/notes/canary.yaml
#	src/adapters/kubernetes/render.ts
#	src/resolve/application.ts
#	test/application/compose.test.ts
@ExtraToast
ExtraToast merged commit 928c1f2 into main Oct 26, 2026
28 checks passed
@ExtraToast
ExtraToast deleted the feat/602-gate-reaches-members branch October 26, 2026 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: deploy homelab-deploy, deploy-v2, manifests, and rollout flow. type: feature New user-facing or operator-facing capability.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admit the Release Gate's own requests to every gated member

1 participant