vergabe-teilnahme/workplans/VERGABE-WP-0019-invited-company-pilot.md
tegwick 7e5cfba380
All checks were successful
Application acceptance / application-tests (push) Successful in 12s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Record tested sign-in release and attended rollout handoff
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
2026-09-12 02:53:55 +02:00

14 KiB

id type title domain repo status owner topic_slug created updated related state_hub_workstream_id
VERGABE-WP-0019 workplan Admit the first invited company pilot with protected access and recoverable data communication vergabe-teilnahme active the-custodian vergabe-teilnahme 2026-09-11 2026-09-12
VERGABE-WP-0018
RAPPS-WP-0014
HFACT-WP-0001
CUST-WP-0071
85b5f304-d497-5570-bebf-3a3669ef6a7d

Invited company pilot

Confirm the bounded customer milestone

id: VERGABE-WP-0019-T01
status: done
priority: high
assignee: the-custodian
state_hub_task_id: "5785d35a-6501-57a3-aedf-3885db269e83"

User decision on 2026-09-11: start with an invited pilot, one company and several users, manually onboarded. Pricing is a later improvement and is not an entry gate. Use the existing single-company product: each admitted company has an isolated deployment, database and data volumes. All active company members can collaborate on the company's tenders; the existing v1 domain approval roles remain descriptive. Django staff/superuser administration remains restricted. External partners remain data objects. No public registration or shared-app multitenancy is introduced.

Product readiness proceeds alongside the governed factory runtime. It does not wait for the fourteen-day factory value study. VERGABE-WP-0018-T03 retains the separate claim that the factory can produce and deliver the customer release; HFACT-WP-0001-T05 still needs a natural governed worker trace.

Require invited access across the UI and uploaded documents

id: VERGABE-WP-0019-T02
status: done
priority: high
assignee: the-custodian
state_hub_task_id: "11e67327-aae4-5c83-99eb-86a8c82dd0be"

Use Django's default-deny login middleware with explicit health/login exemptions, German login and password-change forms, CSRF-protected POST logout, and full-page reauthentication for expired HTMX sessions. Protect uploaded files in production and development, serve private attachments only within MEDIA_ROOT, and keep operational issue state outside that downloadable root. Do not cache company responses. Inactive users lose existing session access; ordinary members do not gain Django administration privileges.

The 12 access regressions initially produced 9 failures, including actual anonymous tender read/create. After the fix all 94 application tests pass locally and in the existing container target; Vite assets build, 139 static files collect, and migration drift is absent. New/changed access modules pass Ruff. Source acceptance is not native customer admission.

Publish and prove the isolated deployment and recovery contract

id: VERGABE-WP-0019-T03
status: progress
priority: high
assignee: the-custodian
depends_on: [VERGABE-WP-0019-T02, RAPPS-WP-0014-T02, RAPPS-WP-0014-T03]
state_hub_task_id: "9065d5cb-2c65-561e-a237-e39da4f3b0fd"

RAPPS-WP-0014 owns exact image/chart/host/namespace/database/Secret binding, persistent media plus distinct issue-facade state, isolated restore rehearsal, and rollback. The customer app owns live CI and immutable release evidence. The user now selects a fresh demo-company demo tenant with demo-user1, etc. Use tenant:trial:demo-company under NetKingdom ADR-0013 and two ordinary demo accounts initially. Native tenant creation and memberships use the existing User Engine operator portal; this does not implement Django SSO. The user selected https://vergabe-teilnahme.coulomb.social/demo-company (one product host, company path). The concrete prepared binding lives at railiance-apps/docs/vergabe-demo-company-binding.md. No password or personal user list belongs in public work records. The historical vergabe_db is not disposable and must not be overwritten.

The user subsequently accepts a 60m application CPU request for one tenant with very few users as a prototype of HelixForge app delivery and Railiance/NetKingdom onboarding. RAPPS-WP-0014 owns the explicit pilot override; this is an accepted low-allocation experiment, not measured production sizing. CUST-WP-0071 is registered for later metrics-based sizing and a final weekly allocation-review setup. That follow-up does not block this deployment. CPU limits, memory, protected access and company/data isolation remain governed by the pilot packet.

On 2026-09-11 the checked Railiance cluster contains neither the historical vergabe-teilnahme namespace nor any Deployment whose name/image contains vergabe/teilnahme. Treat the old runbook as historical intent, not a live return. Native placement and existing data inventory remain required before cutover.

2026-09-12 deployment evidence: the operator added A records for vergabe-teilnahme.coulomb.social and users.coulomb.social. Authoritative IONOS and recursive readback both return 92.205.62.239. Both cert-manager certificates are Ready. The portal now uses https://users.coulomb.social/login; its legacy nip.io address redirects to the canonical hostname. The exact new callback is registered alongside the rollback callback; scopes, public client type and PKCE remain unchanged. Canonical authorization succeeds; unapproved callback and missing PKCE fail. This supersedes earlier DNS and portal-hostname blockers.

Helm release vergabe-teilnahme revision 1 is deployed in vergabe-demo-company, chart 0.2.1, pinned product digest cebe8ca6218cc89f903e8a69e06ac50d3812526d4119cf4da485cc173f674b68. Deployment UID 2152014d-a020-4c5e-a3b0-9575e9f21c44 is Ready 1/1. Its init migration completed before the web process; both phases share the same 60m CPU / 256Mi memory request. Node requests now total 3965m of 4000m; the 35m remainder matches the accepted prototype allocation. No unrelated resource requests changed.

RPF-WP-0039 delivered fresh vergabe_demo_company database/role on apps-pg and runtime Secret vergabe-demo-company/vergabe-demo-env. The app's own connection confirms that exact database/role. The role is non-superuser, cannot create roles or databases, has a 20-connection ceiling and 15-second timeouts, and cannot CONNECT to historical vergabe_db, coulomb_social_db or apps_meta. Both dedicated PVCs are Bound: 5Gi media and 1Gi issue state. Historical data was not selected or overwritten; no credentials are recorded here.

Thirteen live Chromium/HTTP checks pass: page and assets, secure tenant-scoped CSRF cookie, anonymous login gate and media refusal, private operational path refusal, neighboring/root path refusal, canonical slash, HTTPS redirect and missing-CSRF POST denial. Migration/app initialization also proves consumer connectivity. The empty product has zero accounts, including zero staff accounts. The current login is still the interim Django login, not NetKingdom SSO. Native recipient login, company welcome and account mapping remain VERGABE-WP-0019-T06. RAPPS-WP-0014-T03 retains restart and coherent off-host backup/isolated restore; the latest existing apps-pg base backup predates this new database. No pilot-user acceptance, shared tenancy, MFA completion or natural factory-worker trace is claimed.

Accept onboarding, collaboration, recovery and support with pilot users

id: VERGABE-WP-0019-T04
status: wait
priority: high
assignee: the-custodian
depends_on: [VERGABE-WP-0019-T03]
blocking_reason: "Application placement and native tenant/user/password setup are verified. Await tenant welcome/SSO connection, two-user acceptance and demonstrated restore."
state_hub_task_id: "db807f96-f5b8-528d-bc33-75a33fbbf1e4"

Product acceptance: Bernd Worsch and the named company contact. Verify two separate ordinary-user accounts (demo-user1 and demo-user2 initially) can sign in, change passwords, create a tender and lot, collaborate on tasks, upload/download a document, record a v1 domain approval and submission, and report feedback. Verify anonymous access and a revoked user fail, health remains available, and pod replacement preserves all three data stores. Restore a backup into an isolated destination and repeat the workflow without touching the live database. Record operator/support contact, incident route, backup cadence/retention and demonstrated recovery time. Use manual account creation/reset/deactivation through the admitted operator path; never seed development accounts or put credentials in logs/workplans/chat.

A successful invited pilot does not claim shared multitenancy, paid subscriptions, HA or autonomous production release. Pricing is outside this milestone and will need a later explicit product decision.

Support the selected product host and tenant path

id: VERGABE-WP-0019-T05
status: done
priority: high
assignee: the-custodian
state_hub_task_id: "d00acb0b-6514-5ab5-9894-7fadb917feb7"

Implement fixed APP_BASE_PATH, prefix-aware Django URLs/assets/media, scoped and uniquely named cookies, and prefixed login/logout/password-change/HTMX redirects. Replace root URL literals in templates and breadcrumbs with named reversing. The edge strips only the admitted company prefix; the application remains an isolated per-company instance. Four prefix regressions and seven local Chromium checks pass, alongside the existing 94 root-path tests. Vite builds correctly. See docs/tenant-path-deployment.md. T03 retains CI publication, exact live pin, DNS/TLS/namespace/database binding and recovery; source acceptance is not deployment.

On 2026-09-11 at 19:03:18 UTC, native operator creation succeeded. Authority readback confirms tenant:trial:demo-company active, version 1; the chosen first administrator exists in User Engine with invited status. A subsequent Create login failed in identity-provisioner at LLDAP service authentication (HTTP 401). Its existing credential was reloaded without rotation; the connection still fails. NetKingdom tracks that owner-credential reconciliation before identity provisioning retries. No passwords or private addresses enter this record.

2026-09-12 native follow-through: the credential repair is verified, the operator reports successful user password setup, and live read-only User Engine evidence shows three memberships with one linked directory identity. This supersedes the preceding service-login failure. It does not create a Django account or session.

Connect identity setup to the company's welcome and sign-in page

id: VERGABE-WP-0019-T06
status: progress
priority: high
assignee: the-custodian
state_hub_task_id: "455b33f9-163a-5389-86a3-04000c32d176"

The operator successfully sets a user's directory password, but the provider ends on a generic Password set page. The user requests a welcome page for the tenant on the application. Target the selected https://vergabe-teilnahme.coulomb.social/demo-company/ entry point.

Finish RAPPS-WP-0014-T02's real application route/data/placement, then preserve company and intended recipient through the invitation/password-setup handoff using exact allowed HTTPS return locations. Show a tenant-specific welcome page and a clear sign-in action. Connect application authentication to the existing NetKingdom identity contract, with issuer, signature, audience, expiry and exact tenant validation, and a stable subject-to-local-account mapping. Keep ordinary users non-staff and reject wrong-tenant identities. No password copying or operator-session impersonation is an acceptable bridge.

The administrator may create another user's setup link while signed in as platform-root. Completing that link must not turn the operator's existing portal or shared SSO session into the recipient's application session. Handle the explicit fresh-user sign-in/account-switch boundary; USER-WP-0025-T03 retains complete provider sign-out coordination. Preserve the single-company database, media and issue-state isolation and the accepted 60m allocation.

Verify a fresh invited user follows setup → company welcome → authenticated application, sees the correct company, and can enter the pilot workflow. Verify invalid/expired setup returns, unapproved external return URLs, wrong-tenant identities and operator-session confusion fail safely. Keep setup tokens, credentials and personal addresses out of work records. The earlier manual Django login gate remains an interim product capability, not SSO proof.

2026-09-12 continuation: implemented company welcome, OIDC code+PKCE/nonce verification, explicit account confirmation and stable issuer/subject mapping. New accounts are ordinary users with unusable local passwords; signed directory membership, exact tenant and bounded session expiry are required. Added callback, wrong-tenant/platform, signature, replay, CSRF, local deactivation and prefix tests. Source/deployment contract: docs/netkingdom-sign-in.md. The current live issuer predates tenant_source and drops prompt=login before Authelia, so enabling the product depends on KEY-WP-0033 and NK-WP-0037's exact registration/provider rollout. The password-setup company return is grant-bound in NK-WP-0037. Native recipient login/MFA, product publication and live acceptance remain open; no completed SSO or pilot acceptance is claimed from source tests.

2026-09-12 release readiness: source 8be2810 is published as sha256:2cb393608a82be2851adfc27f2bf4d8ef5d709f1b0038be5d0999e38c68b039e (Forgejo run 51). All 125 local app tests, build and migration checks pass. Acceptance run 49 completed tests but failed at image export; the independent publication gate passed, and acceptance run 52 plus smoke run 53 pass on cf50cc5 with identical application source (only generated brief changed). The exact release packet, rollback and server-dry-run manifests are in railiance-apps/docs/vergabe-demo-company-sso-rollout.md. Runtime remains on the interim gate pending the documented attended KeyCape upgrade and native user/MFA acceptance. KEY-WP-0033 and NK-WP-0037 remain live receiving records.