Complete DVD-WP-0002 main codebase TDD kickoff
This commit is contained in:
parent
945460b84e
commit
11b862588f
12 changed files with 135 additions and 5 deletions
|
|
@ -6,12 +6,16 @@
|
|||
## Dev Commands
|
||||
|
||||
```bash
|
||||
# Production codebase (src/)
|
||||
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
||||
.venv/bin/pytest -q tests/unit
|
||||
.venv/bin/pytest -q tests/acceptance # routing-rules tests fail until implemented
|
||||
|
||||
# Orient on architecture and migration plan
|
||||
cat INTENT.md
|
||||
cat docs/WORKPLAN_MainCodebase_Integration.md
|
||||
ls docs/architecture/adr/
|
||||
|
||||
# Prototype smoke (chatgpt5 — most complete)
|
||||
# Prototype reference (chatgpt5)
|
||||
cd prototype-chatgpt5 && pip install -e . && pytest -q
|
||||
|
||||
# After workplan edits
|
||||
|
|
|
|||
3
SCOPE.md
3
SCOPE.md
|
|
@ -28,7 +28,8 @@ direkt-vermittlung-de exists to provide the capability described in INTENT.md.
|
|||
|
||||
## Current State
|
||||
|
||||
- Pre-production: three parallel prototypes (chatgpt5, geminiNbt3pro, grok4.1) exist under /prototype-*; no unified /src codebase yet. Architecture is documented via 8 ADRs and a migration workplan, but the target production codebase has not been started.
|
||||
- `/src` production skeleton started (`dvd.domain`, `dvd.adapters.routing`); unit tests green; routing-rules acceptance tests red (TDD).
|
||||
- Prototypes remain under `/prototype-*` as reference; migration tracked in `docs/WORKPLAN_MainCodebase_Integration.md`.
|
||||
|
||||
## Getting Oriented
|
||||
|
||||
|
|
|
|||
25
pyproject.toml
Normal file
25
pyproject.toml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
[project]
|
||||
name = "direkt-vermittlung-de"
|
||||
version = "0.1.0"
|
||||
description = "DirektVermittlungDe production backend"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"pydantic>=2.7.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"pytest-asyncio>=0.23.0",
|
||||
]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
testpaths = ["tests"]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=68"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
1
src/dvd/__init__.py
Normal file
1
src/dvd/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
"""DirektVermittlungDe production codebase."""
|
||||
0
src/dvd/adapters/__init__.py
Normal file
0
src/dvd/adapters/__init__.py
Normal file
11
src/dvd/adapters/routing.py
Normal file
11
src/dvd/adapters/routing.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"""Metadata-only routing adapter (split-payload model)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dvd.domain.models import DocumentMetadata
|
||||
|
||||
|
||||
async def route_document(meta: DocumentMetadata) -> str:
|
||||
"""Route using plaintext metadata only — never inspect encrypted payload."""
|
||||
if meta.doc_type.upper() == "NOTICE":
|
||||
return f"{meta.authority_id}-NoticeTeam"
|
||||
return f"{meta.authority_id}-DefaultTeam"
|
||||
8
src/dvd/adapters/routing_rules.py
Normal file
8
src/dvd/adapters/routing_rules.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"""Future routing-rules table adapter (not yet implemented)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dvd.domain.models import DocumentMetadata
|
||||
|
||||
|
||||
async def route_document_with_rules(meta: DocumentMetadata) -> str:
|
||||
raise NotImplementedError("Authority routing rules table not implemented yet")
|
||||
0
src/dvd/domain/__init__.py
Normal file
0
src/dvd/domain/__init__.py
Normal file
28
src/dvd/domain/models.py
Normal file
28
src/dvd/domain/models.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
"""Domain models for split-payload document intake (ADR-001)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class DocumentMetadata(BaseModel):
|
||||
"""Plaintext routing metadata — backend routes on this only."""
|
||||
|
||||
authority_id: str = Field(..., max_length=50, alias="authorityId")
|
||||
reference_number: str = Field(..., max_length=50, alias="referenceNumber")
|
||||
doc_type: str = Field(..., max_length=50, alias="docType")
|
||||
issued_at: datetime = Field(..., alias="issuedAt")
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
|
||||
|
||||
class DocumentCreateRequest(BaseModel):
|
||||
metadata: DocumentMetadata
|
||||
encrypted_payload: str = Field(
|
||||
...,
|
||||
description="Base64-encoded opaque blob; routing layer must not decode",
|
||||
alias="encryptedPayload",
|
||||
)
|
||||
|
||||
model_config = {"populate_by_name": True}
|
||||
20
tests/acceptance/test_routing_rules.py
Normal file
20
tests/acceptance/test_routing_rules.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
"""Acceptance tests for future routing-rules table (TDD red phase)."""
|
||||
from datetime import UTC, datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from dvd.domain.models import DocumentMetadata
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_by_reference_prefix_from_rules_table() -> None:
|
||||
"""ADR-001 follow-on: authority-specific rules should override doc_type defaults."""
|
||||
meta = DocumentMetadata(
|
||||
authorityId="DE-BY-001",
|
||||
referenceNumber="FIN-2026-001",
|
||||
docType="APPLICATION",
|
||||
issuedAt=datetime(2026, 1, 15, tzinfo=UTC),
|
||||
)
|
||||
from dvd.adapters.routing_rules import route_document_with_rules
|
||||
|
||||
assert await route_document_with_rules(meta) == "DE-BY-001-FinanceTeam"
|
||||
28
tests/unit/test_routing.py
Normal file
28
tests/unit/test_routing.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
from datetime import UTC, datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from dvd.adapters.routing import route_document
|
||||
from dvd.domain.models import DocumentMetadata
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_notice_to_notice_team() -> None:
|
||||
meta = DocumentMetadata(
|
||||
authorityId="DE-BY-001",
|
||||
referenceNumber="AZ-123",
|
||||
docType="NOTICE",
|
||||
issuedAt=datetime(2026, 1, 15, tzinfo=UTC),
|
||||
)
|
||||
assert await route_document(meta) == "DE-BY-001-NoticeTeam"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_route_default_team_for_other_doc_types() -> None:
|
||||
meta = DocumentMetadata(
|
||||
authorityId="DE-BY-001",
|
||||
referenceNumber="AZ-456",
|
||||
docType="APPLICATION",
|
||||
issuedAt=datetime(2026, 1, 15, tzinfo=UTC),
|
||||
)
|
||||
assert await route_document(meta) == "DE-BY-001-DefaultTeam"
|
||||
|
|
@ -4,11 +4,12 @@ type: workplan
|
|||
title: "Main codebase TDD integration kickoff"
|
||||
domain: government
|
||||
repo: direkt-vermittlung-de
|
||||
status: ready
|
||||
status: finished
|
||||
owner: codex
|
||||
topic_slug: personhood
|
||||
created: "2026-07-08"
|
||||
updated: "2026-07-08"
|
||||
state_hub_workstream_id: "dde8f640-0bf7-4258-bb88-3be3f408e63f"
|
||||
---
|
||||
|
||||
# Main codebase TDD integration kickoff
|
||||
|
|
@ -19,8 +20,11 @@ Start unified `/src` production codebase with ADR-governed TDD interfaces, conso
|
|||
|
||||
```task
|
||||
id: DVD-WP-0002-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "90d0ab6a-6c86-4025-b8bf-2f63e3cd8cc3"
|
||||
```
|
||||
|
||||
Result 2026-07-08: Created src/dvd domain+routing; pyproject.toml; unit tests pass; acceptance routing-rules test fails (TDD red).
|
||||
|
||||
Create `/src` skeleton, port split-payload routing interfaces from chatgpt5 prototype, and add first failing acceptance tests per docs/WORKPLAN_MainCodebase_Integration.md.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue