Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .agents/skills/test-driven-change/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
name: test-driven-change
description: Deliver observable behavior changes through a verified Red–Green–Refactor cycle. Use for new features, bug fixes, domain logic, permission changes, API behavior, data changes, and contract changes; do not use automatically for documentation-only, formatting, generated-file, or mechanical changes without testable behavior.
---

# Deliver a test-driven change

## Establish the proof

Before writing the test, record:

- the domain invariant;
- the observable target behavior;
- the defect or regression the test must detect;
- the chosen test level;
- what the test proves and what it does not prove;
- relevant negative and boundary cases.

Choose the lowest level that proves the real contract without replacing
observable behavior with implementation detail. Use a higher integration,
contract, smoke, or end-to-end level when the lower level cannot exercise the
relevant boundary truthfully. For a bug fix, make the smallest proof a
regression test.

## Red

1. Write the smallest meaningful test before changing production code.
2. Run that test and record the command, exit code, and concrete failure or
assertion difference.
3. Confirm that it fails for the expected domain reason: the target behavior
is missing or wrong.
4. Do not proceed to Green when:
- the test is immediately green and is not an explicitly justified
characterization test;
- it fails only because of infrastructure, syntax, fixture, or configuration
defects;
- it does not reach the target behavior;
- it checks only a mock call although observable behavior can be checked
meaningfully.

Repair a defective test environment without adding the target production
behavior, then repeat Red. An immediately green test can preserve known
behavior as a characterization test, but is not evidence of a TDD Red step.

## Green

1. Make only the smallest production-code change needed to satisfy the test.
2. Add no speculative abstraction or unrelated refactoring.
3. Run the new test again.
4. Run the relevant existing regression suite.

## Cover risk-specific evidence

For permission changes, verify at least:

- unauthorized access is rejected;
- authorized access succeeds;
- a foreign or manipulated object ID grants no access and causes no data
change;
- a rejected request changes no data;
- UI visibility is never used as a substitute for server-side access control.

For database or migration changes, verify at least:

- fresh installation on an empty schema;
- upgrade from at least the immediately relevant prior version;
- preservation or correct migration of existing data;
- required constraints and indexes exist and preserve integrity;
- no incomplete state after failure.

For shared libraries or contracts, verify:

- relevant provider and consumer contract tests;
- every affected dependent app;
- backward compatibility or an explicitly documented break.

For write operations, verify:

- the return value or HTTP result;
- the persisted state;
- absence of unwanted side effects;
- repeated execution when idempotency is relevant.

These checks supplement applicable repository stop gates. They do not authorize
database, permission, cross-repository, or production changes.

## Refactor

Refactor only after the new test and relevant regression suite are green.
Change no domain behavior. Run the new test and relevant existing tests again
after refactoring.

## Handle non-behavioral changes and deviations

For documentation-only, formatting, generated-file, or mechanical changes
without meaningfully testable behavior, use the suitable deterministic syntax,
contract, generation, layout, link, or structure check instead of an artificial
TDD cycle.

State and justify every deviation from the test-driven workflow. Do not treat a
test that was never observed red as TDD evidence.

## Report

Include:

- the protected invariant and chosen test level;
- the initially red test and expected failure reason;
- the minimal implementation;
- executed focused, regression, and contract tests as applicable;
- concrete commands, results, and exit codes;
- remaining untested risks;
- justified deviations.
12 changes: 10 additions & 2 deletions .agents/skills/work-in-nextcloud-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,23 @@ Stop immediately if production systems, Git history rewriting, new production de

## Test-first and coverage

- New development and bug fixes normally follow Red – Green – Refactor. Start a bug fix with a regression test and a refactoring with characterization tests. Develop domain logic, permissions, hierarchies, conflicts, and validation test-first.
- Use the locally available sibling skill `test-driven-change` for every new feature, bug fix, domain rule, permission change, API behavior, data change, or contract change. It is the sole detailed Red–Green–Refactor workflow; this section adds only Nextcloud-app test selection and coverage requirements.
- API changes cover success, validation failure, and typical Allow/Deny cases. Cross-app contracts have provider and consumer contract tests. Use integration/DDEV tests for migrations and repository behavior when unit tests cannot represent the real contract.
- Develop executable UI logic test-first; additionally cover layout, accessibility, and Nextcloud integration with suitable smoke or browser checks.
- Permitted test-first entry exceptions are time-boxed exploratory spikes, purely declarative text/metadata or trivial presentation changes, and hard-to-isolate Nextcloud integration where a broader integration test is more truthful. Discard spike code or characterize it before adoption; give declarative changes appropriate syntax, contract, layout, or visibility checks.
- Treat a time-boxed exploratory spike or hard-to-isolate Nextcloud integration as an explicitly justified deviation. Discard spike code or characterize it before adoption; choose the truthful broader integration level when isolation would hide the real contract.
- Use the local fast entries named by `AGENTS.md`, normally `php tests/run.php` and `node tests/run-js.mjs`; dependency-light PHP smokes run in isolated processes. Run LocalBase and every affected consumer contract/smoke suite after a LocalBase contract change.
- In local pre-production, app tests may use shared LocalBase test helpers through relative repository paths. Add heavier packaging/autoload structure or a larger test framework only when path handling, runners, assertions, mocks, or fixtures are materially duplicated or impair readability.
- Known overall and app coverage must not decline unnoticed. Aim for at least 85 percent line coverage for new or materially changed executable code, report PHP and JavaScript separately, and fully cover security invariants regardless of percentages. Coverage is a warning and delivery indicator, not a substitute for meaningful assertions.
- Do not prepare a commit or release with red relevant fast tests, contract tests, security checks, coverage gates, or delivery gates.

## Persistent state and migrations

- Before implementing a feature that changes persistent domain objects, determine the complete state model: allowed and forbidden starting states, preconditions, target state, side effects, error states, retry or repetition behavior, and relevant concurrency conflicts.
- Do not expose unrestricted generic setters for status changes governed by domain transition rules. Encapsulate allowed transitions in the domain model or one clearly responsible application service and cover positive, negative, and failure cases.
- Before a database change that can encounter existing data, document the old and new schema, transformation rules, known existing-data variants, integrity conditions, transaction boundary, resumability, and rollback limits.
- Such a database change requires at least a fresh-install test, an upgrade test from the relevant previous version with synthetic existing data, domain data- and relationship-integrity checks, handling of invalid or contradictory legacy data, and an application test on the migrated schema.
- Never modify a published migration after the fact. Correct it with a new migration.

## DDEV, Nextcloud, and hosting safety

- Prefer local PHP/Node checks and batch DDEV checks. Control the shared DDEV project only from its documented `nextcloud-dev` root when that separate Parent workspace is actually available.
Expand Down
67 changes: 64 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,24 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: none
coverage: ${{ matrix.php-version == '8.3' && 'xdebug' || 'none' }}
tools: none
- name: PHP-Tests
if: matrix.php-version == '8.5'
working-directory: localbase
run: php tests/run.php
- name: PHP-Coverage-Tooling installieren
if: matrix.php-version == '8.3'
run: composer install --working-dir=localbase/tests/coverage --no-interaction --no-progress --prefer-dist
- name: PHP-Coverage
if: matrix.php-version == '8.3'
working-directory: localbase
run: |
mkdir -p "$RUNNER_TEMP/php-coverage"
PHP_COVERAGE_COMMAND="$GITHUB_WORKSPACE/localbase/tests/coverage/vendor/bin/phpcov" \
PHP_COVERAGE_OUTPUT_DIR="$RUNNER_TEMP/php-coverage" \
php tests/run.php
php "$GITHUB_WORKSPACE/localbase/tests/coverage/merge-clover.php" localbase "$RUNNER_TEMP/php-coverage" 95.71

javascript:
name: JavaScript
Expand All @@ -50,9 +63,17 @@ jobs:
with:
node-version: 24
package-manager-cache: false
- name: JavaScript-Tests
- name: JavaScript-Coverage-Tooling installieren
run: npm ci --prefix localbase/tests/coverage --ignore-scripts
- name: JavaScript-Tests mit Coverage
working-directory: localbase
run: node tests/run-js.mjs
run: |
tests/coverage/node_modules/.bin/c8 \
--all \
'--include=js/**/*.js' \
--check-coverage \
--lines=61.14 \
node tests/run-js.mjs

consumer-contracts:
name: Verbraucher-Verträge
Expand Down Expand Up @@ -89,6 +110,26 @@ jobs:
with:
repository: Filzmann/nextcloud-adroom
path: adroom
- name: BRTop auschecken
uses: actions/checkout@v7
with:
repository: Filzmann/nextcloud-brtop
path: brtop
- name: BRStunden auschecken
uses: actions/checkout@v7
with:
repository: Filzmann/nextcloud-brstunden
path: brstunden
- name: Berechtigungsmatrix auschecken
uses: actions/checkout@v7
with:
repository: Filzmann/nextcloud-br-permission-matrix
path: br_permission_matrix
- name: AD Recruitment auschecken
uses: actions/checkout@v7
with:
repository: Filzmann/nextcloud-recruitment
path: adrecruitment
- name: PHP einrichten
uses: shivammathur/setup-php@v2
with:
Expand Down Expand Up @@ -125,3 +166,23 @@ jobs:
run: |
php tests/run.php
node tests/run-js.mjs
- name: BRTop-Vertrag
working-directory: brtop
run: |
php tests/run.php
node tests/run-js.mjs
- name: BRStunden-Vertrag
working-directory: brstunden
run: |
php tests/run.php
node tests/run-js.mjs
- name: Berechtigungsmatrix-Vertrag
working-directory: br_permission_matrix
run: |
php tests/run.php
node tests/run-js.mjs
- name: AD-Recruitment-Vertrag
working-directory: adrecruitment
run: |
php tests/run.php
node tests/run-js.mjs
12 changes: 9 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Nextcloud-App-ID:
localbase

Die priorisierte Produktplanung und offene Entscheidungen stehen in `ROADMAP.md`; verbindliche Fach-, Sicherheits- und Architekturregeln bleiben in dieser Datei.
Der ausführliche Katalog öffentlicher Verträge steht in
`docs/architecture.md`; diese Datei hält die bei jeder Arbeit benötigten
Cross-App-Grenzen und Prüfungen.

## Zweck

Expand All @@ -21,6 +24,8 @@ Aktuell enthalten:
- PHP-Logger `OCA\LocalBase\Service\AppLogger` fuer sichere, skalare Log-Kontexte mit App-ID und optionaler User-ID.
- PHP-Gruppenhelfer `OCA\LocalBase\Service\GroupProvisioningService` zum idempotenten Anlegen beliebiger Nextcloud-Gruppen.
- Neutraler Kalendervertrag `AbsenceQueryEvent`/`AbsenceInterval` fuer optionale, read-only Abwesenheitsprovider. `planned` liefert `U?` ohne Blockade, `approved` liefert `U` mit Blockade.
- `CalendarContext` und `CalendarContextSettingsService` definieren Land, ISO-3166-2-Region und fachliche IANA-Zeitzone organisationsweit. `DE`, `DE-BE` und `Europe/Berlin` bleiben Bestandsdefaults. Persönliche Nextcloud-Zeitzonen dürfen ausschließlich individuelle Terminanzeigen beeinflussen. Der Kontext ist im gemeinsamen AD-Adminbereich änderbar und wird bei bestehenden persönlichen Dashboardlayouts additiv eingeblendet.
- `HolidayCalendarService` liefert Schulferien und gesetzliche Feiertage als validierten, read-only Jahresvertrag für den gemeinsamen Kalenderkontext. `OpenHolidaysClient` ist der einzige externe Provideradapter; `HolidayCalendarCacheStore` hält regionsgebundene Jahresstände in der LocalBase-AppConfig. Ein täglicher Hintergrundjob aktualisiert das laufende und die zwei folgenden Jahre. Bei Providerfehlern bleibt ein vorhandener Stand als `stale` verfügbar, Erstabrufe werden sicher als `unavailable` ausgewiesen und nach kurzer Sperrfrist erneut versucht.
- `AdOrganizationDefinition`, `AdOrganizationSettingsService`, `AdOrganizationHierarchy` und `AdOrganizationPermissionPolicy` bilden die konfigurierbaren gemeinsamen AD-Gruppen, Anzeigenamen, Bereiche, Teamansichten, Hierarchie und Peer-Grenzen fuer Kalender, Urlaub und Assistenzplanung ab.
- `AdSuiteAdminSettingsService` speichert app-übergreifend verwendete Peer-Freigaben semantisch nach Rollen und stellt sie AD Kalender, AD Urlaub und der administrativen OrgSuite-Oberfläche gemeinsam bereit.
- Rollen und Bereiche werden über stabile semantische Schlüssel referenziert; konfigurierbare Nextcloud-Gruppen-IDs oder Anzeigenamen dürfen nicht als Fachschlüssel in App-Code dupliziert werden.
Expand Down Expand Up @@ -104,9 +109,10 @@ Einzelne Checks, die durch die Testlaeufer gebuendelt werden:

## DDEV

Die gemeinsame lokale Nextcloud-DDEV-Umgebung liegt ausserhalb dieses Repos:

~/projects/br-nextcloud-apps/nextcloud-dev
Die gemeinsame Nextcloud-DDEV-Umgebung wird aus dem dokumentierten
Parent-Unterverzeichnis `nextcloud-dev` gesteuert. Bei einem eigenständigen
Checkout ist der lokale DDEV-Pfad zuerst anhand der realen Umgebung zu
ermitteln.

Die App wird nach Nextcloud gemountet unter:

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ Gemeinsame Basisbausteine für die lokalen AD- und BR-Nextcloud-Apps. LocalBase

## Installation

Das Releasearchiv nach `custom_apps/` entpacken und als HTTP-Benutzer aktivieren:
Auf Staging- und Zielsystemen werden Nextcloud-Root, `custom_apps`, CLI-PHP und
Runtimebenutzer aus der realen Konfiguration ermittelt. Danach wird LocalBase
im vorgesehenen Runtimekontext aktiviert:

```bash
sudo -u www-data php occ app:enable localbase
<RUNTIME-KONTEXT> <CLI-PHP> occ app:enable localbase
```

Auf Staging- und Zielsystemen wird LocalBase nicht als separates Fachprodukt installiert, sondern automatisch durch den geprüften Produktinstaller. Die vollständige Installationsreihenfolge und Prüfschritte stehen im öffentlichen [AD-Suite-Projekt](https://github.com/Filzmann/ad-suite).
Expand Down
12 changes: 0 additions & 12 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,6 @@ Diese Datei bündelt geplante Erweiterungen und offene Architekturentscheidungen
- Öffentliche Verträge mit den betroffenen Consumer-Apps auf einem realitätsnahen Staging und durch Contract-Tests absichern.
- Den Organisationseditor mit realen Gruppenbesetzungen und großen Organisationsstrukturen visuell und fachlich abnehmen.

## Umgesetzt

- Rollen und Bereiche lassen sich im Adminbereich per Drag-and-drop oder gleichwertig per Tastatur sortieren. Drag-and-drop im Organigramm darf außerdem direkte Hierarchiebeziehungen ändern; die serverseitige Zyklusprüfung bleibt verbindlich.
- Das Organigramm verwendet kompakte Diagrammknoten, Positionierung sowie gerichtete Pfeile. Bereichsrollen werden je Bürobereich aufgefächert; Verbindungen zwischen zwei Bereichsrollen gelten jeweils innerhalb desselben Bereichs.
- Karten derselben Hierarchieebene lassen sich per Drag-and-drop einschließlich einer Ablage zwischen zwei Karten sowie über zugängliche Links-/Rechts-Schaltflächen global anordnen. Diese Diagrammordnung ist eine rein visuelle Organisationsdarstellung und bleibt technisch von der fachlichen Rollen-/Bereichsreihenfolge getrennt.
- Das aktuell sichtbare Organigramm lässt sich clientseitig als bearbeitbares Draw.io-Diagramm, hochauflösendes PNG und skalierbares Vektor-PDF direkt herunterladen. Die Aufnahme zugeordneter Nutzer*innen muss für jeden Export ausdrücklich aktiviert werden.
- Rollen können ausdrücklich als Einzelposition markiert werden. Organisationsweite Einzelpositionen sowie bereichsbezogene BL-/StvBL-Positionen zeigen ihre Nextcloud-Gruppenbesetzung im Diagramm; fehlende und mehrfache Besetzungen werden sichtbar diagnostiziert.
- Die Gruppenoptionen werden über einen Edit-Stift der Diagrammkarten in einem Seitenpanel mit sichtbaren Erklärungen ihrer fachlichen Wirkung bearbeitet. Technische Zuordnungen sind eingeklappt; die fachliche Reihenfolge bleibt separat kompakt sortierbar, Bereiche und Urlaubsansichten erscheinen als aufklappbare Karten.
- Alle Haupt-, Organisations- und Rechteblöcke der AD-Administration lassen sich wie Dashboard-Widgets unabhängig einklappen und per Drag-and-drop oder Tastatur verschieben. Die Organisationsbereiche stehen dabei als eigenständige Cards ohne gemeinsamen äußeren Kasten; das Organigramm nutzt stets die volle verfügbare Breite. Diese Ansicht wird über die native Nextcloud-Benutzerkonfiguration persönlich und geräteübergreifend gespeichert; fachliche Reihenfolgen und Rechte bleiben davon getrennt.
- Das Organigramm bleibt automatisch hierarchisch angeordnet. Kompakte Karten benötigen innerhalb einer Hierarchieebene nur ihre in Grenzen variable Inhaltsbreite und stehen platzsparend nebeneinander. Die Ansicht unterstützt einen zugänglichen persönlichen Zoom von 50 bis 150 Prozent sowie Scrollen und Zeiger-Pan des sichtbaren Ausschnitts. Nur der Zoom wird geräteübergreifend gespeichert; Exporte verwenden weiterhin die vollständige logische Diagrammgröße.
- Organisationsvertrag Version 2 ergänzt stellvertretende PDL, Büroorganisation Pflege, Fahrzeugverwaltung und Empfang additiv in bestehenden Konfigurationen. Stv. PDL führt Pflegefachkräfte und Büroorganisation Pflege; Fahrzeugverwaltung ist GF-Digi und Empfang dem Sekretariat unterstellt.

## Geplante Erweiterungen

- Neue gemeinsame Bausteine werden erst aufgenommen, wenn mindestens zwei Apps dieselbe Semantik und einen gemeinsam testbaren Vertrag benötigen.
Expand Down
5 changes: 4 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
<name>Lokale Nextcloud-Basis</name>
<summary>Gemeinsame lokale Basisbausteine für eigene Nextcloud-Apps.</summary>
<description>Stellt kleine, gemeinsam genutzte PHP- und JavaScript-Basisbausteine für eigene lokale Nextcloud-Apps bereit.</description>
<version>0.7.0-rc.7</version>
<version>0.8.0-rc.2</version>
<licence>agpl</licence>
<author>Simon</author>
<website>https://github.com/Filzmann/ad-suite</website>
<bugs>https://github.com/Filzmann/nextcloud-localbase/issues</bugs>
<repository type="git">https://github.com/Filzmann/nextcloud-localbase</repository>
<namespace>LocalBase</namespace>
<category>tools</category>
<background-jobs>
<job>OCA\LocalBase\BackgroundJob\RefreshHolidayCalendarJob</job>
</background-jobs>
<dependencies>
<php min-version="8.3"/>
<nextcloud min-version="34" max-version="34"/>
Expand Down
Loading