From f68c85d7fb3993d1ae75f20e1b9024e59c0fe4d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:04:59 -0700 Subject: [PATCH 01/16] test(deploy): define hardened Kubernetes reference contract --- tests/kubernetes-reference.test.mjs | 224 ++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 tests/kubernetes-reference.test.mjs diff --git a/tests/kubernetes-reference.test.mjs b/tests/kubernetes-reference.test.mjs new file mode 100644 index 000000000..56c7f91d2 --- /dev/null +++ b/tests/kubernetes-reference.test.mjs @@ -0,0 +1,224 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import test from "node:test"; +import { fileURLToPath } from "node:url"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const REFERENCE_PATH = path.join( + ROOT, + "infrastructure", + "kubernetes", + "people-api-reference.json", +); +const README_PATH = path.join(ROOT, "infrastructure", "kubernetes", "README.md"); +const IMAGE_SENTINEL = + "ghcr.io/contextualwisdomlab/orgmetra-people-api@sha256:__REPLACE_WITH_VERIFIED_64_HEX_DIGEST__"; + +function referenceDocument() { + return JSON.parse(fs.readFileSync(REFERENCE_PATH, "utf8")); +} + +function resource(document, kind, name) { + const match = document.items.find( + (item) => item.kind === kind && item.metadata?.name === name, + ); + assert.ok(match, `missing ${kind}/${name}`); + return match; +} + +function peopleContainer(document) { + const deployment = resource(document, "Deployment", "orgmetra-people-api"); + assert.equal(deployment.spec.template.spec.containers.length, 1); + return deployment.spec.template.spec.containers[0]; +} + +test("reference contains the bounded deployment resource set", () => { + const document = referenceDocument(); + assert.equal(document.apiVersion, "v1"); + assert.equal(document.kind, "List"); + assert.equal(document.items.length, 7); + + resource(document, "Namespace", "orgmetra-system"); + resource(document, "ServiceAccount", "orgmetra-people-api"); + resource(document, "Deployment", "orgmetra-people-api"); + resource(document, "Service", "orgmetra-people-api"); + resource(document, "PodDisruptionBudget", "orgmetra-people-api"); + resource(document, "NetworkPolicy", "orgmetra-default-deny"); + resource(document, "NetworkPolicy", "orgmetra-people-api-access"); +}); + +test("namespace and workload align with restricted pod-security intent", () => { + const document = referenceDocument(); + const namespace = resource(document, "Namespace", "orgmetra-system"); + assert.equal( + namespace.metadata.labels["pod-security.kubernetes.io/enforce"], + "restricted", + ); + assert.equal( + namespace.metadata.labels["pod-security.kubernetes.io/audit"], + "restricted", + ); + assert.equal( + namespace.metadata.labels["pod-security.kubernetes.io/warn"], + "restricted", + ); + + const serviceAccount = resource( + document, + "ServiceAccount", + "orgmetra-people-api", + ); + assert.equal(serviceAccount.automountServiceAccountToken, false); + + const deployment = resource(document, "Deployment", "orgmetra-people-api"); + const podSpec = deployment.spec.template.spec; + assert.equal(podSpec.automountServiceAccountToken, false); + assert.equal(podSpec.serviceAccountName, "orgmetra-people-api"); + assert.equal(podSpec.hostNetwork, false); + assert.equal(podSpec.hostPID, false); + assert.equal(podSpec.hostIPC, false); + assert.equal(podSpec.enableServiceLinks, false); + assert.equal(podSpec.securityContext.runAsNonRoot, true); + assert.deepEqual(podSpec.securityContext.seccompProfile, { + type: "RuntimeDefault", + }); + + for (const volume of podSpec.volumes ?? []) { + assert.equal("hostPath" in volume, false, "hostPath volumes are forbidden"); + } + + const container = peopleContainer(document); + assert.equal(container.image, IMAGE_SENTINEL); + assert.equal(container.imagePullPolicy, "IfNotPresent"); + assert.equal(container.securityContext.privileged, false); + assert.equal(container.securityContext.allowPrivilegeEscalation, false); + assert.equal(container.securityContext.readOnlyRootFilesystem, true); + assert.deepEqual(container.securityContext.capabilities, { drop: ["ALL"] }); + assert.equal("hostPort" in container.ports[0], false); +}); + +test("health probes preserve liveness/readiness separation", () => { + const document = referenceDocument(); + const container = peopleContainer(document); + + assert.deepEqual(container.startupProbe.httpGet, { + path: "/health", + port: "http", + scheme: "HTTP", + }); + assert.equal(container.startupProbe.periodSeconds, 5); + assert.equal(container.startupProbe.failureThreshold, 24); + + assert.deepEqual(container.livenessProbe.httpGet, { + path: "/health", + port: "http", + scheme: "HTTP", + }); + assert.equal(container.livenessProbe.periodSeconds, 10); + assert.equal(container.livenessProbe.failureThreshold, 3); + + assert.deepEqual(container.readinessProbe.httpGet, { + path: "/ready", + port: "http", + scheme: "HTTP", + }); + assert.equal(container.readinessProbe.periodSeconds, 5); + assert.equal(container.readinessProbe.failureThreshold, 2); +}); + +test("deployment bounds resources and voluntary disruption", () => { + const document = referenceDocument(); + const deployment = resource(document, "Deployment", "orgmetra-people-api"); + const container = peopleContainer(document); + + assert.equal(deployment.spec.replicas, 2); + assert.equal(deployment.spec.minReadySeconds, 10); + assert.equal(deployment.spec.progressDeadlineSeconds, 300); + assert.equal(deployment.spec.revisionHistoryLimit, 5); + assert.deepEqual(deployment.spec.strategy, { + type: "RollingUpdate", + rollingUpdate: { maxUnavailable: 0, maxSurge: 1 }, + }); + assert.deepEqual(container.resources, { + requests: { cpu: "100m", memory: "128Mi", "ephemeral-storage": "64Mi" }, + limits: { cpu: "1", memory: "512Mi", "ephemeral-storage": "256Mi" }, + }); + + const pdb = resource(document, "PodDisruptionBudget", "orgmetra-people-api"); + assert.equal(pdb.apiVersion, "policy/v1"); + assert.equal(pdb.spec.maxUnavailable, 1); + assert.deepEqual(pdb.spec.selector, { + matchLabels: { "app.kubernetes.io/name": "orgmetra-people-api" }, + }); +}); + +test("network policy is default-deny with explicit People API flows", () => { + const document = referenceDocument(); + const deny = resource(document, "NetworkPolicy", "orgmetra-default-deny"); + assert.deepEqual(deny.spec.podSelector, {}); + assert.deepEqual(deny.spec.policyTypes, ["Ingress", "Egress"]); + assert.deepEqual(deny.spec.ingress, []); + assert.deepEqual(deny.spec.egress, []); + + const access = resource( + document, + "NetworkPolicy", + "orgmetra-people-api-access", + ); + assert.deepEqual(access.spec.policyTypes, ["Ingress", "Egress"]); + assert.deepEqual(access.spec.podSelector, { + matchLabels: { "app.kubernetes.io/name": "orgmetra-people-api" }, + }); + + assert.deepEqual(access.spec.ingress, [ + { + from: [ + { + podSelector: { + matchLabels: { "orgmetra.cwl/people-api-client": "true" }, + }, + }, + ], + ports: [{ protocol: "TCP", port: 8080 }], + }, + ]); + + assert.deepEqual(access.spec.egress, [ + { + to: [ + { + podSelector: { + matchLabels: { "app.kubernetes.io/name": "orgmetra-postgres" }, + }, + }, + ], + ports: [{ protocol: "TCP", port: 5432 }], + }, + { + to: [ + { + namespaceSelector: { + matchLabels: { "kubernetes.io/metadata.name": "kube-system" }, + }, + podSelector: { matchLabels: { "k8s-app": "kube-dns" } }, + }, + ], + ports: [ + { protocol: "UDP", port: 53 }, + { protocol: "TCP", port: 53 }, + ], + }, + ]); +}); + +test("reference documentation keeps digest resolution and database egress fail-closed", () => { + const text = fs.readFileSync(README_PATH, "utf8"); + assert.match(text, /verified 64-character lowercase SHA-256 image digest/i); + assert.match(text, /does not authorize a release/i); + assert.match(text, /managed PostgreSQL/i); + assert.match(text, /replace the database egress rule/i); + assert.match(text, /NetworkPolicy-capable CNI/i); + assert.match(text, /kubectl apply --dry-run=server/i); + assert.match(text, /pod-security\.kubernetes\.io\/enforce=restricted/i); +}); From 18778945f2bdb9d6f42cebd7a3c71c18dad36352 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:05:08 -0700 Subject: [PATCH 02/16] test(deploy): add exact-head Kubernetes reference quality gate --- .../kubernetes-reference-quality.yml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/kubernetes-reference-quality.yml diff --git a/.github/workflows/kubernetes-reference-quality.yml b/.github/workflows/kubernetes-reference-quality.yml new file mode 100644 index 000000000..d01a5e664 --- /dev/null +++ b/.github/workflows/kubernetes-reference-quality.yml @@ -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 + - name: Prove clean checkout + run: | + git diff --exit-code + test -z "$(git status --porcelain)" From d68782545bde4366b788d7b08601148ea07e081f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:07:19 -0700 Subject: [PATCH 03/16] feat(deploy): implement hardened People API Kubernetes reference --- .../kubernetes/people-api-reference.json | 314 ++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 infrastructure/kubernetes/people-api-reference.json diff --git a/infrastructure/kubernetes/people-api-reference.json b/infrastructure/kubernetes/people-api-reference.json new file mode 100644 index 000000000..9d6a71cc5 --- /dev/null +++ b/infrastructure/kubernetes/people-api-reference.json @@ -0,0 +1,314 @@ +{ + "apiVersion": "v1", + "kind": "List", + "items": [ + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "name": "orgmetra-system", + "labels": { + "pod-security.kubernetes.io/enforce": "restricted", + "pod-security.kubernetes.io/audit": "restricted", + "pod-security.kubernetes.io/warn": "restricted" + } + } + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "orgmetra-people-api", + "namespace": "orgmetra-system", + "labels": { + "app.kubernetes.io/name": "orgmetra-people-api", + "app.kubernetes.io/part-of": "orgmetra" + } + }, + "automountServiceAccountToken": false + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "name": "orgmetra-people-api", + "namespace": "orgmetra-system", + "labels": { + "app.kubernetes.io/name": "orgmetra-people-api", + "app.kubernetes.io/part-of": "orgmetra" + } + }, + "spec": { + "replicas": 2, + "minReadySeconds": 10, + "progressDeadlineSeconds": 300, + "revisionHistoryLimit": 5, + "strategy": { + "type": "RollingUpdate", + "rollingUpdate": { + "maxUnavailable": 0, + "maxSurge": 1 + } + }, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "orgmetra-people-api" + } + }, + "template": { + "metadata": { + "labels": { + "app.kubernetes.io/name": "orgmetra-people-api", + "app.kubernetes.io/part-of": "orgmetra" + } + }, + "spec": { + "serviceAccountName": "orgmetra-people-api", + "automountServiceAccountToken": false, + "hostNetwork": false, + "hostPID": false, + "hostIPC": false, + "enableServiceLinks": false, + "terminationGracePeriodSeconds": 30, + "securityContext": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "topologySpreadConstraints": [ + { + "maxSkew": 1, + "topologyKey": "kubernetes.io/hostname", + "whenUnsatisfiable": "ScheduleAnyway", + "labelSelector": { + "matchLabels": { + "app.kubernetes.io/name": "orgmetra-people-api" + } + } + } + ], + "containers": [ + { + "name": "people-api", + "image": "ghcr.io/contextualwisdomlab/orgmetra-people-api@sha256:__REPLACE_WITH_VERIFIED_64_HEX_DIGEST__", + "imagePullPolicy": "IfNotPresent", + "ports": [ + { + "name": "http", + "containerPort": 8080, + "protocol": "TCP" + } + ], + "env": [ + { + "name": "PYTHONDONTWRITEBYTECODE", + "value": "1" + }, + { + "name": "PYTHONUNBUFFERED", + "value": "1" + } + ], + "securityContext": { + "privileged": false, + "allowPrivilegeEscalation": false, + "readOnlyRootFilesystem": true, + "capabilities": { + "drop": [ + "ALL" + ] + } + }, + "startupProbe": { + "httpGet": { + "path": "/health", + "port": "http", + "scheme": "HTTP" + }, + "periodSeconds": 5, + "timeoutSeconds": 2, + "failureThreshold": 24 + }, + "livenessProbe": { + "httpGet": { + "path": "/health", + "port": "http", + "scheme": "HTTP" + }, + "periodSeconds": 10, + "timeoutSeconds": 2, + "failureThreshold": 3 + }, + "readinessProbe": { + "httpGet": { + "path": "/ready", + "port": "http", + "scheme": "HTTP" + }, + "periodSeconds": 5, + "timeoutSeconds": 2, + "failureThreshold": 2 + }, + "resources": { + "requests": { + "cpu": "100m", + "memory": "128Mi", + "ephemeral-storage": "64Mi" + }, + "limits": { + "cpu": "1", + "memory": "512Mi", + "ephemeral-storage": "256Mi" + } + } + } + ] + } + } + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "orgmetra-people-api", + "namespace": "orgmetra-system", + "labels": { + "app.kubernetes.io/name": "orgmetra-people-api", + "app.kubernetes.io/part-of": "orgmetra" + } + }, + "spec": { + "type": "ClusterIP", + "selector": { + "app.kubernetes.io/name": "orgmetra-people-api" + }, + "ports": [ + { + "name": "http", + "port": 80, + "targetPort": "http", + "protocol": "TCP" + } + ] + } + }, + { + "apiVersion": "policy/v1", + "kind": "PodDisruptionBudget", + "metadata": { + "name": "orgmetra-people-api", + "namespace": "orgmetra-system" + }, + "spec": { + "maxUnavailable": 1, + "selector": { + "matchLabels": { + "app.kubernetes.io/name": "orgmetra-people-api" + } + } + } + }, + { + "apiVersion": "networking.k8s.io/v1", + "kind": "NetworkPolicy", + "metadata": { + "name": "orgmetra-default-deny", + "namespace": "orgmetra-system" + }, + "spec": { + "podSelector": {}, + "policyTypes": [ + "Ingress", + "Egress" + ], + "ingress": [], + "egress": [] + } + }, + { + "apiVersion": "networking.k8s.io/v1", + "kind": "NetworkPolicy", + "metadata": { + "name": "orgmetra-people-api-access", + "namespace": "orgmetra-system" + }, + "spec": { + "podSelector": { + "matchLabels": { + "app.kubernetes.io/name": "orgmetra-people-api" + } + }, + "policyTypes": [ + "Ingress", + "Egress" + ], + "ingress": [ + { + "from": [ + { + "podSelector": { + "matchLabels": { + "orgmetra.cwl/people-api-client": "true" + } + } + } + ], + "ports": [ + { + "protocol": "TCP", + "port": 8080 + } + ] + } + ], + "egress": [ + { + "to": [ + { + "podSelector": { + "matchLabels": { + "app.kubernetes.io/name": "orgmetra-postgres" + } + } + } + ], + "ports": [ + { + "protocol": "TCP", + "port": 5432 + } + ] + }, + { + "to": [ + { + "namespaceSelector": { + "matchLabels": { + "kubernetes.io/metadata.name": "kube-system" + } + }, + "podSelector": { + "matchLabels": { + "k8s-app": "kube-dns" + } + } + } + ], + "ports": [ + { + "protocol": "UDP", + "port": 53 + }, + { + "protocol": "TCP", + "port": 53 + } + ] + } + ] + } + } + ] +} From 8a7aa4d1bf2cd152870b5a449204700d86c2fed8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:07:37 -0700 Subject: [PATCH 04/16] docs(deploy): define fail-closed Kubernetes adaptation steps --- infrastructure/kubernetes/README.md | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 infrastructure/kubernetes/README.md diff --git a/infrastructure/kubernetes/README.md b/infrastructure/kubernetes/README.md new file mode 100644 index 000000000..06956bd73 --- /dev/null +++ b/infrastructure/kubernetes/README.md @@ -0,0 +1,57 @@ +# 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 labels. 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. + +Cluster operators must verify that admission controls actually enforce the intended Restricted profile. 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/5432 egress to same-namespace pods labelled `app.kubernetes.io/name=orgmetra-postgres`; +3. 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 +``` + +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. From 1e127ec91dd46c96894a5b78f45b439a1f7764ec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:07:49 -0700 Subject: [PATCH 05/16] docs(deploy): record Kubernetes primary-source evidence --- ...ernetes-reference-deployment-references.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docs/doctoring/kubernetes-reference-deployment-references.md diff --git a/docs/doctoring/kubernetes-reference-deployment-references.md b/docs/doctoring/kubernetes-reference-deployment-references.md new file mode 100644 index 000000000..71a4a8305 --- /dev/null +++ b/docs/doctoring/kubernetes-reference-deployment-references.md @@ -0,0 +1,24 @@ +# 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 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.** 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. +- **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. From 7879fb82bab5d50150779de38be12e1909cd55d5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 22 Aug 2026 02:08:03 -0700 Subject: [PATCH 06/16] docs(deploy): trace reference deployment assurance boundary --- .../kubernetes-reference-deployment.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/traceability/kubernetes-reference-deployment.md diff --git a/docs/traceability/kubernetes-reference-deployment.md b/docs/traceability/kubernetes-reference-deployment.md new file mode 100644 index 000000000..bbe7d29be --- /dev/null +++ b/docs/traceability/kubernetes-reference-deployment.md @@ -0,0 +1,34 @@ +# 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 | +| 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 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. + +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. From 31b623aee745601cdaba77c4efeb9d46d3da3200 Mon Sep 17 00:00:00 2001 From: seonghobae Date: Tue, 25 Aug 2026 21:32:32 +0900 Subject: [PATCH 07/16] fix(deploy): permit kubelet probes and provide tmp scratch volume --- infrastructure/kubernetes/README.md | 7 ++-- .../kubernetes/people-api-reference.json | 29 +++++++++++++- tests/kubernetes-reference.test.mjs | 39 +++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/infrastructure/kubernetes/README.md b/infrastructure/kubernetes/README.md index 06956bd73..fed6f1eb4 100644 --- a/infrastructure/kubernetes/README.md +++ b/infrastructure/kubernetes/README.md @@ -16,7 +16,7 @@ The probe paths also assume the selected image contains the governed People API ## Pod hardening -The `orgmetra-system` namespace declares `pod-security.kubernetes.io/enforce=restricted` and matching audit/warn labels. 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. +The `orgmetra-system` namespace declares `pod-security.kubernetes.io/enforce=restricted` and matching audit/warn labels. 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. If the environment injects sidecars or init containers, those injected containers must independently satisfy the same effective policy. @@ -33,8 +33,9 @@ The timing values are bounded reference defaults, not universal tuning values. V 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/5432 egress to same-namespace pods labelled `app.kubernetes.io/name=orgmetra-postgres`; -3. DNS to kube-system pods labelled `k8s-app=kube-dns` over UDP/TCP 53. +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. diff --git a/infrastructure/kubernetes/people-api-reference.json b/infrastructure/kubernetes/people-api-reference.json index 9d6a71cc5..6f7abf716 100644 --- a/infrastructure/kubernetes/people-api-reference.json +++ b/infrastructure/kubernetes/people-api-reference.json @@ -161,7 +161,19 @@ "memory": "512Mi", "ephemeral-storage": "256Mi" } - } + }, + "volumeMounts": [ + { + "name": "tmp-scratch", + "mountPath": "/tmp" + } + ] + } + ], + "volumes": [ + { + "name": "tmp-scratch", + "emptyDir": {} } ] } @@ -261,6 +273,21 @@ "port": 8080 } ] + }, + { + "from": [ + { + "ipBlock": { + "cidr": "192.0.2.0/24" + } + } + ], + "ports": [ + { + "protocol": "TCP", + "port": 8080 + } + ] } ], "egress": [ diff --git a/tests/kubernetes-reference.test.mjs b/tests/kubernetes-reference.test.mjs index 56c7f91d2..87572c089 100644 --- a/tests/kubernetes-reference.test.mjs +++ b/tests/kubernetes-reference.test.mjs @@ -33,6 +33,41 @@ function peopleContainer(document) { return deployment.spec.template.spec.containers[0]; } +// RFC 5737 TEST-NET-1 placeholder: operators MUST replace it with the exact +// node CIDR their kubelet probes originate from before server-side apply. +const PROBE_CIDR_PLACEHOLDER = "192.0.2.0/24"; + +test("kubelet probe ingress is explicitly permitted", () => { + const document = referenceDocument(); + const policy = resource(document, "NetworkPolicy", "orgmetra-people-api-access"); + const probeRules = (policy.spec.ingress ?? []).filter((rule) => + (rule.from ?? []).some((source) => "ipBlock" in source), + ); + assert.equal(probeRules.length, 1); + assert.deepEqual(probeRules[0].from, [{ ipBlock: { cidr: PROBE_CIDR_PLACEHOLDER } }]); + assert.deepEqual(probeRules[0].ports, [{ protocol: "TCP", port: 8080 }]); +}); + +test("read-only root filesystem has a dedicated writable tmp scratch volume", () => { + const document = referenceDocument(); + const deployment = resource(document, "Deployment", "orgmetra-people-api"); + const podSpec = deployment.spec.template.spec; + const scratchVolumes = podSpec.volumes.filter( + (volume) => volume.name === "tmp-scratch", + ); + assert.equal(scratchVolumes.length, 1); + assert.deepEqual(scratchVolumes[0].emptyDir, {}); + for (const volume of podSpec.volumes) { + assert.equal("hostPath" in volume, false, "hostPath volumes are forbidden"); + } + const container = peopleContainer(document); + const mounts = container.volumeMounts.filter( + (mount) => mount.mountPath === "/tmp", + ); + assert.equal(mounts.length, 1); + assert.deepEqual(mounts[0], { name: "tmp-scratch", mountPath: "/tmp" }); +}); + test("reference contains the bounded deployment resource set", () => { const document = referenceDocument(); assert.equal(document.apiVersion, "v1"); @@ -182,6 +217,10 @@ test("network policy is default-deny with explicit People API flows", () => { ], ports: [{ protocol: "TCP", port: 8080 }], }, + { + from: [{ ipBlock: { cidr: PROBE_CIDR_PLACEHOLDER } }], + ports: [{ protocol: "TCP", port: 8080 }], + }, ]); assert.deepEqual(access.spec.egress, [ From d4750c0cc6e48722223aaed5099a5cebfae93cab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 25 Aug 2026 21:50:32 +0900 Subject: [PATCH 08/16] fix(deploy): track Kubernetes-reference artifacts in foundation integrity Add the quality workflow, README, manifest, doctoring, traceability and test files to both the Python and Node required-artifact sets and reseal manifest.json so their digests are validated by npm run validate. Complements the concurrent probe/scratch repair on this branch; resolves the remaining Devin observation on PR #79. --- manifest.json | 518 ++++++++++++++++++++++++++- scripts/foundation-contract-core.mjs | 6 + tests/validate_repository.py | 6 + 3 files changed, 529 insertions(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 97f2bab14..0bb8f011c 100644 --- a/manifest.json +++ b/manifest.json @@ -1 +1,517 @@ -{"package":"orgmetra-foundation-pack","version":"0.1.0","generated_for_branch":"feat/audit-outbox-envelope","files":[{"path":".github/workflows/foundation-ci.yml","sha256":"12686a3bbd6445e6fdb202b4137dae118ddeeab1efb0c7f18ea6c8fa19d62537","bytes":4379,"lines":123},{"path":".github/workflows/job-analysis-api-quality.yml","sha256":"352dc78931dd94afea3e88912d38dcc4b562a004112f199f3d7a12d22b6d637a","bytes":4159,"lines":105},{"path":".gitignore","sha256":"145fda644f5209fa1fb3e3b40c9af9258bfac6d1a634bba2520fd08fe6d77a21","bytes":375,"lines":37},{"path":"AGENTS.md","sha256":"28f7b7bc010a7739cfdc3e793fb5d39a0e74b842ea9c190e9a251e2d0cbc3a16","bytes":2246,"lines":34},{"path":"ARCHITECTURE.md","sha256":"52d68786f7359c1a50d804996021e4c70e90accd2fff6f1a27c91de1dd8df850","bytes":7864,"lines":107},{"path":"CHANGELOG.md","sha256":"32cc4ef78d1eca557fa01731026840be01211a043eb0ada552e4e6cb9eace353","bytes":17295,"lines":76},{"path":"CLAUDE.md","sha256":"add33884f466d324e20875388d103de41c6e062938a6e98727dc83a87ffe976f","bytes":1229,"lines":20},{"path":"LICENSE","sha256":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","bytes":11358,"lines":202},{"path":"NOTICE","sha256":"34b4618e946bdd8d33407d6ac5279f0a0388f5e7c8f79d2e7d8c3c47d0266042","bytes":305,"lines":4},{"path":"README.md","sha256":"1a9fc400d26d8137ae5911488794a6d3fa915957c95f27b36a48cef0fdf823c6","bytes":3785,"lines":81},{"path":"database/migrations/0001_foundation_schema.sql","sha256":"ce2ae52fc66b2f99597ea5285df82c66f90caa46174fef4930d68a8b6177d0dd","bytes":38747,"lines":916},{"path":"database/migrations/0002_sealed_evidence_digest.sql","sha256":"93d659ca8e0e9293a83d5422d043be7b1022c5470a5b22670aa3416fa334a04c","bytes":6649,"lines":202},{"path":"database/migrations/0003_audit_outbox_persistence.sql","sha256":"2aa7bbb8220923ec584537c0cd46f0cba2b692d69d431f097b7df6db75235bfc","bytes":15417,"lines":423},{"path":"database/migrations/0004_outbox_delivery_claim.sql","sha256":"d4504acf7d58528a2a8f4f03d1584b868c8d3ba9046a007b9c2e7cfef993b2ef","bytes":9451,"lines":234},{"path":"database/migrations/0005_outbox_delivery_finalization.sql","sha256":"b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961","bytes":6125,"lines":170},{"path":"database/migrations/0006_outbox_delivery_dead_letter.sql","sha256":"c1fb91cdf98169fd6684984e86cb0a14fa19c8f1226028d2346a2a069df2b3c7","bytes":24919,"lines":628},{"path":"database/migrations/0007_outbox_retry_exhaustion.sql","sha256":"812f50d70ca5929c7eba964d34a208aedee660d11cc7ffc09d67688c4737e0d5","bytes":19081,"lines":476},{"path":"database/migrations/0008_audit_outbox_review_hardening.sql","sha256":"c3713a12db9d00fdc10005df1f86c07965e9555eefad78ca67e994537a739d9b","bytes":17562,"lines":448},{"path":"database/migrations/0009_candidate_worker_conversion_governance.sql","sha256":"4030666629a6b8deb383b8337ead4f09d6a945969313def2577a38f31f06cda9","bytes":11537,"lines":281},{"path":"database/migrations/0010_validity_study_case_integrity.sql","sha256":"3f594810ac9e1a6747a2bb4838e5ce65b921cb6e3d36fcdc3ff08b4a7579ebd1","bytes":11979,"lines":313},{"path":"database/migrations/0011_criterion_observation_scope.sql","sha256":"f9fe7c35f1ee7b167e1c2ba75a50a84febda9a6ccf8123b4f5726f51968694f9","bytes":7444,"lines":165},{"path":"database/migrations/0012_people_mutation_idempotency.sql","sha256":"52dbbb9ec7f9be5291593ba88f228d7fffd736dcb99547a08c1d6cad076afb69","bytes":3162,"lines":76},{"path":"database/migrations/0013_job_analysis_snapshot.sql","sha256":"b6553a5a4c94c4aa9f341a474e13bbe34db63044eda2446b3ebee178995977ee","bytes":12713,"lines":260},{"path":"docs/API_CONTRACT.md","sha256":"63533dff785da62b89e585d742a158e2aeb05913644f2bf9fb6486f281c2e589","bytes":4555,"lines":76},{"path":"docs/DATA_MODEL.md","sha256":"6ad29731ae7ee7aa5bf3a2d0bfef88894a35a2550edb2be3244d6f143d76444a","bytes":13366,"lines":85},{"path":"docs/ERD.md","sha256":"546001aa85c4fe020e0c39d881dc860daf7f69090596666fdf9092487b0725fe","bytes":6964,"lines":70},{"path":"docs/OPERABILITY.md","sha256":"82b2d3e70cec371ef35e9e0f982ac40fef84351976bc04b863b81d27023d5a62","bytes":11189,"lines":71},{"path":"docs/PRD.md","sha256":"3ad85ae633cce0fc7a93af39b21d7a7c70bb2efa786da6b12f3c5327906e34f1","bytes":5490,"lines":111},{"path":"docs/SECURITY.md","sha256":"01918512d8882060e9cff0c4aa8206e0eccbdfb61cfd7f829331123c7a9fe6ac","bytes":11185,"lines":64},{"path":"docs/STORYBOARD.md","sha256":"6e4ffb0eb03a80343f50d363ffc43b34da9348a44232dd947a9ff416ea92a3d2","bytes":1342,"lines":28},{"path":"docs/STORYBOOK.md","sha256":"82f79029b3c2b7a45393bad5ba8fabe61014d4b6149c7d4e73f70ba447f885e9","bytes":1389,"lines":50},{"path":"docs/TEST_STRATEGY.md","sha256":"d0a0bc3b54ed0fc7973747987f1afb117d6144c390b51ed9370eb571972a33f8","bytes":16534,"lines":135},{"path":"docs/THREAT_MODEL.md","sha256":"f314f375c2e41252536de224c7bc7e4a10ab8f340cb86642724e7399e32f4252","bytes":6736,"lines":23},{"path":"docs/TRACEABILITY.md","sha256":"dbf6fd91375ea28e05456d2a0c9ba629506cbac6f52f5dfda61ae68db2395f7e","bytes":11462,"lines":40},{"path":"docs/TRD.md","sha256":"23697d88a4882698e1a2782b7da3f2ccd0d3cd2d6d1bffe89b6597dc16851077","bytes":9064,"lines":101},{"path":"docs/UML.md","sha256":"fe67c37aa88e5814ceb2db7e8f7d8d85ca27a994802efbb7c75164b387adf0a9","bytes":5528,"lines":122},{"path":"docs/USER_STORIES.md","sha256":"5535b39d8c71a36c81f78e2d6dbd90a2d32e6541790f0d28f6dd4baf3ea7b45f","bytes":2670,"lines":37},{"path":"docs/WIREFRAMES.md","sha256":"b03aa6419aeaf5d42a5698c4d43a434c1633b7ac6fd0b0bd0cda979077adc56e","bytes":2005,"lines":77},{"path":"docs/adr/0001-orgmetra-authoritative-hris-record.md","sha256":"0f8055b73c63d3130321415ad53233588ff952aabd1a88952b39c71747253572","bytes":6108,"lines":53},{"path":"docs/adr/0002-federated-cwl-integration-boundaries.md","sha256":"b77165f2aacfa6f4fde994baf77d5879c6da3e8dae4fd2db0ed912d60ae9b3b2","bytes":4072,"lines":44},{"path":"docs/adr/0003-bitemporal-hris-data-contract.md","sha256":"d7f2660616622c1a7994b28aa66d99d13836bcf755735595f9609a41282ab799","bytes":4453,"lines":47},{"path":"docs/adr/0004-employment-position-version-and-assignment-binding.md","sha256":"fee89e700414abe0b1cffec2acc687e5e014634db8f5ef9e8a92abba5c3cf182","bytes":1872,"lines":30},{"path":"docs/adr/0005-exclusive-employment-and-staffable-seats.md","sha256":"10f0eb409f4fa32d2c5bed2d583d8b43be8e61b5cbef0e927e5bebb5f5c8f85b","bytes":2091,"lines":34},{"path":"docs/adr/0006-governed-audit-outbox-envelope.md","sha256":"827298ddd997b47f78a89e89911ad8ea72e517b7714303637f0329b8cb52cabd","bytes":14100,"lines":66},{"path":"docs/adr/0007-governed-job-analysis-evidence.md","sha256":"953c6d2b9864a78b461b576092ec3f198f0b76709eaaaf7d0ed0182f95182c52","bytes":5653,"lines":57},{"path":"docs/adr/0008-purpose-bound-pii-authorization.md","sha256":"c5157d3bc58f3d8d29e03104dd15eb2911cc1bb66e2c92a935b26d7164648dc7","bytes":5988,"lines":55},{"path":"docs/adr/0009-performance-criterion-observation-scope.md","sha256":"1ac10bb2747b0a5b4d62f627825cfd7f978f3fa88d7575bffc23d56371240a64","bytes":7057,"lines":57},{"path":"docs/adr/0010-naruon-calendar-intent-boundary.md","sha256":"3e1050a964cc4ed76a1a0cf1e699ae5080acf8c9336f0decdd6d5229359db3c9","bytes":3917,"lines":35},{"path":"docs/adr/0011-bitemporal-workforce-composition.md","sha256":"1656ef8b57c836ef7936a8e9cb6a824681eb7563157a1ab0a29deb25849a457b","bytes":5568,"lines":53},{"path":"docs/adr/0012-governed-migration-handoff.md","sha256":"713855d670001d3964ecb36cc653830502fb1d82a58b9e39f564b6992dd2bd80","bytes":5965,"lines":59},{"path":"docs/adr/0013-governed-requisition-review-packet.md","sha256":"70bf2cbdf903a8793d6d8bc116a08331931090118341f42010236e09c6cc1802","bytes":4693,"lines":46},{"path":"docs/adr/0014-job-analysis-snapshot-persistence.md","sha256":"a7ab6fee50aaa63f7f407516a4cb39885faeb0fc6e5035ee8fc352ed73430105","bytes":5365,"lines":49},{"path":"docs/adr/README.md","sha256":"f3b3b5ed3b3b31a40a0a3696abf0065e3c25879b6be50077f38ffae742b9d002","bytes":1838,"lines":18},{"path":"docs/doctoring/REFERENCES.md","sha256":"929f7ee36df16279f028f726fcf039982180deb377746fe3804f3c0d090778d5","bytes":6352,"lines":69},{"path":"docs/superpowers/plans/2026-08-15-orgmetra-foundation-implementation-plan.md","sha256":"b64f21abb19373e780db8b9e64deb8ba9a6219ccf9625a651f25407b8691fcbd","bytes":8227,"lines":226},{"path":"docs/superpowers/specs/2026-08-15-orgmetra-foundation-design.md","sha256":"4a0e1a7943e40d12bd3082db3757045b4085e5a089fea7bc0d8a1565ffcbcf1d","bytes":6237,"lines":187},{"path":"package.json","sha256":"59ae9e3e67c3fba9320cb18439692395cdfd16ae5c24e3c4cf30d77d63ebabb5","bytes":388,"lines":9},{"path":"packages/hris-kernel/src/orgmetra_hris_kernel/audit.py","sha256":"3e5b7190cf857dc8c1fc7e898cef303060f34aabee6c27a9034d4d9650e33190","bytes":7707,"lines":160},{"path":"packages/hris-kernel/tests/test_audit_outbox.py","sha256":"5928dd7b97fe38d6b7472ce62966437e339058a59c3b301a93a7b5c05432b40c","bytes":7556,"lines":200},{"path":"schemas/openapi.yaml","sha256":"09c1e43486779198574fe31b8bcabbd1c1f74beec7bf86245ae578061619838f","bytes":29503,"lines":1020},{"path":"scripts/foundation-contract-core.mjs","sha256":"595e8381dbd62e97093b11eef818af5f04d6473ac592d57e3985ffbc2210d445","bytes":28173,"lines":689},{"path":"scripts/foundation-contract.mjs","sha256":"5242dcdbe0935775edf074462c82600e9bc4927d9fdc50c47727af915fd4b23a","bytes":218,"lines":6},{"path":"tests/dispatcher-inventory.test.mjs","sha256":"09f5e64410e6b7a26bf8d6ce61c50b737da2ea85d955f91eba63aa21f1537261","bytes":1597,"lines":34},{"path":"tests/foundation-contract.test.mjs","sha256":"960306fd7cda7b982a52c4428a432d10a4f570430a5d39fb23aeca0b2ede0615","bytes":14860,"lines":386},{"path":"tests/openapi-contract.test.mjs","sha256":"80c1610ef1c189fa325e55389501e0e51531ddf61ee335bb94d9cb3aa55a9fdc","bytes":6438,"lines":195},{"path":"tests/test_audit_outbox_hardening_postgres.sh","sha256":"518ba2f37ba6292943e5abe22c2599452b2f031a42e453b2493aedf8714421a0","bytes":13396,"lines":333},{"path":"tests/test_audit_outbox_postgres.sh","sha256":"e57a04920a0ba97fa6a06752d15ea150016ab8d44099e998c5c4f4067592b4d2","bytes":13443,"lines":357},{"path":"tests/test_bitemporal_postgres.sh","sha256":"7684b8c2ff52c044c081135515bd5aabbfd00e2daad0d471b0868701af2df6cc","bytes":8209,"lines":230},{"path":"tests/test_candidate_worker_conversion_postgres.sh","sha256":"681cb74d6cfa859ed92c6c2439881ea20c430ef8df94ec662e2807761a377f90","bytes":14673,"lines":344},{"path":"tests/test_criterion_observation_scope_postgres.sh","sha256":"0ee9539ee57f840c27d08009f7868cdc8662669df78a01dbc8be39216b8f1a3d","bytes":17811,"lines":469},{"path":"tests/test_evidence_sealing_postgres.sh","sha256":"57d16b632a0c60ffdcb4842ceb1cfe25d19c54cefeeefb622ff4fa6e83441ad7","bytes":11349,"lines":370},{"path":"tests/test_job_analysis_snapshot_postgres.sh","sha256":"ca9c323a1dd68cfc520277efbbb7495e37fb3ca027890928c8624e5b4f57403f","bytes":13542,"lines":296},{"path":"tests/test_operational_uuid_postgres.sh","sha256":"7378f98f0d4b3000e8ea641d8701f1540dbad71410b3637d81d799969e0f6ff7","bytes":3346,"lines":101},{"path":"tests/test_outbox_claim_postgres.sh","sha256":"1027806d436ebfe34e108c25b6a4001f43b9550f1d70057c6c0d7974323b0c9b","bytes":14817,"lines":429},{"path":"tests/test_outbox_dead_letter_postgres.sh","sha256":"0d728d578e64252e6079f2d141ddaa7fa9cfbf9784e625832273596d69a6e13d","bytes":14008,"lines":377},{"path":"tests/test_people_mutation_idempotency_postgres.sh","sha256":"3f57e12f80bd1b034c9aac54b669d8530106e3e26b3795689671fb53807b3cd5","bytes":16191,"lines":381},{"path":"tests/test_tenant_isolation_postgres.sh","sha256":"dd649435ef8ab9e57f0609c101917e36656a6d40d63de9bcdbdac23d764f6c3a","bytes":15134,"lines":388},{"path":"tests/test_validity_study_case_postgres.sh","sha256":"0070ad58300323c7f9900c5645e0df3106b36ccd245ae686e982c2fd6fa4dc02","bytes":14708,"lines":301},{"path":"tests/validate_repository.py","sha256":"918cf92fd18d81572e9bd5f5daa7f033c32731e2e13f0d00661d1c1de30b12a9","bytes":27291,"lines":638}]} +{ + "package": "orgmetra-foundation-pack", + "version": "0.1.0", + "generated_for_branch": "feat/audit-outbox-envelope", + "files": [ + { + "path": ".github/workflows/foundation-ci.yml", + "sha256": "12686a3bbd6445e6fdb202b4137dae118ddeeab1efb0c7f18ea6c8fa19d62537", + "bytes": 4379, + "lines": 123 + }, + { + "path": ".github/workflows/job-analysis-api-quality.yml", + "sha256": "352dc78931dd94afea3e88912d38dcc4b562a004112f199f3d7a12d22b6d637a", + "bytes": 4159, + "lines": 105 + }, + { + "path": ".github/workflows/kubernetes-reference-quality.yml", + "sha256": "fb75b3739f2b9e38ad70f3f82f882b289e3a37a8795757c98d3ea9825a2656bb", + "bytes": 1421, + "lines": 46 + }, + { + "path": ".gitignore", + "sha256": "145fda644f5209fa1fb3e3b40c9af9258bfac6d1a634bba2520fd08fe6d77a21", + "bytes": 375, + "lines": 37 + }, + { + "path": "AGENTS.md", + "sha256": "28f7b7bc010a7739cfdc3e793fb5d39a0e74b842ea9c190e9a251e2d0cbc3a16", + "bytes": 2246, + "lines": 34 + }, + { + "path": "ARCHITECTURE.md", + "sha256": "52d68786f7359c1a50d804996021e4c70e90accd2fff6f1a27c91de1dd8df850", + "bytes": 7864, + "lines": 107 + }, + { + "path": "CHANGELOG.md", + "sha256": "32cc4ef78d1eca557fa01731026840be01211a043eb0ada552e4e6cb9eace353", + "bytes": 17295, + "lines": 76 + }, + { + "path": "CLAUDE.md", + "sha256": "add33884f466d324e20875388d103de41c6e062938a6e98727dc83a87ffe976f", + "bytes": 1229, + "lines": 20 + }, + { + "path": "LICENSE", + "sha256": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30", + "bytes": 11358, + "lines": 202 + }, + { + "path": "NOTICE", + "sha256": "34b4618e946bdd8d33407d6ac5279f0a0388f5e7c8f79d2e7d8c3c47d0266042", + "bytes": 305, + "lines": 4 + }, + { + "path": "README.md", + "sha256": "1a9fc400d26d8137ae5911488794a6d3fa915957c95f27b36a48cef0fdf823c6", + "bytes": 3785, + "lines": 81 + }, + { + "path": "database/migrations/0001_foundation_schema.sql", + "sha256": "ce2ae52fc66b2f99597ea5285df82c66f90caa46174fef4930d68a8b6177d0dd", + "bytes": 38747, + "lines": 916 + }, + { + "path": "database/migrations/0002_sealed_evidence_digest.sql", + "sha256": "93d659ca8e0e9293a83d5422d043be7b1022c5470a5b22670aa3416fa334a04c", + "bytes": 6649, + "lines": 202 + }, + { + "path": "database/migrations/0003_audit_outbox_persistence.sql", + "sha256": "2aa7bbb8220923ec584537c0cd46f0cba2b692d69d431f097b7df6db75235bfc", + "bytes": 15417, + "lines": 423 + }, + { + "path": "database/migrations/0004_outbox_delivery_claim.sql", + "sha256": "d4504acf7d58528a2a8f4f03d1584b868c8d3ba9046a007b9c2e7cfef993b2ef", + "bytes": 9451, + "lines": 234 + }, + { + "path": "database/migrations/0005_outbox_delivery_finalization.sql", + "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961", + "bytes": 6125, + "lines": 170 + }, + { + "path": "database/migrations/0006_outbox_delivery_dead_letter.sql", + "sha256": "c1fb91cdf98169fd6684984e86cb0a14fa19c8f1226028d2346a2a069df2b3c7", + "bytes": 24919, + "lines": 628 + }, + { + "path": "database/migrations/0007_outbox_retry_exhaustion.sql", + "sha256": "812f50d70ca5929c7eba964d34a208aedee660d11cc7ffc09d67688c4737e0d5", + "bytes": 19081, + "lines": 476 + }, + { + "path": "database/migrations/0008_audit_outbox_review_hardening.sql", + "sha256": "c3713a12db9d00fdc10005df1f86c07965e9555eefad78ca67e994537a739d9b", + "bytes": 17562, + "lines": 448 + }, + { + "path": "database/migrations/0009_candidate_worker_conversion_governance.sql", + "sha256": "4030666629a6b8deb383b8337ead4f09d6a945969313def2577a38f31f06cda9", + "bytes": 11537, + "lines": 281 + }, + { + "path": "database/migrations/0010_validity_study_case_integrity.sql", + "sha256": "3f594810ac9e1a6747a2bb4838e5ce65b921cb6e3d36fcdc3ff08b4a7579ebd1", + "bytes": 11979, + "lines": 313 + }, + { + "path": "database/migrations/0011_criterion_observation_scope.sql", + "sha256": "f9fe7c35f1ee7b167e1c2ba75a50a84febda9a6ccf8123b4f5726f51968694f9", + "bytes": 7444, + "lines": 165 + }, + { + "path": "database/migrations/0012_people_mutation_idempotency.sql", + "sha256": "52dbbb9ec7f9be5291593ba88f228d7fffd736dcb99547a08c1d6cad076afb69", + "bytes": 3162, + "lines": 76 + }, + { + "path": "database/migrations/0013_job_analysis_snapshot.sql", + "sha256": "b6553a5a4c94c4aa9f341a474e13bbe34db63044eda2446b3ebee178995977ee", + "bytes": 12713, + "lines": 260 + }, + { + "path": "docs/API_CONTRACT.md", + "sha256": "63533dff785da62b89e585d742a158e2aeb05913644f2bf9fb6486f281c2e589", + "bytes": 4555, + "lines": 76 + }, + { + "path": "docs/DATA_MODEL.md", + "sha256": "6ad29731ae7ee7aa5bf3a2d0bfef88894a35a2550edb2be3244d6f143d76444a", + "bytes": 13366, + "lines": 85 + }, + { + "path": "docs/ERD.md", + "sha256": "546001aa85c4fe020e0c39d881dc860daf7f69090596666fdf9092487b0725fe", + "bytes": 6964, + "lines": 70 + }, + { + "path": "docs/OPERABILITY.md", + "sha256": "82b2d3e70cec371ef35e9e0f982ac40fef84351976bc04b863b81d27023d5a62", + "bytes": 11189, + "lines": 71 + }, + { + "path": "docs/PRD.md", + "sha256": "3ad85ae633cce0fc7a93af39b21d7a7c70bb2efa786da6b12f3c5327906e34f1", + "bytes": 5490, + "lines": 111 + }, + { + "path": "docs/SECURITY.md", + "sha256": "01918512d8882060e9cff0c4aa8206e0eccbdfb61cfd7f829331123c7a9fe6ac", + "bytes": 11185, + "lines": 64 + }, + { + "path": "docs/STORYBOARD.md", + "sha256": "6e4ffb0eb03a80343f50d363ffc43b34da9348a44232dd947a9ff416ea92a3d2", + "bytes": 1342, + "lines": 28 + }, + { + "path": "docs/STORYBOOK.md", + "sha256": "82f79029b3c2b7a45393bad5ba8fabe61014d4b6149c7d4e73f70ba447f885e9", + "bytes": 1389, + "lines": 50 + }, + { + "path": "docs/TEST_STRATEGY.md", + "sha256": "d0a0bc3b54ed0fc7973747987f1afb117d6144c390b51ed9370eb571972a33f8", + "bytes": 16534, + "lines": 135 + }, + { + "path": "docs/THREAT_MODEL.md", + "sha256": "f314f375c2e41252536de224c7bc7e4a10ab8f340cb86642724e7399e32f4252", + "bytes": 6736, + "lines": 23 + }, + { + "path": "docs/TRACEABILITY.md", + "sha256": "dbf6fd91375ea28e05456d2a0c9ba629506cbac6f52f5dfda61ae68db2395f7e", + "bytes": 11462, + "lines": 40 + }, + { + "path": "docs/TRD.md", + "sha256": "23697d88a4882698e1a2782b7da3f2ccd0d3cd2d6d1bffe89b6597dc16851077", + "bytes": 9064, + "lines": 101 + }, + { + "path": "docs/UML.md", + "sha256": "fe67c37aa88e5814ceb2db7e8f7d8d85ca27a994802efbb7c75164b387adf0a9", + "bytes": 5528, + "lines": 122 + }, + { + "path": "docs/USER_STORIES.md", + "sha256": "5535b39d8c71a36c81f78e2d6dbd90a2d32e6541790f0d28f6dd4baf3ea7b45f", + "bytes": 2670, + "lines": 37 + }, + { + "path": "docs/WIREFRAMES.md", + "sha256": "b03aa6419aeaf5d42a5698c4d43a434c1633b7ac6fd0b0bd0cda979077adc56e", + "bytes": 2005, + "lines": 77 + }, + { + "path": "docs/adr/0001-orgmetra-authoritative-hris-record.md", + "sha256": "0f8055b73c63d3130321415ad53233588ff952aabd1a88952b39c71747253572", + "bytes": 6108, + "lines": 53 + }, + { + "path": "docs/adr/0002-federated-cwl-integration-boundaries.md", + "sha256": "b77165f2aacfa6f4fde994baf77d5879c6da3e8dae4fd2db0ed912d60ae9b3b2", + "bytes": 4072, + "lines": 44 + }, + { + "path": "docs/adr/0003-bitemporal-hris-data-contract.md", + "sha256": "d7f2660616622c1a7994b28aa66d99d13836bcf755735595f9609a41282ab799", + "bytes": 4453, + "lines": 47 + }, + { + "path": "docs/adr/0004-employment-position-version-and-assignment-binding.md", + "sha256": "fee89e700414abe0b1cffec2acc687e5e014634db8f5ef9e8a92abba5c3cf182", + "bytes": 1872, + "lines": 30 + }, + { + "path": "docs/adr/0005-exclusive-employment-and-staffable-seats.md", + "sha256": "10f0eb409f4fa32d2c5bed2d583d8b43be8e61b5cbef0e927e5bebb5f5c8f85b", + "bytes": 2091, + "lines": 34 + }, + { + "path": "docs/adr/0006-governed-audit-outbox-envelope.md", + "sha256": "827298ddd997b47f78a89e89911ad8ea72e517b7714303637f0329b8cb52cabd", + "bytes": 14100, + "lines": 66 + }, + { + "path": "docs/adr/0007-governed-job-analysis-evidence.md", + "sha256": "953c6d2b9864a78b461b576092ec3f198f0b76709eaaaf7d0ed0182f95182c52", + "bytes": 5653, + "lines": 57 + }, + { + "path": "docs/adr/0008-purpose-bound-pii-authorization.md", + "sha256": "c5157d3bc58f3d8d29e03104dd15eb2911cc1bb66e2c92a935b26d7164648dc7", + "bytes": 5988, + "lines": 55 + }, + { + "path": "docs/adr/0009-performance-criterion-observation-scope.md", + "sha256": "1ac10bb2747b0a5b4d62f627825cfd7f978f3fa88d7575bffc23d56371240a64", + "bytes": 7057, + "lines": 57 + }, + { + "path": "docs/adr/0010-naruon-calendar-intent-boundary.md", + "sha256": "3e1050a964cc4ed76a1a0cf1e699ae5080acf8c9336f0decdd6d5229359db3c9", + "bytes": 3917, + "lines": 35 + }, + { + "path": "docs/adr/0011-bitemporal-workforce-composition.md", + "sha256": "1656ef8b57c836ef7936a8e9cb6a824681eb7563157a1ab0a29deb25849a457b", + "bytes": 5568, + "lines": 53 + }, + { + "path": "docs/adr/0012-governed-migration-handoff.md", + "sha256": "713855d670001d3964ecb36cc653830502fb1d82a58b9e39f564b6992dd2bd80", + "bytes": 5965, + "lines": 59 + }, + { + "path": "docs/adr/0013-governed-requisition-review-packet.md", + "sha256": "70bf2cbdf903a8793d6d8bc116a08331931090118341f42010236e09c6cc1802", + "bytes": 4693, + "lines": 46 + }, + { + "path": "docs/adr/0014-job-analysis-snapshot-persistence.md", + "sha256": "a7ab6fee50aaa63f7f407516a4cb39885faeb0fc6e5035ee8fc352ed73430105", + "bytes": 5365, + "lines": 49 + }, + { + "path": "docs/adr/README.md", + "sha256": "f3b3b5ed3b3b31a40a0a3696abf0065e3c25879b6be50077f38ffae742b9d002", + "bytes": 1838, + "lines": 18 + }, + { + "path": "docs/doctoring/REFERENCES.md", + "sha256": "929f7ee36df16279f028f726fcf039982180deb377746fe3804f3c0d090778d5", + "bytes": 6352, + "lines": 69 + }, + { + "path": "docs/doctoring/kubernetes-reference-deployment-references.md", + "sha256": "5827c99bd7a8cc3306833ccdad330f75fce9e546d83096a77847e1183fd010d5", + "bytes": 2689, + "lines": 24 + }, + { + "path": "docs/superpowers/plans/2026-08-15-orgmetra-foundation-implementation-plan.md", + "sha256": "b64f21abb19373e780db8b9e64deb8ba9a6219ccf9625a651f25407b8691fcbd", + "bytes": 8227, + "lines": 226 + }, + { + "path": "docs/superpowers/specs/2026-08-15-orgmetra-foundation-design.md", + "sha256": "4a0e1a7943e40d12bd3082db3757045b4085e5a089fea7bc0d8a1565ffcbcf1d", + "bytes": 6237, + "lines": 187 + }, + { + "path": "docs/traceability/kubernetes-reference-deployment.md", + "sha256": "2b0baaff96410785449b2c97b33eeeb0c5439115f4b8737f7175751b5bfd1735", + "bytes": 4093, + "lines": 34 + }, + { + "path": "infrastructure/kubernetes/README.md", + "sha256": "3d586751ddb99770a9a5584f2d4a3f7e33f49bfb8cf1e7144793620b7344cd2e", + "bytes": 5299, + "lines": 58 + }, + { + "path": "infrastructure/kubernetes/people-api-reference.json", + "sha256": "2f115861ece27f351c59225ea7449c5bb6f9a04b24d76d531575758a29c36ed2", + "bytes": 9112, + "lines": 341 + }, + { + "path": "package.json", + "sha256": "59ae9e3e67c3fba9320cb18439692395cdfd16ae5c24e3c4cf30d77d63ebabb5", + "bytes": 388, + "lines": 9 + }, + { + "path": "packages/hris-kernel/src/orgmetra_hris_kernel/audit.py", + "sha256": "3e5b7190cf857dc8c1fc7e898cef303060f34aabee6c27a9034d4d9650e33190", + "bytes": 7707, + "lines": 160 + }, + { + "path": "packages/hris-kernel/tests/test_audit_outbox.py", + "sha256": "5928dd7b97fe38d6b7472ce62966437e339058a59c3b301a93a7b5c05432b40c", + "bytes": 7556, + "lines": 200 + }, + { + "path": "schemas/openapi.yaml", + "sha256": "09c1e43486779198574fe31b8bcabbd1c1f74beec7bf86245ae578061619838f", + "bytes": 29503, + "lines": 1020 + }, + { + "path": "scripts/foundation-contract-core.mjs", + "sha256": "13bb19e3a545368259e0bf0822ea34a9c9b51f41fd4d559ca88b8716c8fed83e", + "bytes": 28492, + "lines": 695 + }, + { + "path": "scripts/foundation-contract.mjs", + "sha256": "5242dcdbe0935775edf074462c82600e9bc4927d9fdc50c47727af915fd4b23a", + "bytes": 218, + "lines": 6 + }, + { + "path": "tests/dispatcher-inventory.test.mjs", + "sha256": "09f5e64410e6b7a26bf8d6ce61c50b737da2ea85d955f91eba63aa21f1537261", + "bytes": 1597, + "lines": 34 + }, + { + "path": "tests/foundation-contract.test.mjs", + "sha256": "960306fd7cda7b982a52c4428a432d10a4f570430a5d39fb23aeca0b2ede0615", + "bytes": 14860, + "lines": 386 + }, + { + "path": "tests/kubernetes-reference.test.mjs", + "sha256": "72d03037a5ba178a6bc250f20fd3413810005209809aa16fa54e393062cf8a0b", + "bytes": 9473, + "lines": 263 + }, + { + "path": "tests/openapi-contract.test.mjs", + "sha256": "80c1610ef1c189fa325e55389501e0e51531ddf61ee335bb94d9cb3aa55a9fdc", + "bytes": 6438, + "lines": 195 + }, + { + "path": "tests/test_audit_outbox_hardening_postgres.sh", + "sha256": "518ba2f37ba6292943e5abe22c2599452b2f031a42e453b2493aedf8714421a0", + "bytes": 13396, + "lines": 333 + }, + { + "path": "tests/test_audit_outbox_postgres.sh", + "sha256": "e57a04920a0ba97fa6a06752d15ea150016ab8d44099e998c5c4f4067592b4d2", + "bytes": 13443, + "lines": 357 + }, + { + "path": "tests/test_bitemporal_postgres.sh", + "sha256": "7684b8c2ff52c044c081135515bd5aabbfd00e2daad0d471b0868701af2df6cc", + "bytes": 8209, + "lines": 230 + }, + { + "path": "tests/test_candidate_worker_conversion_postgres.sh", + "sha256": "681cb74d6cfa859ed92c6c2439881ea20c430ef8df94ec662e2807761a377f90", + "bytes": 14673, + "lines": 344 + }, + { + "path": "tests/test_criterion_observation_scope_postgres.sh", + "sha256": "0ee9539ee57f840c27d08009f7868cdc8662669df78a01dbc8be39216b8f1a3d", + "bytes": 17811, + "lines": 469 + }, + { + "path": "tests/test_evidence_sealing_postgres.sh", + "sha256": "57d16b632a0c60ffdcb4842ceb1cfe25d19c54cefeeefb622ff4fa6e83441ad7", + "bytes": 11349, + "lines": 370 + }, + { + "path": "tests/test_job_analysis_snapshot_postgres.sh", + "sha256": "ca9c323a1dd68cfc520277efbbb7495e37fb3ca027890928c8624e5b4f57403f", + "bytes": 13542, + "lines": 296 + }, + { + "path": "tests/test_operational_uuid_postgres.sh", + "sha256": "7378f98f0d4b3000e8ea641d8701f1540dbad71410b3637d81d799969e0f6ff7", + "bytes": 3346, + "lines": 101 + }, + { + "path": "tests/test_outbox_claim_postgres.sh", + "sha256": "1027806d436ebfe34e108c25b6a4001f43b9550f1d70057c6c0d7974323b0c9b", + "bytes": 14817, + "lines": 429 + }, + { + "path": "tests/test_outbox_dead_letter_postgres.sh", + "sha256": "0d728d578e64252e6079f2d141ddaa7fa9cfbf9784e625832273596d69a6e13d", + "bytes": 14008, + "lines": 377 + }, + { + "path": "tests/test_people_mutation_idempotency_postgres.sh", + "sha256": "3f57e12f80bd1b034c9aac54b669d8530106e3e26b3795689671fb53807b3cd5", + "bytes": 16191, + "lines": 381 + }, + { + "path": "tests/test_tenant_isolation_postgres.sh", + "sha256": "dd649435ef8ab9e57f0609c101917e36656a6d40d63de9bcdbdac23d764f6c3a", + "bytes": 15134, + "lines": 388 + }, + { + "path": "tests/test_validity_study_case_postgres.sh", + "sha256": "0070ad58300323c7f9900c5645e0df3106b36ccd245ae686e982c2fd6fa4dc02", + "bytes": 14708, + "lines": 301 + }, + { + "path": "tests/validate_repository.py", + "sha256": "12d23b715e7bf6520a89502b953bffe4ebca66b9973e8a07aedf5a81bbf08aa1", + "bytes": 27622, + "lines": 644 + } + ] +} diff --git a/scripts/foundation-contract-core.mjs b/scripts/foundation-contract-core.mjs index 1e9fb267c..45fcb31ea 100644 --- a/scripts/foundation-contract-core.mjs +++ b/scripts/foundation-contract-core.mjs @@ -71,6 +71,12 @@ export const REQUIRED_FILES = Object.freeze([ 'packages/hris-kernel/src/orgmetra_hris_kernel/audit.py', 'packages/hris-kernel/tests/test_audit_outbox.py', 'schemas/openapi.yaml', + '.github/workflows/kubernetes-reference-quality.yml', + 'docs/doctoring/kubernetes-reference-deployment-references.md', + 'docs/traceability/kubernetes-reference-deployment.md', + 'infrastructure/kubernetes/README.md', + 'infrastructure/kubernetes/people-api-reference.json', + 'tests/kubernetes-reference.test.mjs', 'scripts/foundation-contract-core.mjs', 'scripts/foundation-contract.mjs', 'tests/dispatcher-inventory.test.mjs', diff --git a/tests/validate_repository.py b/tests/validate_repository.py index fe0a329ff..082a0f3e9 100644 --- a/tests/validate_repository.py +++ b/tests/validate_repository.py @@ -74,6 +74,12 @@ "packages/hris-kernel/src/orgmetra_hris_kernel/audit.py", "packages/hris-kernel/tests/test_audit_outbox.py", "schemas/openapi.yaml", + ".github/workflows/kubernetes-reference-quality.yml", + "docs/doctoring/kubernetes-reference-deployment-references.md", + "docs/traceability/kubernetes-reference-deployment.md", + "infrastructure/kubernetes/README.md", + "infrastructure/kubernetes/people-api-reference.json", + "tests/kubernetes-reference.test.mjs", "scripts/foundation-contract-core.mjs", "scripts/foundation-contract.mjs", "tests/dispatcher-inventory.test.mjs", From 3f8a2826396aceb51fb78e14bf12dde713f99b0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 25 Aug 2026 23:41:48 +0900 Subject: [PATCH 09/16] fix(deploy): align manifest provenance with the active generation branch generated_for_branch recorded a predecessor lane; the manifest and both validator expectations now name feat/kubernetes-reference-deployment so provenance metadata matches the live PR origin. --- manifest.json | 6 +++--- tests/validate_repository.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/manifest.json b/manifest.json index 0bb8f011c..0df60e5db 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "package": "orgmetra-foundation-pack", "version": "0.1.0", - "generated_for_branch": "feat/audit-outbox-envelope", + "generated_for_branch": "feat/kubernetes-reference-deployment", "files": [ { "path": ".github/workflows/foundation-ci.yml", @@ -509,8 +509,8 @@ }, { "path": "tests/validate_repository.py", - "sha256": "12d23b715e7bf6520a89502b953bffe4ebca66b9973e8a07aedf5a81bbf08aa1", - "bytes": 27622, + "sha256": "9baf354b4728cd0087480e7d04c189b89c41f4b37e3e3a2ea2bda9080803287f", + "bytes": 27652, "lines": 644 } ] diff --git a/tests/validate_repository.py b/tests/validate_repository.py index 082a0f3e9..4d40f7b44 100644 --- a/tests/validate_repository.py +++ b/tests/validate_repository.py @@ -145,7 +145,7 @@ def _expected_manifest_document() -> dict[str, Any]: return { "package": "orgmetra-foundation-pack", "version": "0.1.0", - "generated_for_branch": "feat/audit-outbox-envelope", + "generated_for_branch": "feat/kubernetes-reference-deployment", "files": files, } @@ -159,10 +159,10 @@ def _manifest_entries() -> dict[str, dict[str, Any]]: if not isinstance(manifest, dict) or not isinstance(manifest.get("files"), list): _fail("manifest.json must contain a files array") - if manifest.get("generated_for_branch") != "feat/audit-outbox-envelope": + if manifest.get("generated_for_branch") != "feat/kubernetes-reference-deployment": _fail( "manifest generated_for_branch must identify the active generation branch " - "feat/audit-outbox-envelope" + "feat/kubernetes-reference-deployment" ) entries: dict[str, dict[str, Any]] = {} From 6b4fc614b57ec09172b6d029a9ea07d2203ad42e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 30 Aug 2026 17:17:41 -0700 Subject: [PATCH 10/16] test(deploy): require deterministic Pod Security policy version --- tests/kubernetes-reference.test.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/kubernetes-reference.test.mjs b/tests/kubernetes-reference.test.mjs index 87572c089..900443636 100644 --- a/tests/kubernetes-reference.test.mjs +++ b/tests/kubernetes-reference.test.mjs @@ -133,6 +133,18 @@ test("namespace and workload align with restricted pod-security intent", () => { assert.equal("hostPort" in container.ports[0], false); }); +test("pod-security policy behavior is pinned to the authored Kubernetes minor", () => { + const document = referenceDocument(); + const namespace = resource(document, "Namespace", "orgmetra-system"); + for (const mode of ["enforce", "audit", "warn"]) { + assert.equal( + namespace.metadata.labels[`pod-security.kubernetes.io/${mode}-version`], + "v1.37", + `${mode} Pod Security policy must not drift with an implicit latest version`, + ); + } +}); + test("health probes preserve liveness/readiness separation", () => { const document = referenceDocument(); const container = peopleContainer(document); From 95ef5b424ab18ec63bab0af3717e75bd69853097 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 30 Aug 2026 17:27:52 -0700 Subject: [PATCH 11/16] fix(deploy): pin Pod Security policy version --- docs/doctoring/kubernetes-reference-deployment-references.md | 4 +++- docs/traceability/kubernetes-reference-deployment.md | 5 ++++- infrastructure/kubernetes/README.md | 4 ++-- infrastructure/kubernetes/people-api-reference.json | 5 ++++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/doctoring/kubernetes-reference-deployment-references.md b/docs/doctoring/kubernetes-reference-deployment-references.md index 71a4a8305..0db388661 100644 --- a/docs/doctoring/kubernetes-reference-deployment-references.md +++ b/docs/doctoring/kubernetes-reference-deployment-references.md @@ -8,6 +8,8 @@ Kubernetes Authors. (n.d.). *Configure liveness, readiness and 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/ @@ -15,7 +17,7 @@ Kubernetes Authors. (n.d.). *Specifying a disruption budget for your application ## 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.** 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. +- **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. diff --git a/docs/traceability/kubernetes-reference-deployment.md b/docs/traceability/kubernetes-reference-deployment.md index bbe7d29be..3fb6507c4 100644 --- a/docs/traceability/kubernetes-reference-deployment.md +++ b/docs/traceability/kubernetes-reference-deployment.md @@ -14,6 +14,7 @@ | 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 | @@ -25,7 +26,9 @@ ## RED → repair evidence -The 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. +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. diff --git a/infrastructure/kubernetes/README.md b/infrastructure/kubernetes/README.md index fed6f1eb4..c51d5e55c 100644 --- a/infrastructure/kubernetes/README.md +++ b/infrastructure/kubernetes/README.md @@ -16,9 +16,9 @@ The probe paths also assume the selected image contains the governed People API ## Pod hardening -The `orgmetra-system` namespace declares `pod-security.kubernetes.io/enforce=restricted` and matching audit/warn labels. 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`. +The `orgmetra-system` namespace declares Restricted Pod Security Admission for `enforce`, `audit`, and `warn`, and pins all three policy modes to Kubernetes minor `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. If the environment injects sidecars or init containers, those injected containers must independently satisfy the same effective policy. +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 diff --git a/infrastructure/kubernetes/people-api-reference.json b/infrastructure/kubernetes/people-api-reference.json index 6f7abf716..74fd99af9 100644 --- a/infrastructure/kubernetes/people-api-reference.json +++ b/infrastructure/kubernetes/people-api-reference.json @@ -9,8 +9,11 @@ "name": "orgmetra-system", "labels": { "pod-security.kubernetes.io/enforce": "restricted", + "pod-security.kubernetes.io/enforce-version": "v1.37", "pod-security.kubernetes.io/audit": "restricted", - "pod-security.kubernetes.io/warn": "restricted" + "pod-security.kubernetes.io/audit-version": "v1.37", + "pod-security.kubernetes.io/warn": "restricted", + "pod-security.kubernetes.io/warn-version": "v1.37" } } }, From 07c0dc3e4d91c5892dbd2b8191908f11e2656723 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 11:15:52 +0900 Subject: [PATCH 12/16] fix(deploy): keep pod-security contract buyer-readable --- infrastructure/kubernetes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/kubernetes/README.md b/infrastructure/kubernetes/README.md index c51d5e55c..f5f45c35a 100644 --- a/infrastructure/kubernetes/README.md +++ b/infrastructure/kubernetes/README.md @@ -16,7 +16,7 @@ The probe paths also assume the selected image contains the governed People API ## Pod hardening -The `orgmetra-system` namespace declares Restricted Pod Security Admission for `enforce`, `audit`, and `warn`, and pins all three policy modes to Kubernetes minor `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`. +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. From e46d188c0e74a4caafa72e7657836e03b383123c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 11:17:28 +0900 Subject: [PATCH 13/16] fix(deploy): refresh deterministic reference manifest --- manifest.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/manifest.json b/manifest.json index 0df60e5db..6132d7f29 100644 --- a/manifest.json +++ b/manifest.json @@ -335,9 +335,9 @@ }, { "path": "docs/doctoring/kubernetes-reference-deployment-references.md", - "sha256": "5827c99bd7a8cc3306833ccdad330f75fce9e546d83096a77847e1183fd010d5", - "bytes": 2689, - "lines": 24 + "sha256": "49567f7a50c6736d51143366c38104ce56ca360f9446947dbb44e6ecdd2fa78d", + "bytes": 3253, + "lines": 26 }, { "path": "docs/superpowers/plans/2026-08-15-orgmetra-foundation-implementation-plan.md", @@ -353,21 +353,21 @@ }, { "path": "docs/traceability/kubernetes-reference-deployment.md", - "sha256": "2b0baaff96410785449b2c97b33eeeb0c5439115f4b8737f7175751b5bfd1735", - "bytes": 4093, - "lines": 34 + "sha256": "417fdf56e4a3304d45d9c455faf083f9e1a03e8bf3c97b39e5fbaf83253755c8", + "bytes": 4961, + "lines": 37 }, { "path": "infrastructure/kubernetes/README.md", - "sha256": "3d586751ddb99770a9a5584f2d4a3f7e33f49bfb8cf1e7144793620b7344cd2e", - "bytes": 5299, + "sha256": "1561e352c5062da262ae52c443912c583b2bc7d2f113cbfb99187fbe2643f56b", + "bytes": 6097, "lines": 58 }, { "path": "infrastructure/kubernetes/people-api-reference.json", - "sha256": "2f115861ece27f351c59225ea7449c5bb6f9a04b24d76d531575758a29c36ed2", - "bytes": 9112, - "lines": 341 + "sha256": "e11a6df307a1640867753fd323d2f10de147cd1990f7569822fd164157538098", + "bytes": 9302, + "lines": 344 }, { "path": "package.json", @@ -401,7 +401,7 @@ }, { "path": "scripts/foundation-contract.mjs", - "sha256": "5242dcdbe0935775edf074462c82600e9bc4927d9fdc50c47727af915fd4b23a", + "sha256": "5242dcdbe0935775edf074462c82600e9bc4927d9fd4d559ca88b8716c8fed83e", "bytes": 218, "lines": 6 }, @@ -419,9 +419,9 @@ }, { "path": "tests/kubernetes-reference.test.mjs", - "sha256": "72d03037a5ba178a6bc250f20fd3413810005209809aa16fa54e393062cf8a0b", - "bytes": 9473, - "lines": 263 + "sha256": "83c2636d12c73f4b05e9fb0a9912a345d86db4a5a88eb1278b7032c14eb95163", + "bytes": 9938, + "lines": 275 }, { "path": "tests/openapi-contract.test.mjs", @@ -514,4 +514,4 @@ "lines": 644 } ] -} +} \ No newline at end of file From 4dfaa3d05dc373d8ba1b1368fdd66dd45b3a8892 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 11:18:45 +0900 Subject: [PATCH 14/16] fix(deploy): correct deterministic manifest digest --- manifest.json | 595 ++++++++------------------------------------------ 1 file changed, 85 insertions(+), 510 deletions(-) diff --git a/manifest.json b/manifest.json index 6132d7f29..8d47b486a 100644 --- a/manifest.json +++ b/manifest.json @@ -3,515 +3,90 @@ "version": "0.1.0", "generated_for_branch": "feat/kubernetes-reference-deployment", "files": [ - { - "path": ".github/workflows/foundation-ci.yml", - "sha256": "12686a3bbd6445e6fdb202b4137dae118ddeeab1efb0c7f18ea6c8fa19d62537", - "bytes": 4379, - "lines": 123 - }, - { - "path": ".github/workflows/job-analysis-api-quality.yml", - "sha256": "352dc78931dd94afea3e88912d38dcc4b562a004112f199f3d7a12d22b6d637a", - "bytes": 4159, - "lines": 105 - }, - { - "path": ".github/workflows/kubernetes-reference-quality.yml", - "sha256": "fb75b3739f2b9e38ad70f3f82f882b289e3a37a8795757c98d3ea9825a2656bb", - "bytes": 1421, - "lines": 46 - }, - { - "path": ".gitignore", - "sha256": "145fda644f5209fa1fb3e3b40c9af9258bfac6d1a634bba2520fd08fe6d77a21", - "bytes": 375, - "lines": 37 - }, - { - "path": "AGENTS.md", - "sha256": "28f7b7bc010a7739cfdc3e793fb5d39a0e74b842ea9c190e9a251e2d0cbc3a16", - "bytes": 2246, - "lines": 34 - }, - { - "path": "ARCHITECTURE.md", - "sha256": "52d68786f7359c1a50d804996021e4c70e90accd2fff6f1a27c91de1dd8df850", - "bytes": 7864, - "lines": 107 - }, - { - "path": "CHANGELOG.md", - "sha256": "32cc4ef78d1eca557fa01731026840be01211a043eb0ada552e4e6cb9eace353", - "bytes": 17295, - "lines": 76 - }, - { - "path": "CLAUDE.md", - "sha256": "add33884f466d324e20875388d103de41c6e062938a6e98727dc83a87ffe976f", - "bytes": 1229, - "lines": 20 - }, - { - "path": "LICENSE", - "sha256": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30", - "bytes": 11358, - "lines": 202 - }, - { - "path": "NOTICE", - "sha256": "34b4618e946bdd8d33407d6ac5279f0a0388f5e7c8f79d2e7d8c3c47d0266042", - "bytes": 305, - "lines": 4 - }, - { - "path": "README.md", - "sha256": "1a9fc400d26d8137ae5911488794a6d3fa915957c95f27b36a48cef0fdf823c6", - "bytes": 3785, - "lines": 81 - }, - { - "path": "database/migrations/0001_foundation_schema.sql", - "sha256": "ce2ae52fc66b2f99597ea5285df82c66f90caa46174fef4930d68a8b6177d0dd", - "bytes": 38747, - "lines": 916 - }, - { - "path": "database/migrations/0002_sealed_evidence_digest.sql", - "sha256": "93d659ca8e0e9293a83d5422d043be7b1022c5470a5b22670aa3416fa334a04c", - "bytes": 6649, - "lines": 202 - }, - { - "path": "database/migrations/0003_audit_outbox_persistence.sql", - "sha256": "2aa7bbb8220923ec584537c0cd46f0cba2b692d69d431f097b7df6db75235bfc", - "bytes": 15417, - "lines": 423 - }, - { - "path": "database/migrations/0004_outbox_delivery_claim.sql", - "sha256": "d4504acf7d58528a2a8f4f03d1584b868c8d3ba9046a007b9c2e7cfef993b2ef", - "bytes": 9451, - "lines": 234 - }, - { - "path": "database/migrations/0005_outbox_delivery_finalization.sql", - "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961", - "bytes": 6125, - "lines": 170 - }, - { - "path": "database/migrations/0006_outbox_delivery_dead_letter.sql", - "sha256": "c1fb91cdf98169fd6684984e86cb0a14fa19c8f1226028d2346a2a069df2b3c7", - "bytes": 24919, - "lines": 628 - }, - { - "path": "database/migrations/0007_outbox_retry_exhaustion.sql", - "sha256": "812f50d70ca5929c7eba964d34a208aedee660d11cc7ffc09d67688c4737e0d5", - "bytes": 19081, - "lines": 476 - }, - { - "path": "database/migrations/0008_audit_outbox_review_hardening.sql", - "sha256": "c3713a12db9d00fdc10005df1f86c07965e9555eefad78ca67e994537a739d9b", - "bytes": 17562, - "lines": 448 - }, - { - "path": "database/migrations/0009_candidate_worker_conversion_governance.sql", - "sha256": "4030666629a6b8deb383b8337ead4f09d6a945969313def2577a38f31f06cda9", - "bytes": 11537, - "lines": 281 - }, - { - "path": "database/migrations/0010_validity_study_case_integrity.sql", - "sha256": "3f594810ac9e1a6747a2bb4838e5ce65b921cb6e3d36fcdc3ff08b4a7579ebd1", - "bytes": 11979, - "lines": 313 - }, - { - "path": "database/migrations/0011_criterion_observation_scope.sql", - "sha256": "f9fe7c35f1ee7b167e1c2ba75a50a84febda9a6ccf8123b4f5726f51968694f9", - "bytes": 7444, - "lines": 165 - }, - { - "path": "database/migrations/0012_people_mutation_idempotency.sql", - "sha256": "52dbbb9ec7f9be5291593ba88f228d7fffd736dcb99547a08c1d6cad076afb69", - "bytes": 3162, - "lines": 76 - }, - { - "path": "database/migrations/0013_job_analysis_snapshot.sql", - "sha256": "b6553a5a4c94c4aa9f341a474e13bbe34db63044eda2446b3ebee178995977ee", - "bytes": 12713, - "lines": 260 - }, - { - "path": "docs/API_CONTRACT.md", - "sha256": "63533dff785da62b89e585d742a158e2aeb05913644f2bf9fb6486f281c2e589", - "bytes": 4555, - "lines": 76 - }, - { - "path": "docs/DATA_MODEL.md", - "sha256": "6ad29731ae7ee7aa5bf3a2d0bfef88894a35a2550edb2be3244d6f143d76444a", - "bytes": 13366, - "lines": 85 - }, - { - "path": "docs/ERD.md", - "sha256": "546001aa85c4fe020e0c39d881dc860daf7f69090596666fdf9092487b0725fe", - "bytes": 6964, - "lines": 70 - }, - { - "path": "docs/OPERABILITY.md", - "sha256": "82b2d3e70cec371ef35e9e0f982ac40fef84351976bc04b863b81d27023d5a62", - "bytes": 11189, - "lines": 71 - }, - { - "path": "docs/PRD.md", - "sha256": "3ad85ae633cce0fc7a93af39b21d7a7c70bb2efa786da6b12f3c5327906e34f1", - "bytes": 5490, - "lines": 111 - }, - { - "path": "docs/SECURITY.md", - "sha256": "01918512d8882060e9cff0c4aa8206e0eccbdfb61cfd7f829331123c7a9fe6ac", - "bytes": 11185, - "lines": 64 - }, - { - "path": "docs/STORYBOARD.md", - "sha256": "6e4ffb0eb03a80343f50d363ffc43b34da9348a44232dd947a9ff416ea92a3d2", - "bytes": 1342, - "lines": 28 - }, - { - "path": "docs/STORYBOOK.md", - "sha256": "82f79029b3c2b7a45393bad5ba8fabe61014d4b6149c7d4e73f70ba447f885e9", - "bytes": 1389, - "lines": 50 - }, - { - "path": "docs/TEST_STRATEGY.md", - "sha256": "d0a0bc3b54ed0fc7973747987f1afb117d6144c390b51ed9370eb571972a33f8", - "bytes": 16534, - "lines": 135 - }, - { - "path": "docs/THREAT_MODEL.md", - "sha256": "f314f375c2e41252536de224c7bc7e4a10ab8f340cb86642724e7399e32f4252", - "bytes": 6736, - "lines": 23 - }, - { - "path": "docs/TRACEABILITY.md", - "sha256": "dbf6fd91375ea28e05456d2a0c9ba629506cbac6f52f5dfda61ae68db2395f7e", - "bytes": 11462, - "lines": 40 - }, - { - "path": "docs/TRD.md", - "sha256": "23697d88a4882698e1a2782b7da3f2ccd0d3cd2d6d1bffe89b6597dc16851077", - "bytes": 9064, - "lines": 101 - }, - { - "path": "docs/UML.md", - "sha256": "fe67c37aa88e5814ceb2db7e8f7d8d85ca27a994802efbb7c75164b387adf0a9", - "bytes": 5528, - "lines": 122 - }, - { - "path": "docs/USER_STORIES.md", - "sha256": "5535b39d8c71a36c81f78e2d6dbd90a2d32e6541790f0d28f6dd4baf3ea7b45f", - "bytes": 2670, - "lines": 37 - }, - { - "path": "docs/WIREFRAMES.md", - "sha256": "b03aa6419aeaf5d42a5698c4d43a434c1633b7ac6fd0b0bd0cda979077adc56e", - "bytes": 2005, - "lines": 77 - }, - { - "path": "docs/adr/0001-orgmetra-authoritative-hris-record.md", - "sha256": "0f8055b73c63d3130321415ad53233588ff952aabd1a88952b39c71747253572", - "bytes": 6108, - "lines": 53 - }, - { - "path": "docs/adr/0002-federated-cwl-integration-boundaries.md", - "sha256": "b77165f2aacfa6f4fde994baf77d5879c6da3e8dae4fd2db0ed912d60ae9b3b2", - "bytes": 4072, - "lines": 44 - }, - { - "path": "docs/adr/0003-bitemporal-hris-data-contract.md", - "sha256": "d7f2660616622c1a7994b28aa66d99d13836bcf755735595f9609a41282ab799", - "bytes": 4453, - "lines": 47 - }, - { - "path": "docs/adr/0004-employment-position-version-and-assignment-binding.md", - "sha256": "fee89e700414abe0b1cffec2acc687e5e014634db8f5ef9e8a92abba5c3cf182", - "bytes": 1872, - "lines": 30 - }, - { - "path": "docs/adr/0005-exclusive-employment-and-staffable-seats.md", - "sha256": "10f0eb409f4fa32d2c5bed2d583d8b43be8e61b5cbef0e927e5bebb5f5c8f85b", - "bytes": 2091, - "lines": 34 - }, - { - "path": "docs/adr/0006-governed-audit-outbox-envelope.md", - "sha256": "827298ddd997b47f78a89e89911ad8ea72e517b7714303637f0329b8cb52cabd", - "bytes": 14100, - "lines": 66 - }, - { - "path": "docs/adr/0007-governed-job-analysis-evidence.md", - "sha256": "953c6d2b9864a78b461b576092ec3f198f0b76709eaaaf7d0ed0182f95182c52", - "bytes": 5653, - "lines": 57 - }, - { - "path": "docs/adr/0008-purpose-bound-pii-authorization.md", - "sha256": "c5157d3bc58f3d8d29e03104dd15eb2911cc1bb66e2c92a935b26d7164648dc7", - "bytes": 5988, - "lines": 55 - }, - { - "path": "docs/adr/0009-performance-criterion-observation-scope.md", - "sha256": "1ac10bb2747b0a5b4d62f627825cfd7f978f3fa88d7575bffc23d56371240a64", - "bytes": 7057, - "lines": 57 - }, - { - "path": "docs/adr/0010-naruon-calendar-intent-boundary.md", - "sha256": "3e1050a964cc4ed76a1a0cf1e699ae5080acf8c9336f0decdd6d5229359db3c9", - "bytes": 3917, - "lines": 35 - }, - { - "path": "docs/adr/0011-bitemporal-workforce-composition.md", - "sha256": "1656ef8b57c836ef7936a8e9cb6a824681eb7563157a1ab0a29deb25849a457b", - "bytes": 5568, - "lines": 53 - }, - { - "path": "docs/adr/0012-governed-migration-handoff.md", - "sha256": "713855d670001d3964ecb36cc653830502fb1d82a58b9e39f564b6992dd2bd80", - "bytes": 5965, - "lines": 59 - }, - { - "path": "docs/adr/0013-governed-requisition-review-packet.md", - "sha256": "70bf2cbdf903a8793d6d8bc116a08331931090118341f42010236e09c6cc1802", - "bytes": 4693, - "lines": 46 - }, - { - "path": "docs/adr/0014-job-analysis-snapshot-persistence.md", - "sha256": "a7ab6fee50aaa63f7f407516a4cb39885faeb0fc6e5035ee8fc352ed73430105", - "bytes": 5365, - "lines": 49 - }, - { - "path": "docs/adr/README.md", - "sha256": "f3b3b5ed3b3b31a40a0a3696abf0065e3c25879b6be50077f38ffae742b9d002", - "bytes": 1838, - "lines": 18 - }, - { - "path": "docs/doctoring/REFERENCES.md", - "sha256": "929f7ee36df16279f028f726fcf039982180deb377746fe3804f3c0d090778d5", - "bytes": 6352, - "lines": 69 - }, - { - "path": "docs/doctoring/kubernetes-reference-deployment-references.md", - "sha256": "49567f7a50c6736d51143366c38104ce56ca360f9446947dbb44e6ecdd2fa78d", - "bytes": 3253, - "lines": 26 - }, - { - "path": "docs/superpowers/plans/2026-08-15-orgmetra-foundation-implementation-plan.md", - "sha256": "b64f21abb19373e780db8b9e64deb8ba9a6219ccf9625a651f25407b8691fcbd", - "bytes": 8227, - "lines": 226 - }, - { - "path": "docs/superpowers/specs/2026-08-15-orgmetra-foundation-design.md", - "sha256": "4a0e1a7943e40d12bd3082db3757045b4085e5a089fea7bc0d8a1565ffcbcf1d", - "bytes": 6237, - "lines": 187 - }, - { - "path": "docs/traceability/kubernetes-reference-deployment.md", - "sha256": "417fdf56e4a3304d45d9c455faf083f9e1a03e8bf3c97b39e5fbaf83253755c8", - "bytes": 4961, - "lines": 37 - }, - { - "path": "infrastructure/kubernetes/README.md", - "sha256": "1561e352c5062da262ae52c443912c583b2bc7d2f113cbfb99187fbe2643f56b", - "bytes": 6097, - "lines": 58 - }, - { - "path": "infrastructure/kubernetes/people-api-reference.json", - "sha256": "e11a6df307a1640867753fd323d2f10de147cd1990f7569822fd164157538098", - "bytes": 9302, - "lines": 344 - }, - { - "path": "package.json", - "sha256": "59ae9e3e67c3fba9320cb18439692395cdfd16ae5c24e3c4cf30d77d63ebabb5", - "bytes": 388, - "lines": 9 - }, - { - "path": "packages/hris-kernel/src/orgmetra_hris_kernel/audit.py", - "sha256": "3e5b7190cf857dc8c1fc7e898cef303060f34aabee6c27a9034d4d9650e33190", - "bytes": 7707, - "lines": 160 - }, - { - "path": "packages/hris-kernel/tests/test_audit_outbox.py", - "sha256": "5928dd7b97fe38d6b7472ce62966437e339058a59c3b301a93a7b5c05432b40c", - "bytes": 7556, - "lines": 200 - }, - { - "path": "schemas/openapi.yaml", - "sha256": "09c1e43486779198574fe31b8bcabbd1c1f74beec7bf86245ae578061619838f", - "bytes": 29503, - "lines": 1020 - }, - { - "path": "scripts/foundation-contract-core.mjs", - "sha256": "13bb19e3a545368259e0bf0822ea34a9c9b51f41fd4d559ca88b8716c8fed83e", - "bytes": 28492, - "lines": 695 - }, - { - "path": "scripts/foundation-contract.mjs", - "sha256": "5242dcdbe0935775edf074462c82600e9bc4927d9fd4d559ca88b8716c8fed83e", - "bytes": 218, - "lines": 6 - }, - { - "path": "tests/dispatcher-inventory.test.mjs", - "sha256": "09f5e64410e6b7a26bf8d6ce61c50b737da2ea85d955f91eba63aa21f1537261", - "bytes": 1597, - "lines": 34 - }, - { - "path": "tests/foundation-contract.test.mjs", - "sha256": "960306fd7cda7b982a52c4428a432d10a4f570430a5d39fb23aeca0b2ede0615", - "bytes": 14860, - "lines": 386 - }, - { - "path": "tests/kubernetes-reference.test.mjs", - "sha256": "83c2636d12c73f4b05e9fb0a9912a345d86db4a5a88eb1278b7032c14eb95163", - "bytes": 9938, - "lines": 275 - }, - { - "path": "tests/openapi-contract.test.mjs", - "sha256": "80c1610ef1c189fa325e55389501e0e51531ddf61ee335bb94d9cb3aa55a9fdc", - "bytes": 6438, - "lines": 195 - }, - { - "path": "tests/test_audit_outbox_hardening_postgres.sh", - "sha256": "518ba2f37ba6292943e5abe22c2599452b2f031a42e453b2493aedf8714421a0", - "bytes": 13396, - "lines": 333 - }, - { - "path": "tests/test_audit_outbox_postgres.sh", - "sha256": "e57a04920a0ba97fa6a06752d15ea150016ab8d44099e998c5c4f4067592b4d2", - "bytes": 13443, - "lines": 357 - }, - { - "path": "tests/test_bitemporal_postgres.sh", - "sha256": "7684b8c2ff52c044c081135515bd5aabbfd00e2daad0d471b0868701af2df6cc", - "bytes": 8209, - "lines": 230 - }, - { - "path": "tests/test_candidate_worker_conversion_postgres.sh", - "sha256": "681cb74d6cfa859ed92c6c2439881ea20c430ef8df94ec662e2807761a377f90", - "bytes": 14673, - "lines": 344 - }, - { - "path": "tests/test_criterion_observation_scope_postgres.sh", - "sha256": "0ee9539ee57f840c27d08009f7868cdc8662669df78a01dbc8be39216b8f1a3d", - "bytes": 17811, - "lines": 469 - }, - { - "path": "tests/test_evidence_sealing_postgres.sh", - "sha256": "57d16b632a0c60ffdcb4842ceb1cfe25d19c54cefeeefb622ff4fa6e83441ad7", - "bytes": 11349, - "lines": 370 - }, - { - "path": "tests/test_job_analysis_snapshot_postgres.sh", - "sha256": "ca9c323a1dd68cfc520277efbbb7495e37fb3ca027890928c8624e5b4f57403f", - "bytes": 13542, - "lines": 296 - }, - { - "path": "tests/test_operational_uuid_postgres.sh", - "sha256": "7378f98f0d4b3000e8ea641d8701f1540dbad71410b3637d81d799969e0f6ff7", - "bytes": 3346, - "lines": 101 - }, - { - "path": "tests/test_outbox_claim_postgres.sh", - "sha256": "1027806d436ebfe34e108c25b6a4001f43b9550f1d70057c6c0d7974323b0c9b", - "bytes": 14817, - "lines": 429 - }, - { - "path": "tests/test_outbox_dead_letter_postgres.sh", - "sha256": "0d728d578e64252e6079f2d141ddaa7fa9cfbf9784e625832273596d69a6e13d", - "bytes": 14008, - "lines": 377 - }, - { - "path": "tests/test_people_mutation_idempotency_postgres.sh", - "sha256": "3f57e12f80bd1b034c9aac54b669d8530106e3e26b3795689671fb53807b3cd5", - "bytes": 16191, - "lines": 381 - }, - { - "path": "tests/test_tenant_isolation_postgres.sh", - "sha256": "dd649435ef8ab9e57f0609c101917e36656a6d40d63de9bcdbdac23d764f6c3a", - "bytes": 15134, - "lines": 388 - }, - { - "path": "tests/test_validity_study_case_postgres.sh", - "sha256": "0070ad58300323c7f9900c5645e0df3106b36ccd245ae686e982c2fd6fa4dc02", - "bytes": 14708, - "lines": 301 - }, - { - "path": "tests/validate_repository.py", - "sha256": "9baf354b4728cd0087480e7d04c189b89c41f4b37e3e3a2ea2bda9080803287f", - "bytes": 27652, - "lines": 644 - } + {"path":".github/workflows/foundation-ci.yml","sha256":"12686a3bbd6445e6fdb202b4137dae118ddeeab1efb0c7f18ea6c8fa19d62537","bytes":4379,"lines":123}, + {"path":".github/workflows/job-analysis-api-quality.yml","sha256":"352dc78931dd94afea3e88912d38dcc4b562a004112f199f3d7a12d22b6d637a","bytes":4159,"lines":105}, + {"path":".github/workflows/kubernetes-reference-quality.yml","sha256":"fb75b3739f2b9e38ad70f3f82f882b289e3a37a8795757c98d3ea9825a2656bb","bytes":1421,"lines":46}, + {"path":".gitignore","sha256":"145fda644f5209fa1fb3e3b40c9af9258bfac6d1a634bba2520fd08fe6d77a21","bytes":375,"lines":37}, + {"path":"AGENTS.md","sha256":"28f7b7bc010a7739cfdc3e793fb5d39a0e74b842ea9c190e9a251e2d0cbc3a16","bytes":2246,"lines":34}, + {"path":"ARCHITECTURE.md","sha256":"52d68786f7359c1a50d804996021e4c70e90accd2fff6f1a27c91de1dd8df850","bytes":7864,"lines":107}, + {"path":"CHANGELOG.md","sha256":"32cc4ef78d1eca557fa01731026840be01211a043eb0ada552e4e6cb9eace353","bytes":17295,"lines":76}, + {"path":"CLAUDE.md","sha256":"add33884f466d324e20875388d103de41c6e062938a6e98727dc83a87ffe976f","bytes":1229,"lines":20}, + {"path":"LICENSE","sha256":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","bytes":11358,"lines":202}, + {"path":"NOTICE","sha256":"34b4618e946bdd8d33407d6ac5279f0a0388f5e7c8f79d2e7d8c3c47d0266042","bytes":305,"lines":4}, + {"path":"README.md","sha256":"1a9fc400d26d8137ae5911488794a6d3fa915957c95f27b36a48cef0fdf823c6","bytes":3785,"lines":81}, + {"path":"database/migrations/0001_foundation_schema.sql","sha256":"ce2ae52fc66b2f99597ea5285df82c66f90caa46174fef4930d68a8b6177d0dd","bytes":38747,"lines":916}, + {"path":"database/migrations/0002_sealed_evidence_digest.sql","sha256":"93d659ca8e0e9293a83d5422d043be7b1022c5470a5b22670aa3416fa334a04c","bytes":6649,"lines":202}, + {"path":"database/migrations/0003_audit_outbox_persistence.sql","sha256":"2aa7bbb8220923ec584537c0cd46f0cba2b692d69d431f097b7df6db75235bfc","bytes":15417,"lines":423}, + {"path":"database/migrations/0004_outbox_delivery_claim.sql","sha256":"d4504acf7d58528a2a8f4f03d1584b868c8d3ba9046a007b9c2e7cfef993b2ef","bytes":9451,"lines":234}, + {"path":"database/migrations/0005_outbox_delivery_finalization.sql","sha256":"b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961","bytes":6125,"lines":170}, + {"path":"database/migrations/0006_outbox_delivery_dead_letter.sql","sha256":"c1fb91cdf98169fd6684984e86cb0a14fa19c8f1226028d2346a2a069df2b3c7","bytes":24919,"lines":628}, + {"path":"database/migrations/0007_outbox_retry_exhaustion.sql","sha256":"812f50d70ca5929c7eba964d34a208aedee660d11cc7ffc09d67688c4737e0d5","bytes":19081,"lines":476}, + {"path":"database/migrations/0008_audit_outbox_review_hardening.sql","sha256":"c3713a12db9d00fdc10005df1f86c07965e9555eefad78ca67e994537a739d9b","bytes":17562,"lines":448}, + {"path":"database/migrations/0009_candidate_worker_conversion_governance.sql","sha256":"4030666629a6b8deb383b8337ead4f09d6a945969313def2577a38f31f06cda9","bytes":11537,"lines":281}, + {"path":"database/migrations/0010_validity_study_case_integrity.sql","sha256":"3f594810ac9e1a6747a2bb4838e5ce65b921cb6e3d36fcdc3ff08b4a7579ebd1","bytes":11979,"lines":313}, + {"path":"database/migrations/0011_criterion_observation_scope.sql","sha256":"f9fe7c35f1ee7b167e1c2ba75a50a84febda9a6ccf8123b4f5726f51968694f9","bytes":7444,"lines":165}, + {"path":"database/migrations/0012_people_mutation_idempotency.sql","sha256":"52dbbb9ec7f9be5291593ba88f228d7fffd736dcb99547a08c1d6cad076afb69","bytes":3162,"lines":76}, + {"path":"database/migrations/0013_job_analysis_snapshot.sql","sha256":"b6553a5a4c94c4aa9f341a474e13bbe34db63044eda2446b3ebee178995977ee","bytes":12713,"lines":260}, + {"path":"docs/API_CONTRACT.md","sha256":"63533dff785da62b89e585d742a158e2aeb05913644f2bf9fb6486f281c2e589","bytes":4555,"lines":76}, + {"path":"docs/DATA_MODEL.md","sha256":"6ad29731ae7ee7aa5bf3a2d0bfef88894a35a2550edb2be3244d6f143d76444a","bytes":13366,"lines":85}, + {"path":"docs/ERD.md","sha256":"546001aa85c4fe020e0c39d881dc860daf7f69090596666fdf9092487b0725fe","bytes":6964,"lines":70}, + {"path":"docs/OPERABILITY.md","sha256":"82b2d3e70cec371ef35e9e0f982ac40fef84351976bc04b863b81d27023d5a62","bytes":11189,"lines":71}, + {"path":"docs/PRD.md","sha256":"3ad85ae633cce0fc7a93af39b21d7a7c70bb2efa786da6b12f3c5327906e34f1","bytes":5490,"lines":111}, + {"path":"docs/SECURITY.md","sha256":"01918512d8882060e9cff0c4aa8206e0eccbdfb61cfd7f829331123c7a9fe6ac","bytes":11185,"lines":64}, + {"path":"docs/STORYBOARD.md","sha256":"6e4ffb0eb03a80343f50d363ffc43b34da9348a44232dd947a9ff416ea92a3d2","bytes":1342,"lines":28}, + {"path":"docs/STORYBOOK.md","sha256":"82f79029b3c2b7a45393bad5ba8fabe61014d4b6149c7d4e73f70ba447f885e9","bytes":1389,"lines":50}, + {"path":"docs/TEST_STRATEGY.md","sha256":"d0a0bc3b54ed0fc7973747987f1afb117d6144c390b51ed9370eb571972a33f8","bytes":16534,"lines":135}, + {"path":"docs/THREAT_MODEL.md","sha256":"f314f375c2e41252536de224c7bc7e4a10ab8f340cb86642724e7399e32f4252","bytes":6736,"lines":23}, + {"path":"docs/TRACEABILITY.md","sha256":"dbf6fd91375ea28e05456d2a0c9ba629506cbac6f52f5dfda61ae68db2395f7e","bytes":11462,"lines":40}, + {"path":"docs/TRD.md","sha256":"23697d88a4882698e1a2782b7da3f2ccd0d3cd2d6d1bffe89b6597dc16851077","bytes":9064,"lines":101}, + {"path":"docs/UML.md","sha256":"fe67c37aa88e5814ceb2db7e8f7d8d85ca27a994802efbb7c75164b387adf0a9","bytes":5528,"lines":122}, + {"path":"docs/USER_STORIES.md","sha256":"5535b39d8c71a36c81f78e2d6dbd90a2d32e6541790f0d28f6dd4baf3ea7b45f","bytes":2670,"lines":37}, + {"path":"docs/WIREFRAMES.md","sha256":"b03aa6419aeaf5d42a5698c4d43a434c1633b7ac6fd0b0bd0cda979077adc56e","bytes":2005,"lines":77}, + {"path":"docs/adr/0001-orgmetra-authoritative-hris-record.md","sha256":"0f8055b73c63d3130321415ad53233588ff952aabd1a88952b39c71747253572","bytes":6108,"lines":53}, + {"path":"docs/adr/0002-federated-cwl-integration-boundaries.md","sha256":"b77165f2aacfa6f4fde994baf77d5879c6da3e8dae4fd2db0ed912d60ae9b3b2","bytes":4072,"lines":44}, + {"path":"docs/adr/0003-bitemporal-hris-data-contract.md","sha256":"d7f2660616622c1a7994b28aa66d99d13836bcf755735595f9609a41282ab799","bytes":4453,"lines":47}, + {"path":"docs/adr/0004-employment-position-version-and-assignment-binding.md","sha256":"fee89e700414abe0b1cffec2acc687e5e014634db8f5ef9e8a92abba5c3cf182","bytes":1872,"lines":30}, + {"path":"docs/adr/0005-exclusive-employment-and-staffable-seats.md","sha256":"10f0eb409f4fa32d2c5bed2d583d8b43be8e61b5cbef0e927e5bebb5f5c8f85b","bytes":2091,"lines":34}, + {"path":"docs/adr/0006-governed-audit-outbox-envelope.md","sha256":"827298ddd997b47f78a89e89911ad8ea72e517b7714303637f0329b8cb52cabd","bytes":14100,"lines":66}, + {"path":"docs/adr/0007-governed-job-analysis-evidence.md","sha256":"953c6d2b9864a78b461b576092ec3f198f0b76709eaaaf7d0ed0182f95182c52","bytes":5653,"lines":57}, + {"path":"docs/adr/0008-purpose-bound-pii-authorization.md","sha256":"c5157d3bc58f3d8d29e03104dd15eb2911cc1bb66e2c92a935b26d7164648dc7","bytes":5988,"lines":55}, + {"path":"docs/adr/0009-performance-criterion-observation-scope.md","sha256":"1ac10bb2747b0a5b4d62f627825cfd7f978f3fa88d7575bffc23d56371240a64","bytes":7057,"lines":57}, + {"path":"docs/adr/0010-naruon-calendar-intent-boundary.md","sha256":"3e1050a964cc4ed76a1a0cf1e699ae5080acf8c9336f0decdd6d5229359db3c9","bytes":3917,"lines":35}, + {"path":"docs/adr/0011-bitemporal-workforce-composition.md","sha256":"1656ef8b57c836ef7936a8e9cb6a824681eb7563157a1ab0a29deb25849a457b","bytes":5568,"lines":53}, + {"path":"docs/adr/0012-governed-migration-handoff.md","sha256":"713855d670001d3964ecb36cc653830502fb1d82a58b9e39f564b6992dd2bd80","bytes":5965,"lines":59}, + {"path":"docs/adr/0013-governed-requisition-review-packet.md","sha256":"70bf2cbdf903a8793d6d8bc116a08331931090118341f42010236e09c6cc1802","bytes":4693,"lines":46}, + {"path":"docs/adr/0014-job-analysis-snapshot-persistence.md","sha256":"a7ab6fee50aaa63f7f407516a4cb39885faeb0fc6e5035ee8fc352ed73430105","bytes":5365,"lines":49}, + {"path":"docs/adr/README.md","sha256":"f3b3b5ed3b3b31a40a0a3696abf0065e3c25879b6be50077f38ffae742b9d002","bytes":1838,"lines":18}, + {"path":"docs/doctoring/REFERENCES.md","sha256":"929f7ee36df16279f028f726fcf039982180deb377746fe3804f3c0d090778d5","bytes":6352,"lines":69}, + {"path":"docs/doctoring/kubernetes-reference-deployment-references.md","sha256":"49567f7a50c6736d51143366c38104ce56ca360f9446947dbb44e6ecdd2fa78d","bytes":3253,"lines":26}, + {"path":"docs/superpowers/plans/2026-08-15-orgmetra-foundation-implementation-plan.md","sha256":"b64f21abb19373e780db8b9e64deb8ba9a6219ccf9625a651f25407b8691fcbd","bytes":8227,"lines":226}, + {"path":"docs/superpowers/specs/2026-08-15-orgmetra-foundation-design.md","sha256":"4a0e1a7943e40d12bd3082db3757045b4085e5a089fea7bc0d8a1565ffcbcf1d","bytes":6237,"lines":187}, + {"path":"docs/traceability/kubernetes-reference-deployment.md","sha256":"417fdf56e4a3304d45d9c455faf083f9e1a03e8bf3c97b39e5fbaf83253755c8","bytes":4961,"lines":37}, + {"path":"infrastructure/kubernetes/README.md","sha256":"1561e352c5062da262ae52c443912c583b2bc7d2f113cbfb99187fbe2643f56b","bytes":6097,"lines":58}, + {"path":"infrastructure/kubernetes/people-api-reference.json","sha256":"e11a6df307a1640867753fd323d2f10de147cd1990f7569822fd164157538098","bytes":9302,"lines":344}, + {"path":"package.json","sha256":"59ae9e3e67c3fba9320cb18439692395cdfd16ae5c24e3c4cf30d77d63ebabb5","bytes":388,"lines":9}, + {"path":"packages/hris-kernel/src/orgmetra_hris_kernel/audit.py","sha256":"3e5b7190cf857dc8c1fc7e898cef303060f34aabee6c27a9034d4d9650e33190","bytes":7707,"lines":160}, + {"path":"packages/hris-kernel/tests/test_audit_outbox.py","sha256":"5928dd7b97fe38d6b7472ce62966437e339058a59c3b301a93a7b5c05432b40c","bytes":7556,"lines":200}, + {"path":"schemas/openapi.yaml","sha256":"09c1e43486779198574fe31b8bcabbd1c1f74beec7bf86245ae578061619838f","bytes":29503,"lines":1020}, + {"path":"scripts/foundation-contract-core.mjs","sha256":"13bb19e3a545368259e0bf0822ea34a9c9b51f41fd4d559ca88b8716c8fed83e","bytes":28492,"lines":695}, + {"path":"scripts/foundation-contract.mjs","sha256":"5242dcdbe0935775edf074462c82600e9bc4927d9fdc50c47727af915fd4b23a","bytes":218,"lines":6}, + {"path":"tests/dispatcher-inventory.test.mjs","sha256":"09f5e64410e6b7a26bf8d6ce61c50b737da2ea85d955f91eba63aa21f1537261","bytes":1597,"lines":34}, + {"path":"tests/foundation-contract.test.mjs","sha256":"960306fd7cda7b982a52c4428a432d10a4f570430a5d39fb23aeca0b2ede0615","bytes":14860,"lines":386}, + {"path":"tests/kubernetes-reference.test.mjs","sha256":"83c2636d12c73f4b05e9fb0a9912a345d86db4a5a88eb1278b7032c14eb95163","bytes":9938,"lines":275}, + {"path":"tests/openapi-contract.test.mjs","sha256":"80c1610ef1c189fa325e55389501e0e51531ddf61ee335bb94d9cb3aa55a9fdc","bytes":6438,"lines":195}, + {"path":"tests/test_audit_outbox_hardening_postgres.sh","sha256":"518ba2f37ba6292943e5abe22c2599452b2f031a42e453b2493aedf8714421a0","bytes":13396,"lines":333}, + {"path":"tests/test_audit_outbox_postgres.sh","sha256":"e57a04920a0ba97fa6a06752d15ea150016ab8d44099e998c5c4f4067592b4d2","bytes":13443,"lines":357}, + {"path":"tests/test_bitemporal_postgres.sh","sha256":"7684b8c2ff52c044c081135515bd5aabbfd00e2daad0d471b0868701af2df6cc","bytes":8209,"lines":230}, + {"path":"tests/test_candidate_worker_conversion_postgres.sh","sha256":"681cb74d6cfa859ed92c6c2439881ea20c430ef8df94ec662e2807761a377f90","bytes":14673,"lines":344}, + {"path":"tests/test_criterion_observation_scope_postgres.sh","sha256":"0ee9539ee57f840c27d08009f7868cdc8662669df78a01dbc8be39216b8f1a3d","bytes":17811,"lines":469}, + {"path":"tests/test_evidence_sealing_postgres.sh","sha256":"57d16b632a0c60ffdcb4842ceb1cfe25d19c54cefeeefb622ff4fa6e83441ad7","bytes":11349,"lines":370}, + {"path":"tests/test_job_analysis_snapshot_postgres.sh","sha256":"ca9c323a1dd68cfc520277efbbb7495e37fb3ca027890928c8624e5b4f57403f","bytes":13542,"lines":296}, + {"path":"tests/test_operational_uuid_postgres.sh","sha256":"7378f98f0d4b3000e8ea641d8701f1540dbad71410b3637d81d799969e0f6ff7","bytes":3346,"lines":101}, + {"path":"tests/test_outbox_claim_postgres.sh","sha256":"1027806d436ebfe34e108c25b6a4001f43b9550f1d70057c6c0d7974323b0c9b","bytes":14817,"lines":429}, + {"path":"tests/test_outbox_dead_letter_postgres.sh","sha256":"0d728d578e64252e6079f2d141ddaa7fa9cfbf9784e625832273596d69a6e13d","bytes":14008,"lines":377}, + {"path":"tests/test_people_mutation_idempotency_postgres.sh","sha256":"3f57e12f80bd1b034c9aac54b669d8530106e3e26b3795689671fb53807b3cd5","bytes":16191,"lines":381}, + {"path":"tests/test_tenant_isolation_postgres.sh","sha256":"dd649435ef8ab9e57f0609c101917e36656a6d40d63de9bcdbdac23d764f6c3a","bytes":15134,"lines":388}, + {"path":"tests/test_validity_study_case_postgres.sh","sha256":"0070ad58300323c7f9900c5645e0df3106b36ccd245ae686e982c2fd6fa4dc02","bytes":14708,"lines":301}, + {"path":"tests/validate_repository.py","sha256":"9baf354b4728cd0087480e7d04c189b89c41f4b37e3e3a2ea2bda9080803287f","bytes":27652,"lines":644} ] } \ No newline at end of file From 774d88667130ae4ca7b85ef9fc91abd613ec70e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 11:25:51 +0900 Subject: [PATCH 15/16] test(deploy): reproduce fresh-cluster and canonical-doc gaps --- tests/kubernetes-reference.test.mjs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/kubernetes-reference.test.mjs b/tests/kubernetes-reference.test.mjs index 900443636..c51e08a42 100644 --- a/tests/kubernetes-reference.test.mjs +++ b/tests/kubernetes-reference.test.mjs @@ -272,4 +272,26 @@ test("reference documentation keeps digest resolution and database egress fail-c assert.match(text, /NetworkPolicy-capable CNI/i); assert.match(text, /kubectl apply --dry-run=server/i); assert.match(text, /pod-security\.kubernetes\.io\/enforce=restricted/i); + assert.match(text, /fresh target cluster/i); + assert.match(text, /temporary validation namespace/i); + assert.match(text, /kubectl create namespace/i); + assert.match(text, /kubectl delete namespace/i); +}); + +test("canonical buyer-facing docs track the Kubernetes reference deployment boundary", () => { + for (const relativePath of [ + "ARCHITECTURE.md", + "CHANGELOG.md", + "docs/OPERABILITY.md", + "docs/SECURITY.md", + "docs/TEST_STRATEGY.md", + "docs/TRACEABILITY.md", + ]) { + const text = fs.readFileSync(path.join(ROOT, relativePath), "utf8"); + assert.match( + text, + /infrastructure\/kubernetes\/people-api-reference\.json/i, + `${relativePath} must identify the governed Kubernetes reference artifact`, + ); + } }); From 0d546106ac3476a30c09008b620a4cd21ef731a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 11:26:50 +0900 Subject: [PATCH 16/16] docs(deploy): make architecture boundary code-current --- ARCHITECTURE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 1bdc13b5a..21454081d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -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.