This repository was archived by the owner on May 29, 2026. It is now read-only.
[Changelog CI] Add Changelog for Version 0.1.2#2
Merged
Conversation
This was referenced Jan 16, 2025
rubenvdlinde
pushed a commit
that referenced
this pull request
Jul 30, 2025
[Changelog CI] Add Changelog for Version 0.1.2
4 tasks
5 tasks
rjzondervan
added a commit
that referenced
this pull request
May 21, 2026
…-side; surface root cause on rollback (#1593) **Root cause of the operator-reported 500:** The `oc_openregister_entities` table has TWO `NOT NULL`-with-no-default columns (`category` and `updated_at`) that the existing detector flow (`EntityRecognitionHandler::findOrCreateEntity`) always populates. The new manual-entity flow only populated `detected_at`, so the insert failed at the DB layer with two consecutive `SQLSTATE[HY000] 1364 Field 'X' doesn't have a default value` errors — one per column. **Fix #1 — `category` is now server-derived, removed from the API:** - `EntityRecognitionHandler::getCategoryForType()` is now `public static` (was `private`) so producers outside the detector pipeline can derive the same mapping without taking on the handler's DI graph. - `ManualEntityService::lookupOrCreateEntity()` calls it on every new insert. Rationale: the operator UI rarely has the context to make a category decision, the detector flow already derives consistently, and exposing the field as operator-input was the original source of the bug (omitted = null = NOT NULL violation). Manual-entity rows and detector rows now share categories for identical types. - `category` removed from the request body, the service signature, the `writeAuditTrails` signature, the controller body-parsing, and the unit tests. The audit trail still records `category` in `changed.fields` — read from the entity after insert, so the persisted value is captured verbatim. - Operator-override on category is intentionally NOT exposed in v1; a follow-up if a concrete use case emerges. **Fix #2 — `updated_at` populated alongside `detected_at`:** - Same root cause class. Mirroring the detector flow's column population fixes it. **Fix #3 — operator-debuggable rollback path:** The service's `catch (Throwable $error)` block wrapped the original exception as `ManualEntityException(REASON_INTERNAL_ERROR)` without logging. Combined with the controller's `mapManualEntityException` only logging the reason code (not the previous-exception message), a 500 left no debuggable trail in `nextcloud.log` — exactly what the operator hit. Added a `LoggerInterface::error()` call inside the service's rollback handler that captures `errorType`, `error`, and `trace` of the underlying Throwable before re-wrapping. Future operator-reported 500s will have a stack-trace-level log entry keyed by reqId. **Spec + docs updates:** - `docs/Features/manual-entity-anonymisation.md` — request body shape loses the `category` line; added a note explaining the server-side derivation. - `openspec/changes/manual-entity-anonymisation/proposal.md` — example body updated; the 400 error hint updated. - `openspec/changes/manual-entity-anonymisation/design.md` — derivation rationale folded into the existing "lookup-or-create" section; the open-question on category resolved with a "not in the API at all" decision. - `openspec/changes/manual-entity-anonymisation/specs/entity-relation-grondslagen/spec.md` — Requirement updated, "Category mismatch does NOT trigger an update" scenario replaced with "New catalogue row carries the server-derived category". - `openspec validate manual-entity-anonymisation` clean. **Verification:** - PHPCS clean (4 touched files including the new logger call). - PHPStan clean on the full diff. - 44 unit tests / 145 assertions across `ManualEntityServiceTest|FileTextControllerManualEntityTest|ChunkTextMatcherTest|GdprEntityMapperTest|EntityRelationMapperTest` all green in the live `master-nextcloud-1` container. - End-to-end smoke test in the dev environment: - Empty-match POST → HTTP 200 with `message`, catalogue row created. - Match POST → HTTP 201 with `matchCount=4, matchesSkipped=2` (the 2 skipped were pre-existing detector hits at the same positions). - Idempotent re-POST → HTTP 201 with `matchCount=4, matchesSkipped=4`, `relations: []` (no duplicates). Refs: #1593
4 tasks
rjzondervan
added a commit
that referenced
this pull request
May 26, 2026
…-side; surface root cause on rollback (#1593) **Root cause of the operator-reported 500:** The `oc_openregister_entities` table has TWO `NOT NULL`-with-no-default columns (`category` and `updated_at`) that the existing detector flow (`EntityRecognitionHandler::findOrCreateEntity`) always populates. The new manual-entity flow only populated `detected_at`, so the insert failed at the DB layer with two consecutive `SQLSTATE[HY000] 1364 Field 'X' doesn't have a default value` errors — one per column. **Fix #1 — `category` is now server-derived, removed from the API:** - `EntityRecognitionHandler::getCategoryForType()` is now `public static` (was `private`) so producers outside the detector pipeline can derive the same mapping without taking on the handler's DI graph. - `ManualEntityService::lookupOrCreateEntity()` calls it on every new insert. Rationale: the operator UI rarely has the context to make a category decision, the detector flow already derives consistently, and exposing the field as operator-input was the original source of the bug (omitted = null = NOT NULL violation). Manual-entity rows and detector rows now share categories for identical types. - `category` removed from the request body, the service signature, the `writeAuditTrails` signature, the controller body-parsing, and the unit tests. The audit trail still records `category` in `changed.fields` — read from the entity after insert, so the persisted value is captured verbatim. - Operator-override on category is intentionally NOT exposed in v1; a follow-up if a concrete use case emerges. **Fix #2 — `updated_at` populated alongside `detected_at`:** - Same root cause class. Mirroring the detector flow's column population fixes it. **Fix #3 — operator-debuggable rollback path:** The service's `catch (Throwable $error)` block wrapped the original exception as `ManualEntityException(REASON_INTERNAL_ERROR)` without logging. Combined with the controller's `mapManualEntityException` only logging the reason code (not the previous-exception message), a 500 left no debuggable trail in `nextcloud.log` — exactly what the operator hit. Added a `LoggerInterface::error()` call inside the service's rollback handler that captures `errorType`, `error`, and `trace` of the underlying Throwable before re-wrapping. Future operator-reported 500s will have a stack-trace-level log entry keyed by reqId. **Spec + docs updates:** - `docs/Features/manual-entity-anonymisation.md` — request body shape loses the `category` line; added a note explaining the server-side derivation. - `openspec/changes/manual-entity-anonymisation/proposal.md` — example body updated; the 400 error hint updated. - `openspec/changes/manual-entity-anonymisation/design.md` — derivation rationale folded into the existing "lookup-or-create" section; the open-question on category resolved with a "not in the API at all" decision. - `openspec/changes/manual-entity-anonymisation/specs/entity-relation-grondslagen/spec.md` — Requirement updated, "Category mismatch does NOT trigger an update" scenario replaced with "New catalogue row carries the server-derived category". - `openspec validate manual-entity-anonymisation` clean. **Verification:** - PHPCS clean (4 touched files including the new logger call). - PHPStan clean on the full diff. - 44 unit tests / 145 assertions across `ManualEntityServiceTest|FileTextControllerManualEntityTest|ChunkTextMatcherTest|GdprEntityMapperTest|EntityRelationMapperTest` all green in the live `master-nextcloud-1` container. - End-to-end smoke test in the dev environment: - Empty-match POST → HTTP 200 with `message`, catalogue row created. - Match POST → HTTP 201 with `matchCount=4, matchesSkipped=2` (the 2 skipped were pre-existing detector hits at the same positions). - Idempotent re-POST → HTTP 201 with `matchCount=4, matchesSkipped=4`, `relations: []` (no duplicates). Refs: #1593
rubenvdlinde
added a commit
that referenced
this pull request
May 28, 2026
…jection allowlist) (#2008) CRITICAL #1 — RevertHandler RBAC bypass (C1): RevertHandler::revert() called findAcrossAllSources with _rbac:false and _multitenancy:false, letting any authenticated user revert any object in any tenant without permission checks. NotAuthorizedException was imported but never thrown. Fix: - Add missing constructor with AuditTrailMapper, ContainerInterface, IEventDispatcher, MagicMapper, and new PermissionHandler dependency. - Remove _rbac:false / _multitenancy:false flags — use tenant-scoped find. - After the find, call permissionHandler->hasPermission(schema, 'update', object) and throw NotAuthorizedException when denied. CRITICAL #2 — Client-supplied @self overwrites server-controlled fields (C2): Two-layer fix: Layer 1 — SaveObject::setSelfMetadata (primary): The method accepted owner from raw client $selfData and applied it to the entity before applyOwnerAttribution() ran. For logged-in REST requests, applyOwnerAttribution() overrode it; for background/system contexts with no IUserSession user, the client-supplied owner persisted. Removed the owner setter from setSelfMetadata — applyOwnerAttribution() is the sole authoritative owner setter. Layer 2 — MagicMapper::prepareObjectDataForTable (defense-in-depth): Client could inject @self.owner and @self.authorization via the @self block. Added explicit strip of owner and authorization from $metadata before the DB write. Also made the register/schema override unconditional (previously only applied when empty) to prevent identity field injection. Tests updated: SaveObjectDeepTest, SaveObjectTest, SaveObjectCoverageTest (owner-setting assertions inverted to assert null), MagicMapperTest (register/schema values changed to verify server-param override; owner column asserted null). gate output: php -l clean on all 7 files; phpstan no new errors (2 pre-existing errors in test files unchanged); phpunit 457/457 pass on modified test files. References wave-7 deep review (project_deep-review-findings-2026-05-27.md)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Version: 0.1.2