This repository was archived by the owner on May 29, 2026. It is now read-only.
Release: merge development into beta#71
Open
github-actions[bot] wants to merge 290 commits into
Open
Conversation
Contributor
Author
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (110 total)
npm dependencies (266 total)
PHPUnit Tests
Code coverage: 0% (0 / 10 statements) Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Contributor
Author
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (110 total)
npm dependencies (266 total)
PHPUnit Tests
Code coverage: 0% (0 / 10 statements) Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Backend: - TemplateVersionService: version history with create, list, restore, diff - TemplatePreviewService: render templates with sample data - TemplateRenderer: conditional section conversion (data-attributes to Twig) - TemplateService: versioning on update, duplication, optimistic locking - OpenRegisterResolver: version schema resolution - TemplatesController: 8 new endpoints (versions, preview, duplicate, lock) - Register JSON: templateVersion schema, category/tags/lock fields on template Frontend: - Template store (Pinia) with full CRUD, versioning, preview, lock actions - TemplateIndex view with list table - TemplateDetail view placeholder - Navigation: Templates menu item - Views.vue: template view integration Tests: - TemplateRendererTest: conditional section conversion with all operators
- SigningRequestList, SigningRequestDetail, SigningRequestForm - BulkSigningPanel, SignatureVerification
- SigningRequestList, SigningRequestDetail, SigningRequestForm - BulkSigningPanel, SignatureVerification
# Conflicts: # openspec/changes/digital-signing-integration/tasks.md # openspec/changes/enhanced-anonymization/design.md # openspec/changes/enhanced-anonymization/proposal.md # openspec/changes/enhanced-anonymization/specs/anonymization-entity-review/spec.md # openspec/changes/enhanced-anonymization/specs/anonymization/spec.md # openspec/changes/enhanced-anonymization/specs/batch-anonymization/spec.md # openspec/changes/enhanced-anonymization/tasks.md
All tasks complete. Archived to openspec/changes/archive/2026-03-22-advanced-template-management/
Add batch anonymization pipeline for WOO compliance: - BatchStateService: ICache-based batch state management - BatchUploadService: multi-file upload handling - BatchExtractionService: sequential entity extraction - BatchAnonymizeService: batch document anonymization - BatchReportService: CSV audit report generation - EntityConsolidationService: cross-file entity deduplication - WooProfileService: WOO entity category profiles - BatchAnonymizationController: all batch API endpoints - Batch Pinia store and Vue components (BatchAnonymizationView, EntityReviewTable) - OpenSpec artifacts: proposal, design, specs, and tasks
Add batch anonymization pipeline for WOO compliance: - BatchStateService: ICache-based batch state management - BatchUploadService: multi-file upload handling - BatchExtractionService: sequential entity extraction - BatchAnonymizeService: batch document anonymization - BatchReportService: CSV audit report generation - EntityConsolidationService: cross-file entity deduplication - WooProfileService: WOO entity category profiles - BatchAnonymizationController: all batch API endpoints - Batch Pinia store and Vue components (BatchAnonymizationView, EntityReviewTable) - OpenSpec artifacts: proposal, design, specs, and tasks
- Register batch API routes in appinfo/routes.php - Add batchAnonymization to navigation store types - Export batch store from store.js - Add BatchAnonymizationView to Views.vue router - Add Batch Mode button to AnonymizationWidget - Update openspec config schema
Fixes CRITICAL verification findings: - SigningRequest/SignerRecord/SigningAuditEntry schemas in register JSON - Signing register definition added - 9 signing API routes in routes.php - Signing config keys in SettingsService - Version bumped to 4.0.0
- Archive change to openspec/changes/archive/2026-03-22-enhanced-anonymization/ - Sync new capability specs: batch-anonymization, anonymization-entity-review
Manually archived due to existing admin-settings spec format incompatibility (table format vs SHALL/MUST requirement format). All 36 tasks complete, implementation verified.
…tests; add enhanced-anonymization docs
… and service details
chore: add missing generated artifact entries to .gitignore
chore: Update openspec config and gitignore docs artifacts
…hanges chore: Restructure specs to proper OpenSpec format
feat: Enrich all OpenSpec specifications
Contributor
Author
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
PHPUnit Tests
Integration Tests (Newman)
Generated automatically by the Quality workflow.
|
- Move 3 proposed specs (document-creatie-sjablonen, document-signing, register-i18n) to changes/ - Add status: implemented frontmatter to woo-transparency stub - Create .openspec.yaml, proposal.md, tasks.md for each new change - Rename '## ADDED Requirements' to '## Requirements' in archive specs
chore: Final OpenSpec structure cleanup
Contributor
Author
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (110 total)
npm dependencies (266 total)
PHPUnit Tests
Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
chore(docudesk): Convert all specs to change proposals
…templates ci: regenerate docs/features.json from openspec/specs/ [skip ci]
…ient IP, add publiccode.yml (#276) - RegisterDiscoveryService: remove ambiguous `use Exception` import and use fully-qualified `\Exception` in the catch block so Psalm/PHPStan cannot mis-resolve it to the non-existent OCA\DocuDesk\Service\Exception class. - appinfo/routes.php: remove the duplicate signing-routes block that was declared twice (lines 66-74 and 97-105); route names are now unique. - SigningService: inject OCP\IRequest via constructor and replace the direct $_SERVER['REMOTE_ADDR'] read in getClientIp() with $this->request->getRemoteAddress() (Nextcloud proxy-aware, testable). - publiccode.yml: add minimal valid publiccode.yml (v0.4) for Dutch-gov compliance — name, repo URL, version, license EUPL-1.2, nl+en descriptions.
- Add @NoCSRFRequired to all SigningController methods (fixes 412 CSRF errors) - Catch Throwable in listRequests() to handle missing ObjectService methods gracefully - Add tests/e2e/spec-coverage.spec.ts covering all 14 openspec feature groups: admin-settings, dashboard, consent-management, anonymization, anonymization-entity-review, batch-anonymization, template-management, prometheus-metrics, pdf-generation, print-preview, signing-requests, document-register, metadata-enrichment, ocr-document-scanning, letter-correspondence-generation - 44 tests, all passing against localhost:8080
test: add Playwright e2e spec-coverage suite (44 tests, 14/14 specs)
revert: undo #277 — drop @NoCSRFRequired (security) + API-style e2e tests
…g) (#278) Gate-5 (route-auth): was PASS before commit; confirmed clean. Gate-6 (orphan-auth): was PASS; confirmed clean. Gate-7 (no-admin-idor): 35 methods across 8 controllers lacked 401 guard. Added userSession->getUser()===null → STATUS_UNAUTHORIZED guard to: ConsentController (5), CorrespondenceController (3), MetadataController (1), PdfController (2), PrintController (2), SettingsController::create (1), SigningController (8), TemplatesController (13). IUserSession injected into controllers that lacked it. Gate-9 (semantic-auth): was PASS; confirmed clean. Gate-14 (route-reachability): route names for BatchAnonymizationController updated from snake_case batch_anonymization# to camelCase batchAnonymization# to match the scanner's slug-derivation convention; URLs/verbs unchanged. phpstan-baseline.neon regenerated (FP pattern delta for TesseractOCR methods); PHPStan result: [OK] No errors. Gate-17 deferred per instructions.
Annotates all 336 scenarios across 15 specs with either @e2e exclude (pure-backend / unbuilt-UI) or @e2e test references, then adds 24 Playwright UI tests for the 31 UI-observable scenarios that span admin-settings, anonymization, consent-management, and dashboard. Whole-spec excludes (pure backend / no current UI surface): openregister-bridge, pdf-generation, prometheus-metrics, metadata-enrichment, document-register, letter-correspondence-generation, batch-anonymization, anonymization-entity-review, template-management Per-scenario excludes (backend internals within UI specs): admin-settings: auto-init, version gates, REST API details, helper methods, compatibility metadata anonymization: upload/extract/anonymize backend pipeline, entity normalization, UUID, auth checks, service resolution consent-management: service internals, RBAC flags, API endpoints, deadline calculations, no-creation-endpoint gap dashboard: controller internals, CSP, dead-code removal, Pinia wiring, widget script loading Gate-19 final totals: 336 scenarios, 31 covered by UI tests, 305 excluded with reasons, 0 uncovered.
test(gate-19): bring e2e-coverage to 0 uncovered scenarios
…e verify (#291) Addresses three confirmed critical findings: #284 Signature verification always returned valid. SigningVerificationService no longer trusts the self-asserted /DocuDesk-Signature(...) blob: it is now fail-closed (valid=false) unless a server-held HMAC over the document content-hash verifies. Unverifiable /Type /Sig entries report valid=false. Real PAdES/CMS validation remains out of scope and is documented in the code. #283 Consent decisions were readable/forgeable cross-user. Removed the _rbac:false/_multitenancy:false bypass on consent get/update/create so OpenRegister enforces access, added an explicit per-object ownership guard in ConsentController (admins exempt; non-owner -> 404), removed @NoCSRFRequired from the state-changing create/update endpoints, and whitelisted the mutable fields in updateConsentStatus. #282 Sign-as-anyone. SigningService::sign() and decline() now require the authenticated user's UID to match the signer record's userId, else 403. Updated ConsentControllerTest for the new constructor and added ownership guard coverage.
#285, #286) (#292) #285 — Numeric PII silently skipped by anonymization (HIGH) ============================================================== EntityDetectionService::mapEntitiesForAnonymization dropped any detected entity where strlen($text) < 3 OR is_numeric($text) === true. That meant BSN, IBAN, phone numbers, postcodes, bank/account numbers and case-reference numbers — all the most sensitive identifiers — were detected by the NER pipeline but never forwarded to OpenRegister for redaction. They survived verbatim in the 'anonymized' output. The byte-based strlen was also inconsistent for multibyte text. Fix: * Replace the indiscriminate strlen<3 || is_numeric heuristic with a type-aware rule: - Typed PII (BSN/IBAN/PHONE/POSTCODE/ACCOUNT/CASE_NUMBER/KVK/BTW/ EMAIL/PERSON/ADDRESS/LOCATION/ORGANIZATION/DATE/CREDIT_CARD/SSN — see TYPED_PII_TYPES) is ALWAYS forwarded for redaction, regardless of length or numeric-ness. - Only UNKNOWN / unclassified types are still subject to a noise floor, now measured with mb_strlen (characters, not bytes) and lowered to UNTYPED_MIN_LENGTH = 2 so multi-byte single-character tokens are correctly counted. * The is_numeric() exclusion is removed entirely. #286 — Anonymization reports a fabricated replacement count (HIGH) =================================================================== AnonymizationService set $resultInfo['replacementCount'] = count($mappedEntities); i.e. the count of entities SENT to the redaction step, not the count that was actually found and replaced. When a detected value was absent from the literal file text (OCR variance, hyphenation, formatting variants) the count was still reported as success, and a reviewer relying on it could publish an under-redacted document. Fix: * Capture a textual projection of the ORIGINAL document before calling FileService::anonymizeDocument (readNodeTextSafely): - text/* / application/json / application/xml / application/x-yaml nodes: read content directly. - PDF/DOCX/XLSX and other binary formats: return null, so we signal that verification is not possible at this layer instead of silently lying. * verifyReplacements walks the mapped entities and counts how many are literally present (mb_stripos, UTF-8, case-insensitive — mirrors OR's str_ireplace semantics in DocumentProcessingHandler). * The result now surfaces: - replacementsAttempted: int (sent to OR) - replacementsApplied: int|null (literally present, or null when format is unverifiable) - replacementsVerified: bool (false for PDF/DOCX/…) - unmatchedEntities: array<text,type> (sent but not present) * The legacy replacementCount field is preserved for backwards compatibility but now reflects replacementsApplied (the truth) when verifiable, and falls back to replacementsAttempted with replacementsVerified=false otherwise. * A WARNING-level log is emitted whenever sent != applied so the discrepancy is visible in ops dashboards. Tests ===== * EntityDetectionServiceTest: - testMapEntitiesForAnonymizationKeepsNumericBsnPii — asserts the bug-case from #285: BSN '123456782' is now forwarded. - testMapEntitiesForAnonymizationKeepsShortAndNumericTypedPii — phone '06' / '0612345678', postcode '1234AB', IBAN. - testMapEntitiesForAnonymizationDropsUntypedSingleCharNoise — UNKNOWN single-char tokens still dropped (no over-correction). - testMapEntitiesForAnonymizationUsesCharacterLengthForUntypedTokens — mb_strlen vs strlen multibyte difference. - The pre-existing 'FiltersShortAndNumeric' test was rewritten to assert the new correct behaviour (typed PII kept, noise dropped) instead of the old buggy behaviour. * AnonymizationServiceTest: - testReplacementCountIsNoLongerFabricatedFromMappedEntities — asserts the exact #286 bug-line is gone. - testVerificationHelpersExist. - testVerifyReplacementsDistinguishesAppliedFromUnmatched — 4 sent, 3 in source → applied=3, unmatched=[Jo-hn]. - testVerifyReplacementsIsCaseInsensitive — matches OR's str_ireplace. - testVerifyReplacementsReportsUnverifiedForBinaryFormats — null source → applied=null, verified=false. - testReadNodeTextSafelyReturnsNullForBinaryMime — application/pdf → null. - testReadNodeTextSafelyReturnsContentForTextMime — text/plain → content returned. Verification on live Nextcloud (localhost:8080, container deploy) ================================================================ BEFORE FIX (#285 reproduction): of 4 sent entities (BSN, phone, postcode, person), only 2 forwarded — BSN and phone silently dropped. AFTER FIX: all 4 forwarded. #286 fixture (4 sent, source has 3 literally): replacementsAttempted: 4 replacementsApplied: 3 replacementsVerified: true unmatchedEntities: [{text: 'Jo-hn', entityType: 'PERSON'}] Binary degradation (null source): replacementsApplied: null replacementsVerified: false phpcs (--standard=phpcs.xml — lib/ scope) on the two edited lib files: 0 errors, 0 warnings (added @SPEC class tags addressed the pre-existing SpecTagSniff warnings on both services). phpunit (anonymization suite): 27 tests, 73 assertions, all passing.
…udit immutability (#287, #288, #289) (#293) Three MEDIUM-severity findings on the signing pipeline from the 2026-05-27 team-reviewer pass, fixed together because they all touch the same end-to-end native-signing flow and the audit register that backs it. #287 — NativeSigningProvider sessions are no longer per-request only The provider held sessions in a per-instance `$sessions` array, so `initiateSigning()` created a row that `checkStatus()`, `downloadSignedDocument()` and `cancelSigning()` (running in fresh HTTP requests with a freshly-empty array) could never see — every native flow failed with "session not found". A new `signingSession` schema is added to the `signing` register; sessions are persisted via the canonical OR `ObjectService::saveObject(...)` / `findAll(['filters' => ['externalId' => ...]])` surface, keyed by `externalId`. The SES marker / HMAC embedding in `downloadSignedDocument()` is acknowledged as a separate follow-up: until the PDF marker writer ships, the method returns the persisted `signedDocumentPath` (or falls back to the original `documentPath`) and logs an info-level note flagging that the marker hasn't been embedded yet. The signing register's version is bumped 1.0.0 → 1.1.0 and the top-level register schema 5.0.0 → 5.1.0 to trigger OR's `imported_config_docudesk_version` gate on upgrade. #288 — SigningController::listRequests() no longer masks real failures The broad `catch (\Throwable $e)` previously returned an empty list with `notConfigured: true` and logged at WARNING for any failure — an OR/DB outage was indistinguishable from "register not configured yet". The catch is narrowed to `\Error` (the genuine missing-OR-method / sidecar-lag case the original comment claimed to handle) and logs at ERROR; real `\Exception` / runtime infra failures now propagate to the framework's 500 handler so monitoring sees them. The `RegisterNotConfiguredException` branch is retained for the calm "setup state" empty-state UI. #289 — Signing audit immutability is enforced at the storage layer `SigningAuditService::rejectUpdate()` / `rejectDelete()` were misleading dead code: nothing routed OR mutations through them. They were removed. The `signingAuditEntry` schema in `lib/Settings/docudesk_register.json` carries `immutable: true` AND `appendOnly: true`, so OR enforces append-only at the mapper level for every code path — the real Archiefwet-1995 guarantee, no longer contingent on an in-app routing pattern that didn't exist. Tests: - tests/unit/Service/Signing/NativeSigningProviderTest.php (6 tests) - tests/unit/Controller/SigningControllerTest.php (4 tests) - tests/unit/Service/SigningAuditServiceTest.php (5 tests) All 15 new tests pass (34 assertions). phpcs clean on touched files (only pre-existing class-level @SPEC warnings remain).
…#290) (#294) (a) SigningAuditService::getAuditTrail - replace full-register getObjects load + PHP array_filter with a server-side searchObjects call filtered on signingRequestId; prevents excessive memory use as audit log grows (finding #290a). (b) ConsentCrudService::createFromRequest - drop the merge-all-extra-fields approach; only documentId/entityType/entityText are forwarded to createConsentRequest; all other request params (consentStatus, publicationDecision, userId, etc.) are silently dropped so callers cannot forge initial consent state (finding #290b). Also: add @SPEC class-level tag to both classes (pre-existing PHPCS warning); update OpenRegisterStubs searchObjects() to accept a query array param; add unit tests asserting the server-side filter (searchObjects called with signingRequestId) and the extra-fields drop (createConsentRequest called without $extra).
PHPCS: phpcbf auto-fixes 5 missing //end-try closing comments in SettingsController, SigningVerificationService, and TemplatesController. PHPStan: wire ALLOWED_CREATE_FIELDS constant into createFromRequest() via array_intersect_key so it is no longer unused; remove redundant ?? '' from getSigningSecret() where getValueString() already returns a non-nullable string. PHPMD (easy): rename short vars $mc→$minConfidence, $p→$params, $d→$data; hoist count() out of for-loop in BatchUploadService; eliminate 3 ElseExpression violations in AnonymizationController, BatchAnonymizationController, and AnonymizationService using early-return / default-then-override patterns.
fix: resolve PHPCS, PHPStan, and PHPMD violations
Adds `x-openregister-lifecycle` to the signingRequest schema so OR's
platform-annotations Newman suite can drive the signing workflow via
the standard `/api/objects/{id}/transition` endpoint.
field: status (matches the existing enum on the schema)
initial: DRAFT
transitions:
- send DRAFT → PENDING (notify signers)
- start PENDING → IN_PROGRESS (a signer opens the request)
- complete IN_PROGRESS → COMPLETED (all signers done; terminal)
- decline IN_PROGRESS → DECLINED (terminal)
- expire PENDING → EXPIRED (deadline passed; terminal)
- cancel PENDING → CANCELLED (initiator cancels; terminal)
Matches the Newman flow `send → start → complete` exactly, plus the
three terminal-branches needed for completeness.
Closes the docudesk half of the Tier-3 follow-up from OR's session
report; decidesk half lands separately.
feat(schemas): lifecycle annotation on signingRequest
#297) Replace all positional saveObject($register, $schema, $data) calls with the named-arg form saveObject(object:, register:, schema:), replace non-existent getObject(3-arg) with find(id:, register:, schema:)+jsonSerialize, and replace non-existent getObjects with findAll(['filters'=>...]). Remove the \Error fallback in SigningController::listRequests — it existed solely to catch the missing-getObjects deployment-drift case which no longer applies. Fix NativeSigningProvider::persistSession to use the same canonical surface. Add missing IUserSession/Http stubs + findAll stub to the test harness. Closes findings C1.
C2 (MetadataService): removed `_rbac:false/_multitenancy:false` overrides from find() and saveObject() calls, restoring per-tenant data isolation. C3 (AnonymizationController): added IRootFolder file-ownership guard; extract() and anonymize() now return 404 when the calling user's folder does not contain the requested fileId (prevents cross-user file IDOR). H1 (ConsentController/ConsentCrudService/ConsentService/ConsentUpdateHandler): consent list and byDocument endpoints now filter results to the calling user unless the caller is an admin, preventing cross-user consent data disclosure. M2 (SigningController): getAudit() now checks that the caller is the request initiator or a listed signer before returning the audit trail; non-admin callers who are neither receive 403 Forbidden. Tests: all 37 unit tests (AnonymizationControllerTest + ConsentControllerTest + SigningControllerTest + MetadataControllerTest + MetadataServiceTest) green. Stubs: IRootFolder moved to OCP\Files namespace; IGroupManager/IUserSession stubs added; Http STATUS constants added.
M1 (SigningVerificationService::allSignaturesValid): added count > 0 guard so that an empty signatures array returns false instead of true. A document with zero verifiable signatures was previously incorrectly reported as valid. L1 (SigningVerificationService::stripAssertionMac): replaced str_replace with preg_replace + preg_quote so the MAC value is treated as a literal string regardless of any regex metacharacters it may contain. L2 (SigningAuditService::VALID_ACTIONS): added 'START' to the allowed action list so signing-session initiation events are not silently dropped by the logEvent() guard. Tests: new SigningVerificationServiceTest (5 tests) covers M1 (empty array → false, non-empty all-valid → true, one-invalid → false) and L1 (plain MAC stripped, regex-metachar MAC stripped). SigningAuditServiceTest gains one new test asserting 'START' is in VALID_ACTIONS (L2). All 13 tests green.
Resolves CVE-2026-48805, CVE-2026-48806, CVE-2026-48807, CVE-2026-48808, and CVE-2026-46636 (sandbox bypass / policy bypass variants, 2026-05-27). All five affect twig/twig <3.27.0. composer audit is now clean.
fix(security): bump twig/twig to ^3.27.0 (CVE-2026-48805/06/07/08, CVE-2026-46636)
C1: SettingsController::create was accessible to any authenticated user, allowing overwrite of signing_verification_secret and all other app-config keys including register/schema pointers. Fix: restrict to admin-only (groupManager::isAdmin check + remove @NoAdminRequired) and add an explicit WRITABLE_KEYS allowlist in SettingsService::updateSettings so non-listed keys (incl. signing_verification_secret) are silently rejected. C2: ObjectionDeadlineChecker::checkObjectionDeadline called OR ObjectService find() with _rbac:false + _multitenancy:false, enabling cross-tenant consent record access. Fix: remove both flags so OR enforces caller tenant + RBAC. C3: RegisterDiscoveryService::fetchAvailableRegisters called RegisterService::findAll and SchemaMapper::find with _multitenancy:false, exposing all tenants' registers and schemas via GET api/settings. Fix: remove _multitenancy:false overrides so discovery is scoped to the caller's tenant. C4: Drop @NoCSRFRequired from all mutating (POST/PUT/DELETE) endpoints across the app — @nextcloud/axios already sends the requesttoken header in the SPA; this change blocks cross-site forgeries with no user impact. GET routes retain @NoCSRFRequired. Also fix pre-existing PHPCS violations in ConsentController (ternary + implicit-bool) and SigningController (alignment + missing //end try).
…wlist (#302) testUpdateSettingsPersistsValues was passing 'test_key' which is not in WRITABLE_KEYS, causing setValueString to be called 0 times (expected once) and the key to be absent from the result. Switch to 'signing_provider' which is in the allowlist. Also add testUpdateSettingsSilentlyRejectsUnknownKeys to lock in the wave-3 C1 behaviour: unknown keys must be dropped and must never reach setValueString.
- SigningVerificationService: remove spaces around concat operator in preg_replace - ConsentCrudService, ConsentService, ConsentUpdateHandler: add missing @param for $ownerUid; fix @param alignment spaces - SigningService: convert 6 multi-line ternary expressions to if/else blocks (Inline IF not allowed)
fix(quality): resolve all PHPCS errors — composer check:strict now exits 0
…tee HTTP 400
Move entities/bases input validation ahead of verifyFileAccess() in
AnonymizationController::anonymize(). Previously, the file-access guard
ran first: a non-existent fileId returned 404, masking the validation
entirely, and a valid fileId with malformed bases reached the service layer
where it could throw an unhandled exception (HTTP 500).
After this fix, malformed input (bases is not an array, or contains a
non-string item) always returns HTTP 400 with a clear error message,
regardless of whether the referenced file exists.
Two regression tests added to AnonymizationControllerTest verifying the
new ordering: bases validation returns 400 even when the controller's
root-folder mock reports no matching file.
Fixes the Newman test cases "invalid bases - non-array" and
"invalid bases - non-string item" against POST /api/anonymization/anonymize/{fileId}.
fix(anonymization): validate bases before file-access check to guarantee HTTP 400
…atch IDOR + jobId CSPRNG + signer IDOR + consent multitenancy) (#306) C1 (structural — issue #304): NativeSigningProvider::initiateSigning() and downloadSignedDocument() now throw a descriptive RuntimeException referencing #304 so admins who enable signing_enabled=1 see the gap at once rather than getting a silent no-op. The full request<->provider wiring is deferred to #304. C2 (batch IDOR): BatchStateService::getBatch() now compares batch['userId'] against the authenticated user UID; non-owners receive a RuntimeException. Admins bypass the check. IUserSession + IGroupManager injected; tests updated and three new ownership tests added. C3 (jobId CSPRNG + jobStatus IDOR): generateJobId() in CorrespondenceService replaced mt_rand UUID with random_bytes (RFC-4122 v4, CSPRNG). jobStatus in CorrespondenceController now compares options.userId against the current user UID and returns 403 on mismatch. C4 (signer IDOR): SigningService::sign() and decline() now verify signer['signingRequestId'] === $requestId before accepting the signer record, preventing a signer-ID-hijack across signing requests. C5 (consent _rbac:false): Already fixed in a prior wave on development; confirmed absent in all 6 cited sites (ConsentService, ConsentUpdateHandler, ConsentCrudService, MetadataService).
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.
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.