# Bc Gov Network Architect

> BC Government network architect combining SDN zone classification, NetworkPolicy authoring, and Emerald enforcement mechanics. Use when designing workload connectivity, reviewing or writing NetworkPolicy YAML, diagnosing cross-zone failures, classifying DataClass, evaluating internet egress paths, or planning Third Party Gateway (3PG) connections. Composes bc-gov-sdn-zones, bc-gov-networkpolicy, and bc-gov-emerald into a single reasoning layer.

- Skill: `rloisell/bc-gov-network-architect` (Agent Skill)
- Install (CLI): `npx skillmds@latest add rloisell/bc-gov-network-architect`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rloisell/bc-gov-network-architect/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: rloisell (https://skillmd.com/u/rloisell)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/rloisell/bc-gov-network-architect

---


# BC Gov Network Architect

Synthesises three skill layers into a single connectivity reasoning workflow.

| Layer | Skill | Responsibility |
|---|---|---|
| 1 — Classification | `bc-gov-sdn-zones` | ISCF data class → SDN zone → permitted adjacencies |
| 2 — Policy authoring | `bc-gov-networkpolicy` | Two-policy rule, YAML patterns, ag-helm intent API |
| 3 — Enforcement | `bc-gov-emerald` | AVI annotation, DataClass pod label, default-deny mechanics |

**Always load all three skills before starting work.**

---

## Reasoning Sequence

For every connectivity question, follow these steps in order:

1. **Classify the data** — What ISCF classification does the workload handle?
2. **Assign the zone** — Map classification to SDN zone (Low / Medium / High) — see `bc-gov-sdn-zones`
3. **Validate adjacency** — Are source and destination zones directly adjacent? No zone-hopping.
4. **Determine egress path** — Direct internet / Forward Proxy / blocked / 3PG for external partners
5. **Author NetworkPolicy objects** — Apply the two-policy rule (egress sender + ingress receiver)
6. **Confirm Emerald enforcement** — AVI annotation and DataClass pod label must match

---

## Quick Reference: Zone Adjacency

Uses the SDN Low/Medium/High model (see `bc-gov-sdn-zones` for full ISCF → zone mapping).

| SDN zone | ISCF class | May connect to |
|---|---|---|
| Low | Unclassified / Public | Low only |
| Medium | Protected A / Protected B (lower) | Medium, Low |
| High | Protected B (higher) / Protected C | High, Medium |

Crossing a non-adjacent boundary requires a 3PG or ALB mediation layer.
Protected C maps to High — there is no separate SDN zone for Protected C.

---

## Common Failure Modes

| Symptom | Most likely cause |
|---|---|
| TCP timeout, no error | Missing one of the two NetworkPolicy objects (two-policy rule) |
| DNS resolution fails | Missing DNS egress policy (UDP 53 to `openshift-dns`) |
| Works in Silver, fails in Emerald | Missing AVI InfraSettings annotation or DataClass pod label |
| Inter-namespace flow fails | Receiver ingress policy lacks `namespaceSelector` for sender |
| External partner connectivity fails | 3PG not configured; direct egress blocked at zone boundary |

---

## NetworkPolicy Checklist

Before declaring a flow complete:
- [ ] Egress policy exists on the **sender** pod
- [ ] Ingress policy exists on the **receiver** pod
- [ ] DNS egress policy present on every pod that resolves hostnames
- [ ] `DataClass` pod label set and matches AVI annotation
- [ ] `owner` and `environment` pod labels present (Emerald requirement)
- [ ] AVI InfraSettings annotation: `dataclass-medium` / `dataclass-high` / `dataclass-public`

---

## Cross-Namespace and Cross-Cluster Flow Mapping Playbook

---

### Detecting Cross-Namespace NetworkPolicies

```bash
# Find all NPs with namespaceSelector in ingress or egress rules
oc get networkpolicies -A -o json | jq '
  .items[] |
  select(
    (.spec.ingress[]?.from[]?.namespaceSelector != null) or
    (.spec.egress[]?.to[]?.namespaceSelector != null)
  ) |
  {namespace: .metadata.namespace, name: .metadata.name, spec: .spec}'

# Detect "wide-open" pattern: namespaceSelector with no podSelector and no port restriction
oc get networkpolicies -A -o json | jq '
  .items[] |
  select(
    .spec.ingress[]?.from[]? |
    (.namespaceSelector != null) and
    (.podSelector == null or .podSelector == {})
  ) |
  {namespace: .metadata.namespace, name: .metadata.name}'
```

### Cross-Namespace NP Risk Classification

| Pattern | Risk | Explanation |
|---|---|---|
| `namespaceSelector` only — no `podSelector`, no `ports` | 🔴 HIGH | Any pod in source NS can reach any pod in target NS on any port |
| `namespaceSelector` + `podSelector`, no `ports` | 🟡 MEDIUM | Scoped to specific pods but all ports exposed |
| `namespaceSelector` + `podSelector` + `ports` | 🟢 COMPLIANT | Fully scoped — principle of least privilege |

### Recommended Scoped Cross-Namespace NP Pattern

```yaml
# Ingress on the RECEIVER side — allows traffic from a specific pod in another namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-<source-app>-api
  namespace: <target-ns>-dev
spec:
  podSelector:
    matchLabels:
      app: <target-app>-api          # target: only the receiver pods
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: <source-ns>-dev   # source namespace
          podSelector:
            matchLabels:
              app: <source-app>-api                          # source: specific sender pods only
      ports:
        - protocol: TCP
          port: 8080                                         # only the required port
```

### Cross-Cluster Flows (Silver ↔ Emerald)

There is **no direct cluster-to-cluster Kubernetes networking** between Silver and Emerald. All cross-cluster communication routes via **public Routes**.

| Step | Detail |
|---|---|
| 1. Service B in Silver | Must have a `Route` with a public hostname |
| 2. Service A in Emerald | Makes HTTP/HTTPS calls to Service B's public route hostname |
| 3. Egress NP on Service A | Egress to the Silver route hostname (via Forward Proxy or direct if public) |
| 4. Ingress NP on Service B | Standard public-ingress NP (allows from router namespace) |

**Treat Silver ↔ Emerald flows as external egress — apply the same controls as any internet-bound flow including TLS enforcement, FWCR if applicable, and Forward Proxy routing.**

### Stale NP Detection

```bash
# List all NPs in a namespace with their pod selector and age
oc get networkpolicies -n <ns> -o json | jq '
  [.items[] | {
    name: .metadata.name,
    age: .metadata.creationTimestamp,
    podSelector: .spec.podSelector
  }]'

# Cross-reference NP pod selectors against running pod labels
# For each NP, check if any running pod matches .spec.podSelector.matchLabels
oc get pods -n <ns> -o json | jq '
  [.items[] | {name: .metadata.name, labels: .metadata.labels}]'
```

Flag NPs where the `podSelector` matchLabels matches **no running pods** — these are stale and accumulate silently after workload decommission.

### Common Cross-Namespace NP Anti-Patterns

| Anti-Pattern | Namespace | Issue | Risk |
|---|---|---|---|
| `namespaceSelector` only (no `podSelector`, no `ports`) | `<ns>-dev` | Allows traffic from any pod in the source namespace on any port | 🔴 HIGH |
| Stale NP — pod selector matches no running pods | `<ns>-dev` | Orphaned after workload decommission; silently accumulates | Orphaned |
| NP for a service that no longer exists (e.g. old message broker) | `<ns>-dev` | Was created for a removed workload; no current enforcement value | Orphaned |

These patterns have been observed in production BC Gov Silver namespaces. The stale NP pattern is especially common after Patroni-to-CloudNativePG migrations and Redis topology changes.

---

## BC_GOV_NETWORK_ARCHITECT_KNOWLEDGE

<!-- agent-evolution appends discoveries here -->
<!-- Format: - YYYY-MM-DD: [engagement] <imperative statement> -->
- 2026-06-05: [multi-app-engagement] Cross-namespace NPs with no port/pod filtering are wide-open — always scope with podSelector + ports
- 2026-06-05: [multi-app-engagement] Stale NPs from decommissioned workloads accumulate silently — add NP cleanup to decommission checklists
- 2026-06-05: [multi-app-engagement] Cross-cluster flows (Silver↔Emerald) route via public Routes, not K8s networking — treat as external egress

