Update

Due to a short software update, docu.ilias.de will be unavailable from 14:45 CEST for approximately 10 minutes.

25. Internationale ILIAS-Konferenz

Feature Wiki

Information about planned and released features

Tabs

Data: Privacy Data Types

1 Initial Problem

ILIAS processes large amounts of personal data — user IDs, email addresses, names, phone numbers, postal addresses, session data, forum posts, course memberships, access logs.

Today this data circulates as bare PHP primitives (int, string, array). There is no machine-readable way to answer questions that data protection increasingly requires:

  • Which components store personal data, and in which database tables?
  • Which components display personal data to end users?
  • Which components forward personal data to other components, and why?

Answering these questions currently requires a manual code audit per component. This is expensive, error-prone, and does not scale as ILIAS grows. It also makes the component-level privacy documentation expected under the GDPR hard to produce and keep up to date.

2 Conceptual Summary

Introduce Privacy Data Types: a small set of value-object wrappers in the ILIAS\Data\Privacy namespace that make personal data machine-readable at the PHP type level.

A wrapped value carries two pieces of metadata:

  • Source — where the value came from (e.g. the usr_data.email column).
  • Purpose — why it is being accessed, stated at the point of access.

The raw value is reachable only through resolve(Purpose $purpose). Each call is logged (GDPR audit trail) and is statically analysable (used to generate documentation).

The feature has no end-user-facing behaviour. It is a developer-facing infrastructure component plus tooling.

Rollout strategy: We deliberately start with a single, rarely-used data type — for example a user's postal address, possibly the email address — to prove the pattern end to end at low risk. The hard part, should we decide to do it, is UserId: it is read in likely thousands of places across the codebase, so migrating it is by far the largest and most disruptive step. Starting small lets us validate the concept before committing to that scale.

2.1 Technical possibilities and potential implementation

The system has four interlocking parts:

  1. Typed wrappers — UserId, EmailAddress, PhoneNumber, PostalAddress, … all extending an abstract base type. Replaces bare primitives in method signatures.
  2. Typed sources — DbTableColumn, UserInput, ExternalApi, SessionData. A central KnownSources registry maps known ILIAS columns to named methods (KnownSources::user()->email()) instead of string literals.
  3. Typed purposes — StoreInTable, DisplayToUser, PassToComponent, TechnicalProcessing. Passing the wrong purpose is a static-analysis error.
  4. Logging and static analysis — a PrivacyLogger interface records every access. A PHPStan extension collects all access calls and a CLI script generates a PRIVACY.md per component.

A reference implementation already exists (interfaces, concrete types, source registry, logger, PHPStan rules/collector, doc generator, unit tests). This feature request asks only for an in-principle decision on the idea.

3 User Interface Modifications

3.1 List of Affected Views

  • None in the first phase. The feature is infrastructure only and introduces no GUI changes.

Possible later, out of scope here: a backend/administration view that renders the generated privacy access log for a given user (to support GDPR Art. 15 self-disclosure requests).

3.2 User Interface Details

Not applicable for this phase.

3.3 New User Interface Concepts

None.

3.4 Accessibility Implications

None — no UI is added.

4 Additional Information

4.1 Involved Authorities

  • Jour Fixe / Technical Board — new shared infrastructure in ILIAS/Data, cross-component conventions, a new PHPStan extension and a new CLI script under scripts/Privacy/.
  • Mid-term: all authorities whose components handle personal data. As the pattern is adopted incrementally, every component maintainer working with privacy-relevant data will be involved in migrating their own component.

If this request is related to multiple components, please list both authorities for all related components.

4.2 Technical Aspects

New namespace ILIAS\Data\Privacy in the ILIAS/Data component. New PHPStan extension (rules + collector + return-type extension). New CLI script under scripts/Privacy/ producing PRIVACY.md per component, intended to run in CI. PHP 8.x required (readonly properties, enums, generics in PHPDoc). Adoption is incremental: existing repositories are migrated component by component; new code uses the types from acceptance onward.

Audit trail — storage not yet decided. The PrivacyLogger is an interface, so the backend is interchangeable. The audit trail gives us: a queryable record of who accessed which personal data, for what purpose, and when; evidence that access to personal data happens only with a declared purpose; a per-user and per-component view of actual data usage at runtime, complementing the statically generated PRIVACY.md.

4.3 Privacy

This is a privacy-enabling feature.

The audit trail (database table or log file) stores metadata only: data type, source, purpose, timestamp, acting user. The raw personal value is never written.

__toString() on any wrapper returns a masked representation, preventing accidental leaks into log files, stack traces, or string interpolation.

The generated documentation gives a per-component overview of which personal data is stored, displayed, and forwarded.

A retention policy for the audit log must be defined before production rollout (open question).

4.4 Security

PHPStan rules forbid passing a wrapper directly to var_dump, print_r, var_export, json_encode, serialize, reducing accidental disclosure.

Out of scope: passwords and authentication secrets are explicitly not wrapped by this feature.

No new external interfaces or network surface introduced.

4.5 Contact

Person to be contacted in case of questions about the feature or for funding offers: Maintainer: to be filled in. Component: ILIAS/Data.

4.6 Funding

Funding status and funding parties are listed in the block 'Status of Feature' in the right column of this page.

5 Discussion

Open questions to resolve with the community:

  1. Null values — should the wrapper allow T = null, or is a separate nullable wrapper preferable (relevant for nullable columns such as usr_data.birthday)?
  2. Bulk operations — exports and reports resolve the same type thousands of times in a loop. Should the logger offer a batch API to avoid log spam and performance impact?
  3. Static vs. instance API for KnownSources — the reference implementation is currently inconsistent and needs a decision.
  4. Inter-component contracts — when component A passes a wrapper to B and B resolves it, the recorded source is A’s but the file/line is in B. Confirm this is acceptable.
  5. External repositories (LDAP, Shibboleth) — naming conventions for ExternalApi sources need to be agreed before the User migration.
  6. PHPStan enforcement timeline — proposed staged rollout: warning → error → no suppressions allowed.

6 Implementation

Feature has been implemented by {Please add related profile link of this person}

6.1 Description and Screenshots

Reference implementation lives under:

  • components/ILIAS/Data/src/Privacy/ — types, sources, purposes, logger
  • components/ILIAS/Data/PHPStan/Privacy/ — rules, collector, doc generator
  • components/ILIAS/Data/tests/Privacy/ — unit tests
  • scripts/Privacy/generate-privacy-docs.php — CLI doc generator

No screenshots — the feature has no UI. The visible output is the generated PRIVACY.md file per component (Markdown tables: stored / displayed / passed / technical, plus a GDPR-relevance summary).

6.2 Test Cases

Test cases completed at {date} by {user}

  • Test cases to be defined after implementation.

6.3 Privacy

Covered under 4.3. Implementation must guarantee no raw value is written to the audit trail and that masking holds for every concrete type. Audit-trail retention policy to be implemented per the agreed policy.

6.4 Approval

Approved at {date} by {user}.

Last edited: 19. Jun 2026, 21:49, Schmid, Fabian [fschmid]