ci(docs): sync documentation branch with development#1509
Merged
Conversation
- Convert Dutch hardcoded strings to English t() keys in OrganisationsIndex, UploadFiles - Wrap bare attributes and template strings across 20+ Vue files - Wrap showSuccess/showError notifications in settings store - Update l10n files with new keys and Dutch translations
Standardize on #actions across all components per the updated slot naming convention in @conduction/nextcloud-vue.
Update all translation keys to use sentence case (only first letter capitalized) instead of title case. Keys changed: - "Add Groups" → "Add groups" - "Active Collections" → "Active collections" - "API Key" → "API key" - And 400+ similar keys across all apps Sentence case for keys improves consistency and readability while preserving proper English grammar in translated values. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap bare strings in 20+ Vue files (modals, views, settings, workflow) - Convert Dutch strings in OrganisationsIndex and UploadFiles to English - Fix template attributes (label=, placeholder=, title=, aria-label=) - Wrap showSuccess/showError notifications in t() - Regenerate l10n files with 1,863 keys (sentence case)
The two NcTextArea placeholders in EditWebhook.vue were written as inline
template expressions containing a `\n` escape:
:placeholder="t('openregister', 'X-Custom-Header: value\nAuthorization: Bearer token')"
:placeholder="t('openregister', 'objectType: object\naction: created')"
Vue's template compiler inlines that expression into the generated render
function, where the `\n` is turned into a real newline character inside a
single-quoted JS string. Webpack then emits that literal newline into
openregister-main.js, producing an unterminated string constant. V8 throws
"Invalid or unexpected token" on parse and the entire app bundle never
executes, so /apps/openregister/ renders a blank page under the Nextcloud
shell with no further console info.
Move both strings to `headersPlaceholder` / `filtersPlaceholder` computed
properties (where `\n` is a normal JS escape) and bind them by name. Added
a comment on the computed block so the next person who's tempted to inline
a multi-line placeholder knows why not to.
Add bind-mount for ../decidesk so the Decidesk app is available in the dev nextcloud container alongside the other custom_apps.
…ent class name Previously the listener decided whether to inject its script by string- matching "OCA\\Mail\\" against the fully qualified event class name. That was fragile: the listener is registered against the core BeforeTemplateRenderedEvent, and Mail's own class may not appear in the FQCN depending on how the event is dispatched. Instead, verify the event is a BeforeTemplateRenderedEvent, cast the response to TemplateResponse, and check $response->getApp() === 'mail'. This is the supported way to target rendering from a specific app and avoids the coincidental-string-match hazard.
Adds docker/mail/seed-cases.sh which creates two caseType objects (Omgevingsvergunning, Kapvergunning) and two case objects (ZK-2026-0142, ZK-2026-0034) in the Procest register (id=92) via the OpenRegister objects API. The cases are the counterparts of the emails seeded by seed-mail.sh, so the OpenRegister mail sidebar has real link targets to demo the email-to-case linking flow end-to-end. Default target is http://localhost:8080 with admin:admin; override via positional args. Script header documents prerequisites and the follow-up TODOs (Decidesk meetings, Pipelinq leads) that are blocked on upstream register initialisation.
…ns' into fix/header-info-email # Conflicts: # lib/Db/MagicMapper/MagicSearchHandler.php # lib/Listener/MailAppScriptListener.php # src/modals/webhook/EditWebhook.vue
Proposes a cross-repo Features & Roadmap menu item mounted in every Conduction app's NcAppNavigationSettings slot above the gear. - Features tab: shipped capabilities from openspec/specs/, extracted at build time into docs/features.json (committed, also powers Docusaurus public features page) - Roadmap tab: open GitHub issues from the app's own repo, sorted by reactions, with pipeline-label blocklist and full markdown body rendering - Suggest-feature modal launched from the route header and from any widget/page declaring a specRef via its NcActions menu - Extends existing GitHubHandler with listIssues() + createIssue(); user PAT preferred, server PAT fallback with attribution prefix - Out of scope: ADR-019 fleet rollout, Discussions, Accept->specter wiring Capabilities: - github-issue-proxy - features-roadmap-menu Validates strict.
The body-mount fix from 04948cc was accidentally reverted during a merge conflict resolution, causing the sidebar to disappear whenever Mail's Vue root re-renders. Restored by mounting the Vue app via $mount() (no el:) and appending to document.body. Gate on the presence of #initial-state-mail-accounts so the sidebar only injects on Mail app pages without depending on transient DOM that Mail's Vue owns. Added fixed-position CSS on .or-mail-sidebar (higher specificity than NcAppSidebar's .app-sidebar default so the panel floats on the right with rounded corners, 8px margins and the classic NC chrome. Also wires up useAttachmentDrag composable: patches Mail's MessageAttachment DOM elements with draggable=true and a dragstart listener that writes attachment metadata (messageId, attachmentId, fileName, mime, size, downloadUrl) into dataTransfer under the application/x-nc-mail-attachment MIME type. ObjectsTab already consumes this payload and uploads the file to the dropped object via /filesMultipart. Upstream PR to make Mail attachments natively draggable tracked separately. Seed script gained an extra email with three real attachments (2 PDFs + 1 PNG) matching ZK-2026-0142 so the drag-drop flow has demo data out of the box.
Hydra's orchestrator requires a hydra.json per change to dispatch. Adds the schema-v2 file pointing at issue #1328 with empty depends_on (greenfield change with no spec dependencies). Without this file, Hydra's supervisor silently skips the change even if it carries the `ready-to-build` label.
Create Beta - Fix faulty constructors
Development to beta
Specter-generated spec directories that were sitting untracked. Each contains the standard openspec scaffold (proposal.md, design.md, tasks.md, specs/, hydra.json) for a future implementation cycle. The 21 specs include: - 18 integration-* specs (calendar, contacts, deck, email, photos, etc.) - 3 standalone: cleanup-linked-entity-type-map, fix-date-histogram-mariadb, seed-related-items Several of these will need re-splitting after market-intelligence#30 landed (MAX_FEATURES_PER_SPEC: 100→15). The companion preflight in hydra#196 will block oversized ones at builder dispatch with a clear "spec too large" comment.
Merge development to beta
Development
…-update Updated package
…ative-engines-adr024-027
…r CVEs Resolves PKSA-hznc-gbby-6w16 (CVE-2026-40296) and PKSA-jtdk-dcr5-f11n (CVE-2026-35453). Cascaded minor bumps to symfony/var-dumper, symfony/deprecation-contracts, symfony/polyfill-mbstring (all in-range).
# Conflicts: # src/mail-sidebar.js # src/mail-sidebar/MailSidebar.vue
…ration-2026-04 # Conflicts: # lib/Controller/OasController.php
Blockers (F03–F06): - F03 TransitionController/Engine — gate transition() with PermissionHandler::hasPermission(action='update', object) and availableActions() with action='read'. Adds NotAuthorizedException catch in the controller (403 Forbidden). Without this gate any authenticated user could advance any object's lifecycle. - F04 AggregationRunner — gate run() with hasPermission(action='list') on the schema. Adds 403 catch in AggregationController. Documents the per-object ACL leak that remains for schemas with object-acl / conditional rules; fix tracked alongside the aggregations-backend-native follow-up. - F05 AnnotationNotificationDispatcher — validate every recipient uid via IUserManager::userExists() (per-request cached). Covers the `users`, `field`, and `relation` recipient kinds so attacker- controlled object data cannot direct notifications at admin uids. - F06 LifecycleGuardRegistry / AnnotationNotificationDispatcher — drop every `\OC::$server` reference in lib/. Inject IServerContainer instead. Aligns with the ADR added in this same PR (docs/development-notes/AUDIT_2026-05-01.md). The Talk emit path also prefers the injected IConfig. Concerns (F07–F15): - F07 NotificationHistoryController — return 401 when unauthenticated; force `recipient = currentUid` filter for non-admins so the endpoint cannot dump every user's notification history. - F08 Dispatcher.interpolate() — htmlspecialchars-escape every substituted value (defence in depth before NC's own render layer). - F09 ScopesController.index() — add `@NoAdminRequired`. Endpoint was silently 401-ing for the very audience it's designed to serve. - F10 UrnController — add `@NoAdminRequired` to resolve / lookup / bulk. - F11 RealtimeController — return 401 when no user session, instead of the empty-stream masquerade. - F12 LifecycleValidationListener — document the trust contract: only fires on `ObjectUpdatingEvent`, so callers MUST go through `ObjectService::saveObject()` for lifecycle integrity. - F13 Schema::validateConfigurationArray — declare the `x-openregister-*` vocabulary in `ANNOTATION_VOCABULARY` and drop unknown keys at save time so `x-openregister-lifecycl` (typo) is caught early instead of round-tripping silently. - F14 CalculationEvaluator::formatDate — document the trust model (schema authors are admin-equivalent; format string is not allowlisted). - F15 AggregationRunner — cap PHP fallback at 10 000 rows (PHP_FALLBACK_ROW_CAP), surface `truncated: true` in the result. Native Postgres path is unaffected. F16 dompdf 3.1.5 — `composer audit` on production deps reports no known advisories. Single instantiation site at PdfReportWriter:69 (verified via grep). isRemoteEnabled=false / isPhpEnabled=false on that path — no other Dompdf instances added. F01 (split into four PRs) and F02 (no CI on head SHA — push trigger excludes `platform-integration-*`, pull_request types omit `synchronize`) are addressed in PR comment replies, not by code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves conflicts in: - lib/Service/Lifecycle/TransitionEngine.php — keep F03 RBAC gate (NotAuthorizedException → 403); take development's named-arg style for getLifecycleAnnotation() calls. - lib/Service/Aggregation/AggregationRunner.php — keep F15 PHP_FALLBACK_ROW_CAP + truncated flag; take development's broader constructor (OrganisationService, optional SearchBackendInterface); deduplicate the two RBAC gates added in parallel on each branch and upgrade development's RuntimeException-based gate to NotAuthorizedException for proper 403 mapping. - lib/Service/Notification/AnnotationNotificationDispatcher.php — keep F05 userExists() guard on extracted relation uids; take development's named-arg style; merge development's @param/@return docblock additions with the F08 escape-rationale and F06 IServerContainer-ADR rationale. - lib/Service/Calculation/CalculationEvaluator.php — keep F14 trust- model docblock; merge development's @param/@return tags. - lib/Controller/RealtimeController.php — keep F11 401 guards on events() and cursor(); take development's @param/@return docblock additions and the new org-scoped cursor implementation. - lib/Controller/UrnController.php — keep F10 @NoAdminRequired on all three methods; merge development's @param/@return docblock additions. - lib/Controller/NotificationHistoryController.php — accept development's wording in the 401 error body ("Authentication required"). Functional behaviour unchanged. - lib/Controller/OasController.php — accept development's spec path (`retrofit-2026-05-01-oas-generation`); the directory in the merged tree only exists under this name. php -l on every edited file is clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve the requested blockers by restoring a Vue 2 single-root template, hardening sidebar mount deduplication, and implementing object-card drop uploads for mail attachments. Also make seed-cases idempotent and environment-resilient with API-based ID discovery plus overrides, and add coverage for attachment drag behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
Addresses the phpcs failures flagged on the merge commit: - TransitionEngine.php — add docblock for $permissionHandler param and switch the two NotAuthorizedException throws to named-parameter form (`message: sprintf(...)`). - LifecycleGuardRegistry.php — add docblock for $serverContainer and re-align the now-three-param block. - AggregationRunner.php — switch the NotAuthorizedException throw to named-parameter form. The multi-line IF closing-paren style and equals-sign alignment were auto-fixed by phpcbf. - Schema.php — blank line after the if-closing brace inside validateConfigurationArray (auto-fixed by phpcbf). phpcs --standard=phpcs.xml now reports 0 errors across all four files. The 3 remaining warnings (line-length in computeMetric's match block) predate this PR and live in unaltered code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Round 2 of the c34082e phpcs cleanup, plus the dompdf license override flagged as the only remaining 🔴 in the latest CHANGES_REQUESTED review. License gate - .license-overrides.json — add `dompdf/dompdf` (LGPL-2.1) with the same rationale we use for smalot/pdfparser (LGPL family is allowlisted; the checker can't normalise the SPDX variant). The single instantiation site PdfReportWriter:69 keeps isRemoteEnabled / isPhpEnabled false. phpcs in F03/F05/F06/F07/F11 fix-commit files (the 21 errors flagged on 535973c that the c34082e pass missed) - NotificationHistoryController — add docblocks for $userSession + $groupManager (F07). - RealtimeController — add docblock for $userSession (F11). - TransitionController — phpcbf supplied the missing `//end try` end-comment (F03 long try block). - AnnotationNotificationDispatcher — add `$serverContainer` docblock (kept short to stay inside the 150-char hard limit), shift the five existing optional-param docblocks back into alignment, switch the three `userExists($u)` calls to named-parameter form (`uid: $u`), add the missing `@return bool` tag on userExists itself, and let phpcbf clean up the no-blank-line-after-control violations introduced alongside the F08 escape changes. phpcs in upstream-side files that the full-repo gate also fails on - PermissionHandler — add `@param Schema|null $schema` for the new optional cache-break parameter on buildPermissionCacheKey; phpcbf supplied the missing `//end try` end-comment. - AuditTrailController — add docblocks for $userSession + $groupManager. - ReportsController — add docblock for $logger; phpcbf added the missing `//end try` end-comment. - ActionsController — add docblocks for $userSession + $groupManager; capitalise an inline-comment first letter. - RegistersController — phpcbf restored two ternary spaces (auto-fix). `./vendor/bin/phpcs --standard=phpcs.xml` now reports 0 errors across the full lib/ tree (warnings only, all line-length on pre-existing match arms / long format strings — none introduced by F03–F16). `php -l` clean on every touched file. License-checker should now stop flagging dompdf as denied. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolutions per #1353 review thread: Blockers - aggregations-and-calculations/tasks.md: explicit ADR-028 gating note pointing at split PR #1354 — change MUST NOT merge in current bundled form. - lifecycle-annotation spec: add auth contract for POST /transition (NoAdminRequired, CSRF enforced, 401/403 codes + scenarios). - lifecycle-annotation spec: forbid duplicate (from,to) transition pairs; this makes ObjectTransitionedEvent.action deterministically resolvable on direct PATCH; new 422 code lifecycle-duplicate-from-to + scenario. - aggregations spec: new MUST clause for organisation/register multi-tenancy scoping on aggregate queries (closes the gap that PR #1357/#1419 hit) + cross-org and cross-register scenarios. - notifications-annotation/tasks.md: explicit prerequisite note (depends_on aggregations-and-calculations) — PlaceholderResolver + cache-invalidation event live there. - platform-capabilities.md: mail-sidebar status corrected to implemented; RBAC and multi-tenancy rows now reference the active specs (rbac-scopes, tenant-isolation-audit/lifecycle/quotas) with explicit archive notes for the legacy slugs; geo-metadata-kaart reverted to proposed (still in changes/, not yet graduated). Concerns - lifecycle spec: define StoppableEvent rejection-metadata contract (setRejectionReason / getRejectionReason on ObjectUpdatingEvent; ObjectService::saveObject translates stopped+reason into HTTP 422). Add prerequisite task 1.2a to extend the event class if missing. - notifications spec: normative channel block format table (per kind) + explicit prohibition on inline webhook URLs (SSRF); end-to-end annotation example. - notifications spec: scenarios for created and updated triggers, including only_if_changed field-diff semantics. - aggregations spec: computeOn vocabulary ('save' default; 'transition:<name>' explicitly cross-spec dependent on lifecycle-annotation, with fail-fast 422 if used without lifecycle). - platform-capabilities.md: mark Hydra spec linter and CI catalog enforcement as planned, not shipped. - three deltas/tasks.md: explicit CHANGELOG-entry obligation tasks (deferred to implementing PR; spec PRs document the obligation). - lifecycle spec: auth contract requirement now captures NoAdminRequired in the spec body, not only in tasks.md. Minors - aggregations spec: time-bucket UTC semantics + v2 deferral note. - notifications spec: throttle window grammar pinned to ^([1-9][0-9]*) per (second|minute|hour|day|week)$. Composer.lock plugin-api-version downgrade (concern #14): no spec edit; addressed in the inline review reply (CI Composer version is the canonical regenerator; the field is an environment artefact and the symfony bumps in the same hunk are the substantive change). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…vice Add a slug-aware bridge to ObjectService::searchObjects() that resolves register and schema slugs to numeric IDs via the mappers (scoped to the caller's organisation by the standard multi-tenancy filter) and delegates to the numeric-ID search path. Closes the OpenBuilt smoke-test foot-gun where callers passed slugs in @self.register / @self.schema and got zero results back — the numeric-ID contract on searchObjects() is now strict, so any future misuse fails loudly at the call site rather than silently returning empty. Slug-aware callers (controller layer, OpenCatalogi, softwarecatalog) get a one-method-call upgrade path. Multi-tenancy honours the same _multitenancy flag every other lookup uses; a slug that exists in another organisation but not the caller's throws DoesNotExistException via the mappers' standard organisation filter. Also documents the numeric-ID contract inline on searchObjects() so the foot-gun cannot reappear silently.
countSearchObjects(['@self' => ['schema' => $id]]) only returns a real count when BOTH register AND schema IDs are present in the @self filter; single-axis queries silently return 0. That made the DELETE safety guard on schemas and registers a no-op — `DELETE /schemas/{id}` and `DELETE /registers/{id}` succeeded even when objects were attached, because `objectCount` was always 0 and the 409 branch never fired. Switch both destroy() controllers to ObjectEntityMapper::getStatistics() on the single-axis path (registerId|schemaId), which is the same handler the rest of the controller already uses for stats display (see SchemasController.php:288, 924 and RegistersController.php:366, 399). After the fix, deleting a schema/register with attached objects without `?force=true` returns 409 with the orphan count, matching the runtime-schema-api ADR. Also apply PHPCS auto-fixes flagged on PR #1464 review: - RegistersController.php:539,648 — missing `//end try` end-comments. - ImportHandler.php:2419-2423 — docblock param-type spacing. PHPCS now reports zero errors on the touched files.
…uto-Register Adds spec-specific unit tests for the new behaviour introduced by change openregister-runtime-schema-api: - tests/Unit/Service/ObjectServiceSearchBySlugTest.php (3 tests) covers REQ 'ObjectService.searchObjectsBySlug resolves slugs at the slug-aware layer': resolves both slugs into the numeric @self block, throws DoesNotExistException identifying register-side failures, throws DoesNotExistException identifying schema-side failures. - tests/Unit/Service/Configuration/ImportHandlerApplicationTypeTest.php (3 tests) covers data-import-export delta REQ 'importFromApp auto-creates a Register for application-type configurations': first import creates Register with derived slug/title/schemas[], re-import is idempotent on (slug, org) and only updates, library/untyped configs are skipped. - tests/bootstrap-spec-docker.php — Docker bootstrap that resolves OCA\OpenRegister\* to the spec worktree instead of the main custom_apps mount, so spec branch tests can run against the live NC container without disturbing the main mount.
…sters Adds spec-specific unit tests for the runtime-schema-api guard introduced in feature/runtime-schema-api: - tests/Unit/Controller/SchemasDestroySafetyTest.php (3 tests) covers REQ 'Runtime schema deletion is guarded by object count': DELETE returns 409 with schema-has-objects + objectCount when objects attached and force=false, DELETE with force=true succeeds + invalidates cache + logs WARNING with orphan count, DELETE on unused schema succeeds (baseline). - tests/Unit/Controller/RegistersDestroySafetyTest.php (3 tests) covers REQ 'Same CRUD guarantees apply to /api/registers': DELETE returns 409 with register-has-objects + objectCount when objects attached and force=false, DELETE with force=true succeeds + invalidates cache + logs WARNING with orphan count, DELETE on unused register succeeds (baseline).
…ntegration
Adds the canonical integration test referenced by tasks.md §4.4 — a
service-level round-trip through SchemasController that proves the cache
invalidation chain holds in the same PHP worker:
- POST /api/schemas + immediate GET — new schema visible (cache invalidated)
- PUT /api/schemas/{id} + same-worker re-read — new description observed
- DELETE without ?force=true returns 409 when objects exist
- DELETE with ?force=true returns 200; cache cleared; schema gone
- ObjectService::searchObjectsBySlug resolves a fresh slug-pair in-worker
Uses real services from \OC::\$server (SchemaMapper, RegisterMapper,
MagicMapper, ObjectService, SchemaCacheHandler, FacetCacheHandler,
SchemasController) and mocks only IRequest as a thin data carrier. Whole
suite is skipped automatically when Nextcloud isn't bootstrapped so the
host \`composer test:unit\` run stays green.
phpunit.xml updated so the Integration Tests testsuite picks up both the
existing tests/integration (newman) and the new tests/Integration (php).
…DELETE safety
Adds tests/integration/openregister.postman_collection.json — a focused,
spec-scoped Newman collection that exercises the end-to-end HTTP round-trip
the unit + service-level tests can only assert in isolation:
1. POST /api/registers seed register
2. POST /api/schemas create schema with `x-openregister-lifecycle`
3. GET /api/schemas/{id} immediate read sees the new schema (cache cleared)
4. PUT /api/schemas/{id} update description; chained GET sees update
5. PUT /api/registers/{id} attach schema to register
6. POST /api/objects/{r}/{s} create object against the schema
7. GET /api/objects/{r}/{s}/{u} read object back
8. DELETE /api/schemas/{id} no `?force=true` → 409 (schema-has-objects)
9. DELETE /api/schemas/{id}?force=true → 200; chained GET → 404
10. DELETE /api/registers/{id}?force=true → 200
Also updates openspec/.../tasks.md: 4.4 + 6.4 now closed (integration test
landed); 5.4 cross-references the unit-level ImportHandler coverage and
explicitly defers full importFromApp upload coverage to a follow-up.
Run inside the container:
docker exec -u 33 nextcloud newman run \
/var/www/html/custom_apps/openregister/tests/integration/openregister.postman_collection.json \
--env-var base_url=http://localhost --env-var admin_user=admin --env-var admin_password=admin
Post-rebase onto development: - psalm: 11 UnusedBaselineEntry errors removed (entries no longer match) - phpstan: baseline regenerated, net -50 lines (1455 errors tracked, matches current source after rebase reconciled both branches)
- RegistersController gained a 19th ctor arg (RegisterCacheHandler); update RegistersControllerTest + RegistersDestroySafetyTest to pass it (plus the previously-missing ContainerInterface/IGroupManager in the DELETE-safety test). - SchemasController create/update/destroy now route schema-cache cleanup through SchemaCacheHandler::invalidate(); update SchemasControllerTest expectations and add getStatistics() stubs for the new DELETE-safety object count. Use real Schema entities so the magic getId() resolves. - SchemasDestroySafetyTest: append the 14th ctor arg (ContainerInterface). - ObjectServiceSearchBySlugTest: pass the dateTimeNormalizer ctor arg. - RegistersControllerTest destroy/* tests: use real Register entities and stub getStatistics() so RegisterCacheHandler::invalidate(int) is fed a real id.
feat(openspec): runtime-schema-api — runtime CRUD on schemas + registers
Adds the spec set for extending EntityRelation with an optional bases JSON column. The anonymise endpoint accepts bases per entity, persists them on the matching relation row, and strips them from the payload before forwarding to OpenAnonymiser. Backwards-compatible — callers that omit bases see identical behaviour. Tightly scoped: this does not retrofit the broader EntityRelation surface (currently uncovered by an OpenSpec capability). Refs: #1435 Pair: ConductionNL/docudesk#135 (anonymisation-grondslagen-summary + anonymisation-grondslagen-and-prohibition-gate hard/soft dep).
Adds the spec set for extending TextExtractionService with EML support via zbateson/mail-mime-parser. Two outputs share the parser: - Flat plain-text extraction (headers + body + recursively-extracted attachment text inline) for entity detection. - A new public parseEmlStructured() returning headers + both text/plain and text/html body parts + attachments-with-bytes (recursive nestedEml capped at depth 3) for downstream PDF assembly. Tightly scoped: does not retrofit the broader TextExtractionService surface (currently uncovered by an OpenSpec capability). Refs: #1438 Pair: ConductionNL/docudesk#135 (eml-pdf-assembly hard dep, anonymise-output-as-pdf-by-default soft dep).
fix(mail-sidebar): restore body-mount + attachment drag-drop + header email typo
…s-adr024-027 feat(openspec): platform capabilities catalog + three declarative-annotation deltas
Blockers: - B1: add audit-trail Requirement (ADR-022 / Woo compliance). Every set/update of bases produces an audit entry with previousBases, newBases, actor UID (per ADR-005, not display name), timestamp, and row identifier. Reads do not produce audit entries. - B2: add authorization-inheritance Requirement (ADR-005 / ADR-023). Bases writes inherit the anonymise endpoint's existing per-object authorization; no extra check is added in this change, and the absence is documented explicitly so reviewers do not mistake it for oversight. Concerns: - C1: add endpoint-shape-validation Requirement that distinguishes endpoint-layer shape check (rejects non-array / non-string elements with 400) from mapper-layer content acceptance (any string array persisted verbatim). Reconciles spec ↔ tasks.md. - C2: add retry-idempotency Requirement. Three caller intents are distinguished: field absent (reuse persisted), present-null (clear, audit-logged), present-empty-array (set to [], audit-logged). - C3: add Notes section with Woo Art. 5 references and the six canonical DocuDesk base seed slugs. Minors: - M1: apply MUST to THEN/AND assertions throughout all Scenarios. Tasks: update 3.1 to clarify two-layer shape vs content split; add 3.5 (audit-trail wiring), 3.6 (retry semantics), 3.7 (auth confirm); add corresponding 4.4–4.7 test tasks. Skipped: C4 (spec-format vs writing-specs.md) and M2 (tasks.md spec_ref / files / acceptance_criteria) — both flag repo-wide format drift that Wilco explicitly says does not block merge and needs maintainer coordination.
Blocker: - B1: tighten EmlAttachment.content contract — MUST hold decoded binary bytes (via $part->getContent(), not getRawContent()); consumers MUST NOT base64-decode again. Prevents downstream PDF/A-3 attachment corruption in DocuDesk's eml-pdf-assembly. Concerns: - C1: fix scenario notation — body accessors switched from array form result.body['plainText'] to value-object form result.body->plainText to match the typed EmlBody declaration. - C2: parseEmlStructured changed from MAY throw to MUST throw on irrecoverable malformed input — so DocuDesk's exception-driven fallback (eml-pdf-assembly → extractEml flat text) actually fires. - C3: add multipart/alternative scenario for the flat path — confirms text/plain is preferred over text/html when both are present. - C4: add no-PII-in-logs Requirement (ADR-005) with two Scenarios — parser-failure log lines and sanitised exception-message logging MUST NOT leak addresses / names / subjects / body content / attachment filenames. Minors: - M1: clarify depth-3 recursion semantics — depth is measured as the number of recursive parseEmlStructured calls from the root (root = depth 0, limit of 3 allows parses at depths 0, 1, 2, 3). - M2: add SHOULD Requirement + Scenario for non-UTF-8 body charset transcoding (mb_detect_encoding + mb_convert_encoding to UTF-8). - M3: state the missing-filename fallback format (attachment-<n>, 1-indexed) on EmlAttachment, with a new Scenario covering it. Tasks: update 3.4 (filename fallback + decoded-bytes), 3.9 (MUST throw), and add 3.10 (PII-sanitised logging) + 3.11 (explicit multipart/alternative preference). Add tests 5.6 (multipart pref), 5.7 (filename fallback), 5.8 (content encoding), 5.9 (PII log redaction), 5.10 (MUST throw assertion). Skipped: C5 (spec-format vs writing-specs.md) — repo-wide drift that Wilco explicitly says does not block merge and needs maintainer coordination.
Specs: text-extraction-eml (#1438)
…grondslagen Specs: entity-relation-grondslagen (#1435)
…nisation (#1499) Organisation.php carried two parallel sets of the seven linked-entity properties (mail / contacts / notes / todos / calendar / talk / deck) — a terse "Linked X app data" set and a fully-documented "Linked X entity IDs" set — from a merge collision between two PRs that both added the unified-Nextcloud-entity-linking feature. PHP fatal-errors at class load with "Cannot redeclare OCA\OpenRegister\Db\Organisation::$mail", so `occ app:enable openregister` (and therefore every app that depends on OR) breaks on the development branch. Removed the terse duplicate set; kept the fully-documented one. The constructor's addType() calls and jsonSerialize()'s `_*` keys reference the properties by name and are unaffected. `php -l` clean; no property name now appears twice.
…penregister.conduction.nl, brand landing) (#1505)
…ate from code CI/CD) (#1508)
# Conflicts: # docs/package-lock.json # docs/package.json
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Brings the documentation branch up to date with development so the live docs site (which deploys from documentation) reflects the latest preset/landing/tutorial work.