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

261 lines
14 KiB
Markdown

---
id: VERGABE-WP-0019
type: workplan
title: "Admit the first invited company pilot with protected access and recoverable data"
domain: communication
repo: vergabe-teilnahme
status: active
owner: the-custodian
topic_slug: vergabe-teilnahme
created: "2026-09-11"
updated: "2026-09-12"
related: [VERGABE-WP-0018, RAPPS-WP-0014, HFACT-WP-0001, CUST-WP-0071]
state_hub_workstream_id: "85b5f304-d497-5570-bebf-3a3669ef6a7d"
---
# Invited company pilot
## Confirm the bounded customer milestone
```task
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
```task
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
```task
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
```task
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
```task
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
```task
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.