Skip to content

fix: admit Dynatron's Conduit clients in every instance to Phorge - #609

Merged
holmboe merged 2 commits into
mainfrom
dev-app-label-selector
Oct 30, 2026
Merged

holmboe merged 2 commits into
mainfrom
dev-app-label-selector

Conversation

@holmboe

@holmboe holmboe commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Dynatron runs one instance per git worktree in the shared k3d cluster: namespace dynatron
for the main checkout, and dynatron-<slug> for each worktree. phorge-from-dev-apps selected
kubernetes.io/metadata.name: dynatron, so only the main checkout could reach Phorge at
http://web.phorge.svc.cluster.local/api/. Every worktree instance timed out. It also admitted
every pod in that namespace, including Postgres, Valkey and the object store, although only the
hub and the worker call Conduit.

Change

  • k8s/base/networkpolicy.yaml: phorge-from-dev-apps has one from entry, and both
    selectors in it must match:

    • namespaceSelector app.kubernetes.io/part-of: dynatron, which every Dynatron instance
      carries, main or worktree
    • podSelector app.kubernetes.io/name In [dynatron, worker], the hub and the worker

    The podSelector on Phorge and port 80 are unchanged. The comment states the trade-off. A
    namespace label is only as trustworthy as whoever may edit namespaces. The pod selector
    narrows the grant, but anyone who can create pods in an admitted namespace can still give a pod
    an admitted name. In a local dev cluster those are the people who could edit the policy anyway.
    A production cluster would have to restrict who labels namespaces first.

  • dynamist.se/dev-app is no longer part of the policy. It stays the label dev apps are
    discovered by, in make destroy, the k8s workflow and the isolation test.

  • tests/k8s/test_isolation.py: probe_from takes pod labels. The probes from default and
    the other dev apps' namespaces now expect an unlabelled pod to be refused on all three ports.
    New tests run in a scratch namespace labelled app.kubernetes.io/part-of: dynatron and check:

    • pods named dynatron and worker are admitted
    • a pod named postgres is refused

    The scratch namespace means the tests need no Dynatron deployed beside Phorge, which is the
    case in CI.

  • docs/phorge-setup.md (the Phorge and in-cluster clients bullets) and CHANGELOG.md
    describe the new policy and its caveat.

Rollout: Dynatron already labels its namespaces app.kubernetes.io/part-of: dynatron alongside
dynamist.se/dev-app: dynatron, so this can merge without waiting on Dynatron.

Checks

  • make validate: both overlays valid, 17 resources each
  • uv run ruff check, ruff format, uv run mypy: clean
  • uv run pytest: 6416 passed
  • The new isolation tests run in CI's Deploy and test Phorge stable in k3d (the PR is
    labelled ci:k8s)

This revision was not applied to the shared local cluster by hand. Before the revision, an
earlier version that selected only on the namespace label was checked live. Pods in dynatron,
dynatron-test-reports and dynatron-handle-warnings reached conduit.ping, and pods in
default, noodle and an unlabelled scratch namespace were refused.

🤖 Generated with Claude Code

@holmboe holmboe added the ci:k8s Run the Kubernetes deploy check label Oct 30, 2026
@holmboe holmboe changed the title fix: admit every Dynatron instance to Phorge's Conduit port fix: admit Dynatron's Conduit clients in every instance to Phorge Oct 30, 2026
holmboe and others added 2 commits October 30, 2026 02:35
Dynatron now runs one instance per git worktree in the shared k3d
cluster: `dynatron` for the main checkout, `dynatron-<slug>` for each
worktree. phorge-from-dev-apps selected kubernetes.io/metadata.name:
dynatron, so only the main checkout reached
web.phorge.svc.cluster.local and every worktree instance timed out.

Select on dynamist.se/dev-app: dynatron instead, which every Dynatron
namespace carries; the podSelector and port 80 stay as they were. The
API server sets the namespace name, while anyone who can create a
namespace can set this label, but in a local dev cluster those are the
people who could edit the policy anyway. The isolation test now decides
which namespaces are admitted by that label rather than by name, and the
setup docs say which namespaces reach Phorge.
phorge-from-dev-apps admitted every pod in a namespace labelled
dynamist.se/dev-app: dynatron, which includes each instance's postgres,
valkey and object store. Only the hub and the worker call Conduit.

One from entry now selects both: the namespace by
app.kubernetes.io/part-of: dynatron, which every Dynatron instance
carries, main or worktree, and the pod by app.kubernetes.io/name in
[dynatron, worker]. dynamist.se/dev-app stays the label dev apps are
discovered by and is no longer part of the policy.

The comment and the setup docs say what that is worth: a namespace
label is only as trustworthy as whoever may edit namespaces, and the
pod selector narrows the grant, but anyone who can create pods in an
admitted namespace can still claim an admitted name.

probe_from takes pod labels. The probes from other namespaces now
expect an unlabelled pod to be refused everywhere, and new tests in a
scratch namespace labelled part-of: dynatron show that dynatron and
worker are admitted and postgres is not, so they need no Dynatron
deployed beside Phorge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@holmboe
holmboe force-pushed the dev-app-label-selector branch from 4a5b69e to 967f84a Compare October 30, 2026 01:36
@holmboe
holmboe merged commit b34e859 into main Oct 30, 2026
27 checks passed
@holmboe
holmboe deleted the dev-app-label-selector branch October 30, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:k8s Run the Kubernetes deploy check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant