Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/kubernetes-reference-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Kubernetes Reference Quality

on:
pull_request:
branches:
- develop
push:
branches:
- develop
workflow_dispatch:

permissions:
contents: read

concurrency:
group: kubernetes-reference-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
kubernetes-reference:
name: Hardened reference deployment contract
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout exact candidate
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Prove exact candidate checkout
env:
EXPECTED_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: test "$(git rev-parse HEAD)" = "${EXPECTED_SHA}"
- name: Set up Node.js LTS
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "24"
check-latest: false
- name: Exercise hardened Kubernetes reference contract
run: node --test tests/kubernetes-reference.test.mjs
- name: Validate repository contracts
run: npm run validate
Comment thread
seonghobae marked this conversation as resolved.
- name: Prove clean checkout
run: |
git diff --exit-code
test -z "$(git status --porcelain)"
4 changes: 4 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ The foundation starts as a monorepo with separately deployable services. Each se
## Security posture

Access is tenant-, actor-, purpose-, resource-, and lifetime-scoped. High-impact decisions require preview, explicit human confirmation, versioned evidence, immutable decision records, and attributable audit events. LLM outputs are draft evidence only.

## Kubernetes reference deployment boundary

The active deployment lane carries the provider-neutral People API reference at `infrastructure/kubernetes/people-api-reference.json`. It is an architecture example for extracting the People API behind the same published API/data-ownership boundary; it does not authorize a release and does not make Kubernetes part of protected-branch runtime truth until this lane is integrated. The manifest keeps the image non-runnable until an immutable digest from an integrated protected revision is supplied, preserves Restricted Pod Security Admission and default-deny network isolation, and requires environment-specific node-CIDR, DNS, PostgreSQL, admission and CNI validation. No Kubernetes object may introduce direct cross-service application-table access or weaken Orgmetra's service-owned schema boundary.
Comment on lines +109 to +111

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Architecture update invalidates repository manifest

After this architecture update, manifest.json retains the previous digest, byte count, and line count. npm run validate fails immediately.

Prompt for agents
Regenerate the deterministic manifest metadata for every file changed on the current head, especially ARCHITECTURE.md and tests/kubernetes-reference.test.mjs. Use tests/validate_repository.py --print-manifest as the repository directs, update manifest.json with the exact SHA-256, byte, and line values, then run npm run validate and the Kubernetes reference test from a clean checkout.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

26 changes: 26 additions & 0 deletions docs/doctoring/kubernetes-reference-deployment-references.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Kubernetes reference deployment — primary-source doctoring

**Evidence state:** active-PR design evidence. These sources inform the Orgmetra-owned reference deployment; they do not constitute Kubernetes certification, cloud-provider compatibility, SOC 2 evidence by themselves, or release authorization.

## APA 7 references

Kubernetes Authors. (n.d.). *Configure liveness, readiness and startup probes*. Kubernetes. Retrieved August 22, 2026, from https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

Kubernetes Authors. (n.d.). *Network policies*. Kubernetes. Retrieved August 22, 2026, from https://kubernetes.io/docs/concepts/services-networking/network-policies/

Kubernetes Authors. (n.d.). *Pod Security Admission*. Kubernetes. Retrieved August 31, 2026, from https://kubernetes.io/docs/concepts/security/pod-security-admission/

Kubernetes Authors. (n.d.). *Pod security standards*. Kubernetes. Retrieved August 22, 2026, from https://kubernetes.io/docs/concepts/security/pod-security-standards/

Kubernetes Authors. (n.d.). *Specifying a disruption budget for your application*. Kubernetes. Retrieved August 22, 2026, from https://kubernetes.io/docs/tasks/run-application/configure-pdb/

## Design consequences recorded from the primary documentation

- **Probe roles stay separate.** Startup probes delay takeover by liveness/readiness while a process starts; liveness is for restart decisions; readiness controls whether a pod receives service traffic. Orgmetra therefore keeps `/health` dependency-free and uses `/ready` for owned PostgreSQL readiness rather than making database reachability a liveness condition.
- **Restricted pod intent is explicit and versioned.** The reference declares Restricted Pod Security Admission labels and a pod/container security context that avoids host namespaces, privileged mode and privilege escalation, runs non-root, uses `RuntimeDefault` seccomp and drops Linux capabilities. Kubernetes defines a per-mode `*-version` label; if version is not pinned, the admission controller uses `latest`. Orgmetra therefore pins `enforce`, `audit`, and `warn` to `v1.37` so the authored policy contract does not silently change when the control plane advances. A target on a different minor requires an explicit re-baseline and re-pin, not deletion of the version labels.
- **Network isolation starts deny-by-default.** A NetworkPolicy selecting all pods with both `Ingress` and `Egress` policy types establishes the namespace baseline. Required application and DNS flows are then explicit exceptions. Cluster networking must actually enforce NetworkPolicy before this is treated as isolation evidence.
- **PDB evidence is bounded.** `maxUnavailable: 1` applies to a controller-managed replicated Deployment and limits voluntary evictions; it is not evidence against involuntary node, process or dependency failures.

## Out of scope for this evidence set

This doctoring file does not select a managed Kubernetes vendor, CNI, ingress controller, service mesh, cloud load balancer, registry, PostgreSQL provider or image signer. Those choices must be bound to their own current primary documentation and target-environment acceptance evidence before release.
37 changes: 37 additions & 0 deletions docs/traceability/kubernetes-reference-deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Kubernetes reference deployment traceability

## State legend

- **Protected-main truth:** accepted on `develop@9e3e4847510e1e612b48474ba42b177b8ed824df`.
- **Active PR:** implemented only on `feat/kubernetes-reference-deployment` until merged.
- **Dependency-active PR:** same-repository capability required for a runnable release but not copied into this branch.
- **Planned:** deliberately outside this bounded slice.

## Requirement → evidence map

| Requirement | State | Executable / review evidence |
| --- | --- | --- |
| Provider-neutral Kubernetes reference is absent on protected main and cannot be mistaken for shipped deployment truth | Protected-main truth | Foundation implementation plan Task 10 plus initial RED exact head `18778945f2bdb9d6f42cebd7a3c71c18dad36352` |
| Reference uses immutable image identity rather than a mutable tag | Active PR | `infrastructure/kubernetes/people-api-reference.json`; sentinel requires digest resolution before apply; `tests/kubernetes-reference.test.mjs` |
| Pod uses Restricted-intent security context and no automatic API token | Active PR | Namespace labels, ServiceAccount, Deployment security contexts and adversarial manifest assertions |
| Pod Security Admission behavior is deterministic rather than implicitly drifting with `latest` | Active PR | `enforce-version`, `audit-version`, and `warn-version` are pinned to `v1.37`; `tests/kubernetes-reference.test.mjs`; exact RED head `6b4fc614b57ec09172b6d029a9ea07d2203ad42e`, run `33344167879`, job `99345037244` |
| Startup/liveness and readiness are not conflated | Active PR + dependency-active PR | Reference sends startup/liveness to `/health` and readiness to `/ready`; People API probe implementation is owned by PR #74 and must be integrated into the selected release image before this manifest can be runnable |
| Namespace traffic is deny-by-default | Active PR | `orgmetra-default-deny` plus exact People API ingress/PostgreSQL/DNS exceptions; network-policy assertions |
| Managed PostgreSQL adaptation cannot silently broaden egress | Active PR | `infrastructure/kubernetes/README.md` requires provider-approved exact private-network adaptation while preserving default deny |
| Voluntary disruption and rollout are bounded | Active PR | two replicas, `maxUnavailable: 0` rolling update, PDB `maxUnavailable: 1`, topology-spread preference |
| Target cluster validates object schemas/admission before deployment | Active PR | documented `kubectl apply --dry-run=server ...` precondition; actual target-cluster dry-run remains environment-specific release evidence |
| Release candidate has reproducible source/SBOM/provenance evidence | Dependency-active PR | PR #78; this branch does not duplicate its builder or evidence |
| Image/container build, signed attestation and verified deployable digest exist | Planned | must be produced from one accepted integrated protected head; sentinel intentionally keeps this reference non-runnable until then |
| Production metrics, ingress/TLS, secrets delivery, autoscaling and environment-specific SLOs are accepted | Planned | separate deployment/operability slices; not claimed here |

## RED → repair evidence

The initial exact RED head `18778945f2bdb9d6f42cebd7a3c71c18dad36352` materialized Kubernetes Reference Quality run `32564001046`, job `97009809481`. The job proved exact checkout of that SHA and failed in the first contract step because `infrastructure/kubernetes/people-api-reference.json` and `infrastructure/kubernetes/README.md` did not exist. Six deployment-contract tests failed with `ENOENT`; repository validation and clean-checkout proof were therefore correctly skipped rather than treated as passing evidence.

A second acquisition-grade regression at exact head `6b4fc614b57ec09172b6d029a9ea07d2203ad42e` materialized run `33344167879`, job `99345037244`, proved exact checkout, and produced eight passing tests plus one intentional failure because `pod-security.kubernetes.io/enforce-version` was absent (`undefined` versus expected `v1.37`). The repair pins all three Pod Security Admission modes (`enforce`, `audit`, `warn`) to the authored Kubernetes minor and documents deliberate re-baselining for a target cluster on a different minor.

The repair adds only Orgmetra-owned reference-deployment artifacts and supporting evidence. It does not mutate a dedicated-writer CWL dependency, add cross-service SQL, publish an image, create cluster resources, or claim that a target cluster has accepted the objects.

## Release boundary

A release operator must replace the image sentinel only with a verified digest from the same exact integrated protected revision that contains the required People API probe implementation and passes all applicable build, security, provenance, review, migration, rollback/recovery and target-environment checks together. The checked-in reference itself is therefore buyer-readable deployment intent, not release authorization.
58 changes: 58 additions & 0 deletions infrastructure/kubernetes/README.md
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Orgmetra Kubernetes reference deployment

This directory contains a provider-neutral **reference**, not a release artifact. Applying it does not authorize a release, does not certify a cluster, and does not replace environment-specific threat modelling or change approval.

## Release precondition: immutable image identity

`people-api-reference.json` deliberately contains a non-runnable image sentinel. Before any server-side apply or rollout, replace it with an Orgmetra People API image qualified by a **verified 64-character lowercase SHA-256 image digest**:

```text
ghcr.io/contextualwisdomlab/orgmetra-people-api@sha256:<64-lowercase-hex>
```

The digest must be resolved from the same integrated protected source revision that passed the applicable build, security, SBOM, provenance, migration, recovery, review and release-authorization gates. A mutable tag is not an acceptable substitute. The current repository reference does not publish such an image and therefore must remain non-runnable until that evidence exists.

The probe paths also assume the selected image contains the governed People API `/health` and `/ready` contracts. Do not deploy a protected revision that predates those endpoints merely to satisfy the manifest shape.

## Pod hardening

The `orgmetra-system` namespace declares `pod-security.kubernetes.io/enforce=restricted` and matching `audit`/`warn` Restricted Pod Security Admission labels. It pins the policy contract with `pod-security.kubernetes.io/enforce-version=v1.37`, `pod-security.kubernetes.io/audit-version=v1.37`, and `pod-security.kubernetes.io/warn-version=v1.37`. The explicit version labels are deliberate: an omitted version uses the admission controller's `latest` policy, which can change the effective Restricted contract after a Kubernetes upgrade. The People API pod is non-root, uses `RuntimeDefault` seccomp, disables service-account token automount, privilege escalation, privileged mode and host namespaces, drops every Linux capability, and uses a read-only root filesystem. Because the root filesystem is read-only, the pod declares a dedicated `tmp-scratch` `emptyDir` mounted at `/tmp`; do not remove it and do not replace it with a `hostPath`.

Cluster operators must verify that admission controls actually enforce the intended Restricted profile. A target cluster whose supported policy minor differs from `v1.37` must not make the reference deployable by deleting or weakening the version labels. Re-baseline the policy deliberately against that cluster's authoritative Kubernetes documentation, update the pinned minor and regression evidence together, and prove the resulting objects with server-side dry-run before release. If the environment injects sidecars or init containers, those injected containers must independently satisfy the same effective policy.

## Liveness and readiness

- startup and liveness use `GET /health`, which is process-liveness only;
- readiness uses `GET /ready`, which checks the People API's owned PostgreSQL dependency;
- dependency failure removes a pod from service traffic rather than making liveness depend on PostgreSQL.

The timing values are bounded reference defaults, not universal tuning values. Validate them against measured startup and dependency-recovery behaviour before production use.

## Network isolation

The namespace starts from default-deny ingress and egress. The People API policy then permits only:

1. TCP/8080 ingress from same-namespace pods explicitly labelled `orgmetra.cwl/people-api-client=true`;
2. TCP/8080 ingress from the kubelet probe source range, modelled by the RFC 5737 TEST-NET-1 placeholder `192.0.2.0/24`. **Replace that `ipBlock.cidr` with the exact node CIDR your cluster's kubelet probes originate from** (or the documented per-node ranges); without it, a default-deny CNI drops HTTP health probes and every pod fails liveness;
3. TCP/5432 egress to same-namespace pods labelled `app.kubernetes.io/name=orgmetra-postgres`;
4. DNS to kube-system pods labelled `k8s-app=kube-dns` over UDP/TCP 53.

A **NetworkPolicy-capable CNI** is required. If the selected cluster networking implementation does not enforce Kubernetes NetworkPolicy, do not claim that this reference provides network isolation.

The checked-in PostgreSQL rule models an in-cluster owned database. For **managed PostgreSQL**, replace the database egress rule with the provider-approved private-network policy for the exact database endpoints while preserving default-deny semantics. Do not broaden egress to `0.0.0.0/0` as a convenience workaround. Likewise, adapt the DNS selector only to the cluster's authoritative DNS implementation and keep that exception narrowly scoped.

Keyverse, Naruon and other dedicated-writer CWL services are intentionally absent from this egress policy. Add a foreign-service network path only when a published adapter/API contract and environment-specific authorization design require it; never add cross-service application-table access.

## Availability boundary

The reference uses two replicas, a rolling update with `maxUnavailable: 0`, and a PodDisruptionBudget with `maxUnavailable: 1`. The PDB constrains voluntary disruption only; it does not protect against node failure or application failure. A topology-spread preference reduces accidental same-node concentration but does not claim multi-zone disaster tolerance.

## Pre-deployment verification

Do not apply the reference unchanged. After resolving the exact image digest and cluster-specific database/DNS networking, validate the candidate against the target API server:

```bash
kubectl apply --dry-run=server -f infrastructure/kubernetes/people-api-reference.json

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Fresh-cluster validation always fails

Without orgmetra-system, kubectl apply --dry-run=server validates but never creates the namespace. Every following namespaced resource then fails as missing.

Prompt for agents
The documented server-side dry-run command processes the Namespace and then the namespaced resources separately. On a fresh target cluster, the dry-run Namespace request is not persisted, so admission rejects the remaining resources because orgmetra-system does not exist. Revise the pre-deployment workflow to account for namespace bootstrapping while preserving the stated no-release/no-unreviewed-change boundary. Update the Kubernetes README, any corresponding traceability claim, and regression coverage so the documented verification works both when the namespace already exists and during first installation.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

```

Then verify, at minimum, the target cluster's admission policy, NetworkPolicy enforcement, available resource quotas, image-pull authorization, probe behaviour, disruption semantics, PostgreSQL connectivity, migration compatibility, rollback/recovery procedure and immutable release evidence. A successful dry-run is necessary evidence for the target cluster but is not sufficient release authorization.
Loading
Loading