Merge origin/main into feature/user-management

Renumber the users migration to 0013_users so it follows the upstream
0012_good_gateway (logical board feeds); AGENTS.md deferred-work list keeps
both the new feed items and the auth items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Grovy311 2026-09-28 21:46:21 +02:00
commit 95bfba2f67
63 changed files with 5546 additions and 443 deletions

View file

@ -59,7 +59,8 @@ See `docs/current-architecture.md` for the complete module and request flow.
- Device rows inside a circuit do not have their own equipment identifiers.
- Protection and cable data belong to the circuit, not to individual devices.
- Device-level values include quantity, power per unit, simultaneity factor, cosPhi, room data, cost group and category.
- Circuit total power is the sum of all device rows in that circuit.
- Circuit total power is the sum of all device rows in that circuit plus the
read-only loads of logically linked downstream boards on that feeder circuit.
- Existing equipment identifiers must never be changed automatically.
- Renumbering is always an explicit user action.
@ -291,16 +292,19 @@ not change the project revision or undo/redo stacks. Restoring a server-stored
snapshot verifies its checksum and the current-state hash, replaces supported
project data atomically and records a new `restore` revision with a complete
inverse command. Restore can therefore be undone and redone after a restart.
Current snapshot schema version 8 additionally stores the optional net room
area `rooms[].areaM2` (see `docs/building-structure.md`); versions 1 to 7 are
upgraded with `areaM2 = null`. Version 7 stores the project buildings and
Current snapshot schema version 9 additionally stores
`feedingDistributionBoardId` and `feedingCircuitId` on distribution boards;
versions 1 to 8 are upgraded with both references set to `null`. Version 8
stores the optional net room area `rooms[].areaM2` (see
`docs/building-structure.md`); versions 1 to 7 are upgraded with
`areaM2 = null`. Version 7 stores the project buildings and
`floors[].buildingId`; versions 1 to 6 are upgraded with no buildings and
`buildingId = null`. Version 6 stores the
distribution-board info fields `boardNumber`, `location`, `fedFrom` and
`remark` and the project cover fields `siteAddress`, `workStage`,
`projectLead` and `projectEditor`; all older supported versions are upgraded
with `null` for these fields.
Stored named and automatic snapshots of every supported version (1 to 8)
Stored named and automatic snapshots of every supported version (1 to 9)
remain restorable; they are upgraded while parsing. Version 5 stores
the manual quantity share of every CircuitDeviceRow. Version 4 snapshots are upgraded with
`manualQuantity = quantity`; they already contain the complete confirmed
@ -316,7 +320,7 @@ project graph.
Project-wide Revit CSV configuration uses
`external-csv-configuration.update`. Its complete expected/target snapshot is
persisted through the shared project-command transaction, so create, update,
delete, Undo and Redo are revision-safe. Snapshot schema 5-8, restore and portable
delete, Undo and Redo are revision-safe. Snapshot schema 5-9, restore and portable
project duplication preserve the configuration; duplication remaps its internal
id and project link.
The project page exposes the Revit CSV modal. It edits the complete
@ -330,7 +334,7 @@ immutable import batches with original bytes plus the classified cell matrix,
normalized source-room mappings and external objects unique by
`(sourceId, ifcGuid)`. Source values, planning values and overrides are separate.
The general external-model repository is read-only; runtime writes belong only
to typed command adapters. Snapshot/restore and portable project transfer schema versions 5-8
to typed command adapters. Snapshot/restore and portable project transfer schema versions 5-9
capture the complete external state and remap every internal UUID and link while
preserving IFCGUIDs, source values, original bytes and the classified matrix.
Import batches additionally store the monotonic project CSV configuration
@ -470,22 +474,34 @@ snapshot contains the group, optional component protections, complete circuits,
circuit protections and all device-row link/override metadata. Delete
re-captures and compares the subtree before cascading; restore preserves every
UUID in foreign-key-safe order.
The circuit-tree read model exposes fixed `headerComponents`, group-owned
The project-wide circuit-tree read model exposes fixed `headerComponents`, group-owned
`components`, `footerComponents`, optional group category/number and optional
one-to-one protection DTOs for circuits and group components. These are
the only supported circuit-protection source; no flat compatibility fields remain.
It resolves logical board feeds once for the complete project and adds each
downstream board's demand after its own board simultaneity factor to the chosen
feeding circuit as a read-only virtual row. Recursive chains and several boards
on one circuit are supported. A board-only link affects hierarchy but adds no
load until a feeding circuit is selected.
Distribution-board floor assignment and a project-enabled supply type use
`distribution-board.update`; both values are snapshot/export fields and one
persistent undo step.
The same command (still schema version 1, additively extended) carries the
The same command uses schema version 2 for the logical
`feedingDistributionBoardId` and optional matching `feedingCircuitId` together
with the existing fields. Version-1 history commands remain executable and do
not change logical feed references. The command rejects self-links, cycles and
circuits from another board. The
board info-card fields `boardNumber`, `location`, `fedFrom` and `remark`
(migration `0007`). They are nullable, trimmed planner values; the PUT route
only includes submitted info fields in the command and its inverse. An empty
board with info values is no longer an unchanged setup, so history deletion of
it is rejected like a changed simultaneity factor. Populated-subtree commands
stored before these fields existed are normalized to `null` values
(`normalizeDistributionBoardSubtreeSnapshot`). `fedFrom` is deliberately free
text: the logical link to the feeding board/circuit is an open design decision.
(`normalizeDistributionBoardSubtreeSnapshot`). `fedFrom` remains free text for
external feeds and notes; project-board feeds use the two UUID references.
Deleting a referenced board or feeding circuit is blocked in every direct,
subtree and history-only removal path. Board copies retain their incoming feed,
and project duplication remaps both references.
These fields are intended to be prefillable from Revit parameters later, but
only through the Phase 14 rules (preview, explicit confirmation, no silent
overwrite).
@ -528,9 +544,10 @@ Required operations:
`<thead>` so it repeats on printed pages. PDF export uses the browser print
dialog; page size, margins and "Seite x von y" come from injected named
`@page` rules (`lb-portrait`, `lb-landscape`).
- The board hierarchy and "Σ inkl. unterlagert" in the overview are
PRELIMINARY (text match of `fedFrom` against board number/name, plain sum,
no upstream simultaneity factor). Replace this once the feed link is modeled.
- The board hierarchy follows logical board ids. The overview shows power
before board GZF and demand including linked downstream boards; it does not
add a second cumulative column. Board plans render downstream-board loads as
read-only rows. `fedFrom` groups only external root feeds.
- Colors/fonts follow the kbp corporate design (`--pd-*` variables in
`print-document.css`). Empty cover values are shown as
"[ergänzen]"; the Planstände editor column shows the project's current
@ -708,11 +725,12 @@ for the early-phase power balance by DIN 276 cost group (see
- full electrical sizing
- multi-user/PostgreSQL operation
- supported production deployment
- logical feed link between distribution boards (`fedFrom` stays free text
until the project owner decides whether it references a board, a feeding
circuit or both) and the resulting hierarchical power summation
- second/replacement board feeds, including changeover semantics for SV/SiBe
- Revit prefill proposals for logical board feeds through the Phase 14 preview
and explicit-confirmation workflow
- configurable role/rights matrix instead of the fixed `admin`/`user` roles
- account lockout after failed login attempts
- permanent account lockout (only temporary per-username login throttling
exists)
- email/one-time-link password provisioning, OIDC/Entra login
- linking user accounts to a personnel/employee master table