diff --git a/.forgejo/workflows/application-tests.yaml b/.forgejo/workflows/application-tests.yaml new file mode 100644 index 0000000..399a983 --- /dev/null +++ b/.forgejo/workflows/application-tests.yaml @@ -0,0 +1,27 @@ +name: Application acceptance + +on: + push: + branches: [main, 'factory/**'] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + application-tests: + runs-on: container-build + env: + DOCKER_HOST: tcp://127.0.0.1:2375 + steps: + - name: Test the exact source and built assets + run: | + set -eu + REF="${GITHUB_SHA:?exact source revision required}" + mkdir -p buildctx /tmp/factory-docker-bin + wget -qO /tmp/repo.tar.gz \ + "https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz" + tar xzf /tmp/repo.tar.gz -C buildctx --strip-components=1 + wget -qO- https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \ + | tar xz --strip-components=1 -C /tmp/factory-docker-bin docker/docker + export PATH="/tmp/factory-docker-bin:${PATH}" + docker build --target application-tests buildctx diff --git a/.forgejo/workflows/image.yaml b/.forgejo/workflows/image.yaml index 27423bf..efeb4f8 100644 --- a/.forgejo/workflows/image.yaml +++ b/.forgejo/workflows/image.yaml @@ -16,6 +16,7 @@ on: - "vergabe_teilnahme/**" - "static/**" - "templates/**" + - "conftest.py" workflow_dispatch: env: @@ -42,6 +43,8 @@ jobs: | tar xz --strip-components=1 -C "${HOME}/bin" docker/docker export PATH="${HOME}/bin:${PATH}" docker version + # Test the exact source before registry login or image publication. + docker build --target application-tests buildctx echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" -u "${REGISTRY_USER}" --password-stdin SHORT="${REF:0:7}" IMAGE="${REGISTRY}/${IMAGE_NAME}" @@ -49,4 +52,4 @@ jobs: docker push "${IMAGE}:latest" docker push "${IMAGE}:${SHORT}" docker push "${IMAGE}:main-${SHORT}" - echo "pushed ${IMAGE}:latest ${IMAGE}:${SHORT}" \ No newline at end of file + echo "pushed ${IMAGE}:latest ${IMAGE}:${SHORT}" diff --git a/.repo-classification.yaml b/.repo-classification.yaml index cb8262a..b333b5f 100644 --- a/.repo-classification.yaml +++ b/.repo-classification.yaml @@ -1,9 +1,9 @@ repo_classification: standard: Repo Classification Standard version: '1.0' - classified_at: '2026-06-22' + classified_at: '2026-09-08' classified_by: agent - category: experimental + category: product domain: communication secondary_domains: [] capability_tags: diff --git a/AGENTS.md b/AGENTS.md index 8bb97dd..1242468 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,12 +2,12 @@ ## Repo Identity -**Purpose:** Coulomb project repository (bootstrapped from repo-seed template) +**Purpose:** Customer tender-participation service and UI; primary HelixForge factory customer product. **Domain:** communication **Repo slug:** vergabe-teilnahme **Topic ID:** `36c7421b-c537-4723-bf75-42a3ebc6a1dc` -**Workplan prefix:** `WP-` +**Workplan prefix:** `VERGABE-WP-` --- diff --git a/Dockerfile b/Dockerfile index a25854e..e741bbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,6 +54,31 @@ RUN --mount=type=secret,id=forgejo_pypi_user,required=false \ ' +# Application acceptance gate. This stage is required by CI before publication; +# test tooling and test credentials are absent from the final runtime stage. +FROM python-deps AS application-tests +RUN --mount=type=secret,id=forgejo_pypi_user,required=false \ + --mount=type=secret,id=forgejo_pypi_password,required=false \ + sh -eu -c '\ + if [ -f /run/secrets/forgejo_pypi_user ]; then \ + export UV_INDEX_FORGEJO_USERNAME="$(cat /run/secrets/forgejo_pypi_user)"; \ + fi; \ + if [ -f /run/secrets/forgejo_pypi_password ]; then \ + export UV_INDEX_FORGEJO_PASSWORD="$(cat /run/secrets/forgejo_pypi_password)"; \ + fi; \ + uv sync --frozen --no-install-project \ + ' +COPY manage.py conftest.py ./ +COPY vergabe_teilnahme ./vergabe_teilnahme +COPY static ./static +COPY --from=assets /build/static/dist ./static/dist +ENV DATABASE_URL=sqlite:///:memory: \ + SECRET_KEY=application-test-only \ + DJANGO_SETTINGS_MODULE=vergabe_teilnahme.settings.dev +RUN .venv/bin/python manage.py collectstatic --noinput \ + && .venv/bin/python -m pytest \ + && .venv/bin/python manage.py makemigrations --check --dry-run + # ─── Stage 3 ─── Runtime image ────────────────────────────────────────────── FROM python:3.12-slim-bookworm AS runtime @@ -76,7 +101,6 @@ COPY --chown=app:app manage.py pyproject.toml ./ COPY --chown=app:app vergabe_teilnahme ./vergabe_teilnahme COPY --chown=app:app static/src ./static/src COPY --chown=app:app static/vendor ./static/vendor -COPY --chown=app:app templates ./templates COPY --from=assets --chown=app:app /build/static/dist ./static/dist RUN mkdir -p ./media ./staticfiles ./.issue-facade && chown -R app:app /app diff --git a/INTENT.md b/INTENT.md new file mode 100644 index 0000000..60debc2 --- /dev/null +++ b/INTENT.md @@ -0,0 +1,18 @@ +# Intent + +Vergabe Teilnahme is the primary customer service and UI product for the first +HelixForge factory delivery lane, as selected by Bernd Worsch on 2026-09-08. +It helps a company's team manage tender participation: deadlines, lots, +requirements, decisions, evidence, submission and retrospective learning. + +The existing Django product remains the implementation home. The first customer +offering should preserve its single-company boundary, with an isolated deployment +per admitted company until a separately designed tenancy model is accepted. +Customer availability follows verified access, persistence, restore, release and +support arrangements; this intent does not claim those gates are complete. + +The product requirements and domain workflows remain in +[wiki/ProductRequirementsDocument.md](wiki/ProductRequirementsDocument.md). +Factory integration is coordinated by `prj-helixforge-factory/HFACT-WP-0001`. +Reuse-surface supplies internal capability discovery before new implementation; +customer users interact with the tender UI. diff --git a/Makefile b/Makefile index 2e2931a..b9a3ab5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help db dev css seed migrate test lint shell superuser collectstatic sync-whynot-design +.PHONY: help db dev css seed migrate test test-image plan-check lint shell superuser collectstatic sync-whynot-design .DEFAULT_GOAL := help @@ -32,6 +32,16 @@ migrate: ## Generate and apply all pending migrations test: ## Run the full pytest test suite uv run pytest +test-image: ## Verify locked Python dependencies, built CSS, application tests and migrations + docker build --target application-tests . + +REUSE_SURFACE_BIN ?= reuse-surface +REUSE_SURFACE_URL ?= https://reuse.coulomb.social + +plan-check: ## Check a proposed WORKPLAN against current hosted capabilities (no model call) + @test -n "$(WORKPLAN)" || { echo 'Set WORKPLAN=workplans/.md'; exit 2; } + $(REUSE_SURFACE_BIN) plan-check "$(WORKPLAN)" --hub-url "$(REUSE_SURFACE_URL)" --no-llm --format json --consumer-repo vergabe-teilnahme + lint: ## Run ruff (style) and mypy (types) uv run ruff check . uv run mypy vergabe_teilnahme/ diff --git a/README.md b/README.md index fcd7b8f..cf6c85e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ -# repo-seed +# Vergabe Teilnahme -A git repository template to bootstrap coulomb projects from. \ No newline at end of file +Customer product for managing a company’s tender participation, from initial +research through submission and retrospective. The Django UI covers tenders, +lots, requirements, deadlines, tasks, documents, approvals and reusable evidence. + +- [Product intent](INTENT.md) and [scope](SCOPE.md) +- [Product requirements](wiki/ProductRequirementsDocument.md) +- [Current delivery work](workplans/VERGABE-WP-0018-customer-factory-delivery.md) +- [Delivery and reuse checks](docs/delivery.md) + +Start development with `make db`, `uv sync`, `make migrate` and `make dev`. +Use `make css` for the asset watcher. Run `make test-image` for the isolated +application acceptance gate used before image publication. + +Selected on 2026-09-08 as the primary customer service/UI product for the +HelixForge factory. Customer deployment and access acceptance remain open in +VERGABE-WP-0018; the existing application is scoped to one company. diff --git a/SCOPE.md b/SCOPE.md index d0efe2e..33739a6 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -36,6 +36,13 @@ It operates on three levels, per `wiki/ProductRequirementsDocument.md`: --- +## Product direction — 2026-09-08 + +Primary customer service/UI repository for the HelixForge factory, selected by +the user. Initial delivery preserves a single-company boundary; customer release +requires explicit deployment, access, persistence, restore and support acceptance +in VERGABE-WP-0018. The original internal collaboration workflows remain valid. + ## In Scope - Tender (Ausschreibung) and lot (Los) tracking through 8 navigable phases diff --git a/docs/delivery.md b/docs/delivery.md new file mode 100644 index 0000000..d47df46 --- /dev/null +++ b/docs/delivery.md @@ -0,0 +1,52 @@ +# Delivery checks + +Before implementing a workplan, use the hosted reuse registry: + +```sh +make plan-check WORKPLAN=workplans/VERGABE-WP-0018-customer-factory-delivery.md +``` + +Install a reuse-surface revision containing REUSE-WP-0022. The initially tested +provider revision is recorded in +[evidence/2026-09-08-hosted-plan-check.json](evidence/2026-09-08-hosted-plan-check.json). +`REUSE_SURFACE_BIN` can select an explicit installed executable; +`REUSE_SURFACE_URL` defaults to `https://reuse.coulomb.social`. + +This reads current hosted capabilities with `--no-llm`. It sends no tender intent +or mutation token to the registry. A failed/stale/partial source exits nonzero +without a recommendation. Preserve JSON output with the source revision in the +workplan evidence; a lexical `new` result still requires review of existing +capability owners. For this delivery we reuse reuse-surface, Railiance CI tooling +and the existing Railiance Apps deployment rather than establish new equivalents. + +## Application and release gate + +```sh +make test-image +``` + +The `application-tests` Docker target installs the locked Python dependencies, +builds Vite/Tailwind assets, collects static files, runs the complete Django +application suite against disposable SQLite data, and checks migration drift. +It includes the existing tender → lot → approval and submission workflow tests. +The target carries no production database connection or release credential. +SQLite proves this application acceptance suite; target PostgreSQL and live +storage/recovery behavior remain release admission checks. + +The Forgejo application workflow checks proposed changes. The image workflow +runs the same target on the same archive revision **before** registry login and +publication. Test dependencies and test settings are isolated from the runtime +image. The existing optional BuildKit package secrets remain supported, but the +current issue-core package is anonymously readable; no new secret is required. + +The corrected Dockerfile consumes application templates under +`vergabe_teilnahme/templates/`. A fresh archive does not contain a root +`templates/` directory; attempting to copy it previously broke clean builds. + +## Customer release acceptance + +VERGABE-WP-0018-T03 owns the first admitted Railiance customer pilot: exact image +digest and chart revision, tenant/host and login binding, database and media +ownership, backup/restore and rollback, UI smoke and named operating owner. +Existing production tender data is never disposable test data. A passing source +build does not establish customer availability or the governed factory worker. diff --git a/docs/evidence/2026-09-08-application-acceptance.json b/docs/evidence/2026-09-08-application-acceptance.json new file mode 100644 index 0000000..de7a863 --- /dev/null +++ b/docs/evidence/2026-09-08-application-acceptance.json @@ -0,0 +1,22 @@ +{ + "date": "2026-09-08", + "sqlite_tests": { + "passed": 82, + "exit_code": 0 + }, + "postgres_tests": { + "passed": 82, + "version": "16-alpine", + "exit_code": 0, + "disposable": true + }, + "container_gate": { + "passed": 82, + "exit_code": 0, + "static_files": 139, + "migration_drift": false + }, + "known_warning": "Existing naive datetime in test_naechste_frist_returns_earlier", + "runtime_smoke": "2026-09-08-runtime-smoke.json", + "release_status": "local acceptance; Forgejo CI and admitted Railiance deployment are separate gates" +} diff --git a/docs/evidence/2026-09-08-hosted-plan-check.json b/docs/evidence/2026-09-08-hosted-plan-check.json new file mode 100644 index 0000000..cd3ad1d --- /dev/null +++ b/docs/evidence/2026-09-08-hosted-plan-check.json @@ -0,0 +1,69 @@ +{ + "federated_index_stale_warning": null, + "federated_index_updated": "2026-09-08", + "index_source": { + "capability_count": 65, + "composed_at": "2026-09-08T06:18:03+00:00", + "digest_format": "response-bytes", + "federation_warnings": false, + "fetched_at": "2026-09-08T10:10:35.750043+00:00", + "kind": "hosted", + "max_age_hours": 24, + "sha256": "bfb6b79970867ac981fc48286dea24b2ff766cf732d3675f73ccbddb8971e498", + "stale": false, + "url": "https://reuse.coulomb.social/v1/federated" + }, + "matches": [ + { + "id": "capability.infotech.config-surface-atlas", + "kind": "deterministic", + "owner": "config-atlas", + "score": 0.0656, + "summary": "Read-first, cross-kind map and evidence layer for configuration surfaces \u2014 what configures a system, who owns it, its scope, and where the source of truth lives.", + "vector": "D5 / A0 / C2 / R2" + }, + { + "id": "capability.infotech.citation-evidence-workspace", + "kind": "deterministic", + "owner": "citation-evidence", + "score": 0.0962, + "summary": "Document-centered evidence workspace for capturing, managing, presenting, and re-opening citations \u2014 the umbrella application over the citation-evidence six-package design.", + "vector": "D4 / A1 / C1 / R0" + }, + { + "id": "capability.registry.register", + "kind": "deterministic", + "owner": "reuse-surface", + "score": 0.0816, + "summary": "Register a new capability so it becomes visible for planning and implementation reuse.", + "vector": "D3 / A4 / C2 / R3" + }, + { + "id": "capability.railiance.workload-deployment-tooling", + "kind": "deterministic", + "owner": "railiance-apps", + "score": 0.069, + "summary": "S5 Workloads and Experience Endpoints layer of the Railiance OAS Stack \u2014 application Helm releases, Kubernetes workload manifests, deployment guardrails, and smoke-test/check tooling for user-facing services.", + "vector": "D3 / A2 / C1 / R1" + }, + { + "id": "capability.railiance.ci-enablement", + "kind": "deterministic", + "owner": "railiance-enablement", + "score": 0.0492, + "summary": "S4 Developer Enablement layer of the Railiance OAS Stack \u2014 reusable CI/CD workflow templates, developer portal paths, platform templates, SDKs, and buildpacks, using forge capabilities without owning forge runtime.", + "vector": "D3 / A2 / C2 / R1" + } + ], + "query": { + "source": "workplan", + "text": "Establish verified delivery for the primary customer tender product\nMake the existing tender-participation UI a repeatably tested customer product.\nUse hosted capability discovery for planning, exercise the existing useful\ntender/lot/approval workflow, and prevent image publication when application\nacceptance fails. Preserve single-company scope until a separate tenancy design.", + "workplan_id": "VERGABE-WP-0018", + "workplan_path": "/tmp/custodian-factory-followthrough/vergabe-teilnahme/workplans/VERGABE-WP-0018-customer-factory-delivery.md" + }, + "top_score": 0.0656, + "verdict": "new", + "consumer_repo": "vergabe-teilnahme", + "provider_revision": "2621cf2752a453ed79af37b583185a0291795bcf", + "review_disposition": "Reuse the existing reuse-surface CLI, Railiance CI and workload tooling. Low lexical score does not justify a new registry, CI platform or deployment engine." +} diff --git a/docs/evidence/2026-09-08-runtime-smoke.json b/docs/evidence/2026-09-08-runtime-smoke.json new file mode 100644 index 0000000..ddc6689 --- /dev/null +++ b/docs/evidence/2026-09-08-runtime-smoke.json @@ -0,0 +1,8 @@ +{ + "health_status": 200, + "response": "{\"status\": \"ok\"}", + "image_id": "sha256:e45182096e1b196245c8795b0c3edb0dbb3e9815c78177df122bc36930975da4", + "runtime_user": "999", + "pytest_in_runtime": false, + "scope": "Local loopback smoke; disposable configuration; no database persistence, Railiance deployment or customer availability claim." +} diff --git a/workplans/VERGABE-WP-0018-customer-factory-delivery.md b/workplans/VERGABE-WP-0018-customer-factory-delivery.md new file mode 100644 index 0000000..978adda --- /dev/null +++ b/workplans/VERGABE-WP-0018-customer-factory-delivery.md @@ -0,0 +1,89 @@ +--- +id: VERGABE-WP-0018 +type: workplan +title: "Establish verified delivery for the primary customer tender product" +domain: communication +repo: vergabe-teilnahme +status: active +owner: the-custodian +topic_slug: vergabe-teilnahme +created: "2026-09-08" +updated: "2026-09-08" +related: [HFACT-WP-0001, REUSE-WP-0022] +--- + +# Customer product delivery + +## Core Idea + +Make the existing tender-participation UI a repeatably tested customer product. +Use hosted capability discovery for planning, exercise the existing useful +tender/lot/approval workflow, and prevent image publication when application +acceptance fails. Preserve single-company scope until a separate tenancy design. + +## Establish product authority and reuse discovery + +```task +id: VERGABE-WP-0018-T01 +status: done +priority: high +assignee: the-custodian +``` + +Update product entry points and classification to reflect the user's explicit +customer-product selection. Add a reproducible `make plan-check WORKPLAN=...` +consumer of REUSE-WP-0022, with no model call or mutation credential. Pin and +record the tested provider revision and hosted snapshot receipt. A low lexical +score requires owner review; it does not authorize a duplicate capability. + +## Gate releases with useful application acceptance + +```task +id: VERGABE-WP-0018-T02 +status: progress +priority: high +assignee: the-custodian +``` + +Run existing application tests against disposable data, including tender create, +lot create, approval and submission. Add a reproducible container acceptance +target with locked dependencies, built assets and migration drift checks. Run it +on proposed changes and before the existing image publication step. Record +immutable reviewed source, CI outcome and resulting artifact separately. + +## Accept the first Railiance customer pilot release + +```task +id: VERGABE-WP-0018-T03 +status: wait +priority: high +assignee: the-custodian +depends_on: [VERGABE-WP-0018-T02, HFACT-WP-0001-T05] +blocking_reason: "Await tested/reviewed image and exact Railiance tenant, deployment, database, storage, access and recovery owner acceptance." +``` + +Coordinator: the-custodian; product acceptance: Bernd Worsch; deployment owner: +railiance-apps and admitted Railiance placement owner. Prepare exact chart/image, +host, tenant, credential binding, existing-data disposition, backup/restore, +rollback and UI acceptance evidence before release. Use an isolated internal +pilot first; existing `vergabe_db` is not test data and must not be relocated or +overwritten implicitly. No customer-ready claim until admitted release passes. +Return the release and consumer evidence to HFACT-WP-0001-T06/T07. + +## Source acceptance — 2026-09-08 + +- Full application suite: 82 passed locally with SQLite and again with a + disposable PostgreSQL 16 container; no production data used. +- Clean container application target: 82 passed, Vite/Tailwind built, 139 static + files collected, no migration drift. One pre-existing naive-datetime warning. +- Runtime image built successfully; loopback health HTTP 200 as UID 999; + pytest absent from runtime. See `docs/evidence/2026-09-08-runtime-smoke.json`. +- Clean-build defect fixed: root `templates/` does not exist in published source; + application templates already reside under `vergabe_teilnahme/templates/`. +- Hosted discovery consumed from reuse-surface implementation `2621cf2`; + 65-capability provenance and review disposition are in + `docs/evidence/2026-09-08-hosted-plan-check.json`. + +T02 remains in progress until the published exact revision has its CI return. +T03 retains the concrete deployment/data/access/recovery gates. Attended Codex +source work is not a natural governed worker claim/heartbeat/close trace.