diff --git a/sso-mfa/k8s/tenant-engine/runtime.yaml b/sso-mfa/k8s/tenant-engine/runtime.yaml index 8f8d645..cab93de 100644 --- a/sso-mfa/k8s/tenant-engine/runtime.yaml +++ b/sso-mfa/k8s/tenant-engine/runtime.yaml @@ -45,7 +45,7 @@ spec: securityContext: {runAsNonRoot: true, seccompProfile: {type: RuntimeDefault}} containers: - name: flex-auth - image: forgejo.coulomb.social/coulomb/flex-auth@sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b + image: forgejo.coulomb.social/coulomb/flex-auth@sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4 args: ["serve", "--addr", "0.0.0.0:8080", "--registry", "/opt/flex-auth/examples/user-engine/registry_snapshot.json", "--policy", "/opt/flex-auth/examples/user-engine/policy_package.md"] ports: [{name: http, containerPort: 8080}] securityContext: {allowPrivilegeEscalation: false, capabilities: {drop: ["ALL"]}, readOnlyRootFilesystem: true} diff --git a/sso-mfa/k8s/user-engine/registration-acceptance-harness.yaml b/sso-mfa/k8s/user-engine/registration-acceptance-harness.yaml new file mode 100644 index 0000000..0961f45 --- /dev/null +++ b/sso-mfa/k8s/user-engine/registration-acceptance-harness.yaml @@ -0,0 +1,119 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: registration-acceptance-harness + namespace: email-connect + labels: &labels + app.kubernetes.io/name: email-connect + app.kubernetes.io/instance: registration-acceptance-harness + app.kubernetes.io/component: test-mailbox +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: registration-acceptance-harness + template: + metadata: + labels: *labels + spec: + automountServiceAccountToken: false + securityContext: + seccompProfile: {type: RuntimeDefault} + containers: + - name: email-connect + image: forgejo.coulomb.social/coulomb/email-connect@sha256:daa4c764f565f6bad47efc3ae072af8ad482949d28c68fc251055758cebc594c + ports: [{name: http, containerPort: 8082}] + env: + - {name: EMAIL_CONNECT_DATABASE_PATH, value: /data/email-connect.db} + - {name: EMAIL_CONNECT_HTTP_PORT, value: "8082"} + - {name: EMAIL_CONNECT_INGEST_TOKEN, value: harness-ingest-token} + - {name: EMAIL_CONNECT_SMTP_HOST, value: 127.0.0.1} + - {name: EMAIL_CONNECT_SMTP_PORT, value: "3025"} + - {name: EMAIL_CONNECT_SMTP_SECURITY, value: plaintext} + - {name: EMAIL_CONNECT_SMTP_USERNAME, value: harness} + - {name: EMAIL_CONNECT_SMTP_PASSWORD, value: harness} + - {name: EMAIL_CONNECT_SENDER, value: noreply@harness.email-connect.test} + - {name: EMAIL_CONNECT_PORTAL_URL, value: "https://users.92-205-62-239.nip.io"} + securityContext: + allowPrivilegeEscalation: false + capabilities: {drop: ["ALL"]} + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 10001 + runAsGroup: 10001 + volumeMounts: + - {name: data, mountPath: /data} + - {name: tmp, mountPath: /tmp} + readinessProbe: + httpGet: {path: /readyz, port: http} + periodSeconds: 3 + resources: + requests: {cpu: 25m, memory: 64Mi} + limits: {cpu: 250m, memory: 256Mi} + - name: greenmail + image: greenmail/standalone:2.1.12@sha256:9f32971b4f25d32b4de6fa2e297423768441c65e4541f6aecd7631c890a229a7 + env: + - name: GREENMAIL_OPTS + value: >- + -Dgreenmail.setup.test.smtp -Dgreenmail.setup.test.imap + -Dgreenmail.hostname=127.0.0.1 -Dgreenmail.auth.disabled + securityContext: + allowPrivilegeEscalation: false + capabilities: {drop: ["ALL"]} + readinessProbe: + exec: + command: ["bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/3025 && exec 4<>/dev/tcp/127.0.0.1/3143"] + periodSeconds: 3 + resources: + requests: {cpu: 25m, memory: 96Mi} + limits: {cpu: 250m, memory: 256Mi} + volumes: + - {name: data, emptyDir: {}} + - {name: tmp, emptyDir: {}} +--- +apiVersion: v1 +kind: Service +metadata: + name: registration-acceptance-harness + namespace: email-connect +spec: + selector: + app.kubernetes.io/instance: registration-acceptance-harness + ports: [{name: http, port: 8080, targetPort: http}] +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: registration-acceptance-harness + namespace: email-connect +spec: + podSelector: + matchLabels: + app.kubernetes.io/instance: registration-acceptance-harness + policyTypes: [Ingress, Egress] + ingress: + - from: + - namespaceSelector: + matchLabels: {kubernetes.io/metadata.name: user-engine} + podSelector: + matchLabels: {app.kubernetes.io/name: user-engine} + ports: [{protocol: TCP, port: 8082}] +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: registration-acceptance-harness-egress + namespace: user-engine +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: user-engine + policyTypes: [Egress] + egress: + - to: + - namespaceSelector: + matchLabels: {kubernetes.io/metadata.name: email-connect} + podSelector: + matchLabels: + app.kubernetes.io/instance: registration-acceptance-harness + ports: [{protocol: TCP, port: 8082}] diff --git a/sso-mfa/k8s/user-engine/runtime.yaml b/sso-mfa/k8s/user-engine/runtime.yaml index 1997b67..199e8f8 100644 --- a/sso-mfa/k8s/user-engine/runtime.yaml +++ b/sso-mfa/k8s/user-engine/runtime.yaml @@ -45,7 +45,7 @@ spec: seccompProfile: {type: RuntimeDefault} containers: - name: portal - image: forgejo.coulomb.social/coulomb/user-engine@sha256:1402712e8f3ddc1397e83edb9627251b0ea362f1e3308d252d0d688ac589556e + image: forgejo.coulomb.social/coulomb/user-engine@sha256:6e1909fab6546ba5ee7c23fbdcd5b8b8a6550a8e509bff36ea37391c9d684083 imagePullPolicy: IfNotPresent ports: [{name: http, containerPort: 8080}] env: diff --git a/workplans/NK-WP-0024-user-engine-portal-integration-expansion.md b/workplans/NK-WP-0024-user-engine-portal-integration-expansion.md index 53278e3..726df91 100644 --- a/workplans/NK-WP-0024-user-engine-portal-integration-expansion.md +++ b/workplans/NK-WP-0024-user-engine-portal-integration-expansion.md @@ -4,11 +4,11 @@ type: workplan title: "Expand user-engine platform integrations beyond the Binky MVP" domain: infotech repo: net-kingdom -status: active +status: finished owner: codex topic_slug: netkingdom created: "2026-07-30" -updated: "2026-08-13" +updated: "2026-08-14" depends_on: - NK-WP-0023 - USER-WP-0021 @@ -85,7 +85,7 @@ valid. ```task id: NK-WP-0024-T02 -status: progress +status: done priority: medium state_hub_task_id: "9d5f272b-115c-404d-8387-7f987cee65ea" ``` @@ -121,7 +121,7 @@ cluster event receiver and scoped delivery credential. ```task id: NK-WP-0024-T04 -status: progress +status: done priority: high state_hub_task_id: "4c54e8e4-19d9-4470-bb43-3d43cf27af71" ``` @@ -192,5 +192,18 @@ tests with 3 external skips. The corrected immutable image is T03 is complete: all nine durable source events are delivered, replay is idempotent at audit-core, user-engine reports zero pending events, and the -corrected bounded-retry query is live and Ready. T04 remains open for the -mail-producing application journey and its attended negative cases. +corrected bounded-retry query is live and Ready. + +Done 2026-08-14: email-engine's disposable harness proved application-level +verification issuance, mailbox receipt, single-use consumption, baseline +directory provisioning, and the allow-listed password handoff. The combined +deployed path exercised and recovered from authorization denial, verification +network refusal, a request-schema 400, PostgreSQL rolling-start lock +contention, and self-link authorization denial. Regression fixes are live in +user-engine commits `14b8121`, `d4a1327`, `10ee042`, and `5e37e9c`; the final +suite passes 133 tests with 3 external-provider skips. The successful retry +returned 202 for start, 303 for the provider handoff, and 200 for password +completion. Directory inspection proved the baseline users group and absence +of the tenant-admin group. Three exact disposable directory identities were +deprovisioned, production email-connect custody was restored, and the +temporary harness resources were removed. diff --git a/workplans/NK-WP-0025-public-self-registration-and-application-jit.md b/workplans/NK-WP-0025-public-self-registration-and-application-jit.md index de2585c..da8be2c 100644 --- a/workplans/NK-WP-0025-public-self-registration-and-application-jit.md +++ b/workplans/NK-WP-0025-public-self-registration-and-application-jit.md @@ -8,7 +8,7 @@ status: active owner: codex topic_slug: netkingdom created: "2026-08-09" -updated: "2026-08-13" +updated: "2026-08-14" depends_on: - NK-WP-0024 - USER-WP-0022 @@ -77,7 +77,7 @@ attributes and are not account-link keys. ```task id: NK-WP-0025-T02 -status: wait +status: done priority: high state_hub_task_id: "bc220e2b-4cd1-4dcf-b107-12ef3595fe14" ``` @@ -146,7 +146,7 @@ request. The fresh OIDC flow remains provider-owned after password setup. ```task id: NK-WP-0025-T04 -status: wait +status: done priority: high state_hub_task_id: "cf2e4d05-fd07-4bc3-92ff-b2a5ade97846" ``` @@ -174,7 +174,7 @@ Client and tenant allow-list negatives also fail before mail issuance. ```task id: NK-WP-0025-T05 -status: wait +status: progress priority: high state_hub_task_id: "5d13f9f6-16b1-44c9-8e1d-4630cfe60a7b" ``` @@ -188,3 +188,18 @@ automated tests use disposable identities. Done when both user journeys work on railiance01 and all negative cases leave no orphaned privileged identity or duplicate application profile. + +2026-08-14 live evidence: Case B reached anonymous start, disposable mailbox +verification, baseline LLDAP provisioning, allow-listed provider password +handoff, and password completion with statuses 202, 303, and 200. The identity +had `tenant:coulomb:users` and not `tenant:coulomb:admins`; it and the two +partial diagnostic identities were deprovisioned. No verification handle, +setup token, generated password, or privileged credential was printed or +persisted. The live KeyCape configuration has +`coulomb-social.mfaRequired=false`, while every other client was verified not +to have that lowering override; KeyCape rolled successfully. + +T02 and T04 are complete. T05 remains in progress for the attended browser +OIDC callback/JIT check for both an existing identity and a new registrant, +repeated callback behavior, and attended AAL1/AAL2 isolation. The reserved +`tegwick` identity was not used by automation.