vergabe-teilnahme/workplans/VERGABE-WP-0019-invited-company-pilot.md
tegwick 4175709024
All checks were successful
Application acceptance / application-tests (push) Successful in 7s
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 1s
plan: connect identity setup to the tenant welcome page
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
2026-09-12 01:08:33 +02:00

201 lines
9.6 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.
## 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: "Native tenant/user/password setup is verified. Await admitted application placement, tenant welcome/sign-in connection 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: todo
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.