Repository navigation
refactor(signing): a decision is signed through filinq, and an unsigned end is shown - #3936
Open
rubenvdlinde wants to merge 6 commits into
Open
rubenvdlinde wants to merge 6 commits into
rubenvdlinde wants to merge 6 commits into
Conversation
…ed end is shown Decision 221. Dossiq raises filinq's DocumentSigningRequestedEvent through the generic Service/Signing/DocumentSigningRequester (level from signing.level, SES by default) and hears SigningConcludedEvent in SigningConcludedListener. onderteken answers 202 and the decision waits with signing.state = requested; signed moves it to signed, declined, cancelled and expired (filinq's expiry, 30 days by default) mark it not-concluded and let it be asked again. Without filinq the answer is 503 and nothing is written. The audit packet says no validation report is available. Deleted after git grep found no other caller: SigningAdapterInterface, the four LibreSign classes, MockSigningAdapter, the signing binding in BeschikkingAdapterRegistrar and three test files. beschikking schema 1.2.0 (signing), l10n, digests, app version moved. Gate 119 baseline 185 -> 179.
BeschikkingService passed phpmd's class complexity ceiling (50) with the conclusion in it. Service/Signing/SigningConclusionRecorder now records filinq's outcome on the decision; SigningConcludedListener calls it.
… under phpmd's coupling ceiling
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
October 15, 2026 07:34
…at all Decision 242: SigningConcludedListener records filinq's conclusion through BackgroundServiceAccount::runAs(), never as the signed-in signer. With no usable service account nothing is written (no _rbac false, no admin), the decision still reads signing.state requested, and an error names the decision and the signing request. Both paths tested. ZgwDocumentService::storeRaw goes: git grep finds no caller in lib/, src/ or another app (its one caller was the deleted LibreSign assembler); its storage tests use storeBase64.
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ❌ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ❌ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-debt-ratchet | ❌ | ||||
| check-types-e2e | ✅ | ||||
| composer | ✅ | ✅ 109/109 | |||
| npm | ✅ | ✅ 659/659 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ❌ 8631/8631 · 3 skipped (no test failed, the job failed for another reason — see its log) | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-15 08:04 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ❌ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-debt-ratchet | ❌ | ||||
| check-types-e2e | ✅ | ||||
| composer | ❌ | ✅ 109/109 | |||
| npm | ✅ | ✅ 659/659 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ❌ 8634/8634 · 3 skipped (no test failed, the job failed for another reason — see its log) | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-10-15 10:43 UTC
Download the full PDF report from the workflow artifacts.
This was referenced Oct 15, 2026
This branch has not been deployed
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.
What this does
Decision 221: dossiq stops talking to LibreSign and asks filinq for a signature. Filinq owns signing (its providers, LibreSign among them, its signer rails and its expiry). Decision 182: the dossiq half is named by what it does, a signing request on a document.
Service/Signing/DocumentSigningRequesterraises filinq'sDocumentSigningRequestedEventby class name (source appdossiq, the decision as subject, its file, the signer's user id, a signature level) and answers whether filinq took it, with filinq's request id. The level comes from the app config keysigning.level(SES, AdES or QES; SES when unset). Filinq refuses a level its provider does not offer, and the request then reads "not taken".BeschikkingService::ondertekenasks and returns at once:signing.state: requested, filinq's request idsigning_in_progresssigning_unavailableListener/SigningConcludedListenerhears filinq'sSigningConcludedEventfor dossiq's own requests (registered by name inCrossAppListenerRegistrar, like filinq's document event). A conclusion from filinq's expiry job writes as the background service account.signedsigned;signaturewith the level,signingRequestIdand the signed document ascompositeContent.fileIddeclined,cancelled,expiredsigning.state: not-concluded,signing.outcome= filinq's status; status unchanged; the signature can be asked againDecision 242: every conclusion is written as the background service account (
BackgroundServiceAccount::runAs()), never as the signed-in signer. With no usable service account nothing is written (no_rbac: false, no admin fallback): the decision still readssigning.state: requested, its nearest state without a write, and an error naming the decision, the signing request and filinq's status is logged so it can be reconciled. Both paths are tested inSigningConcludedListenerTest.Filinq ends every request it took, at the latest when
signing_request_expiry_days(default 30) pass (SigningExpirationJob, hourly), so a decision does not wait without end.AuditPacketBuilder:validatierapport.jsonnow saysavailable: falsewith the signing request id, because filinq publishes no validation report. Before, the mock adapter vouchedvalid: truefor a report nobody made.git grepfound no other caller:SigningAdapterInterface,LibresignApiClient,LibresignSigningAdapter,LibresignResultAssembler,LibresignStatusMapper,MockSigningAdapter, the signing binding inBeschikkingAdapterRegistrar(the archival alias stays) and three test files.ZgwDocumentService::storeRawis deleted:git grepfinds no caller inlib/,src/or another app (its one caller was the deleted LibreSign assembler); its storage tests now usestoreBase64.signingAvailable/signingHint(filinq enabled) instead oflibresignAvailable/libresignHint. Nothing undersrc/read the old keys.beschikkingschema 1.1.0 to 1.2.0:signing(state, requestId, requestedAt, concludedAt, outcome, level, tspProvider, signatory) andsignature.level,signature.signingRequestId; l10n en and nl; digests regenerated.openspec/changes/signing-through-filinq(REMOVED REQ-LBS-001 to 005, three ADDED requirements).openspec validate --strict: valid.What it fixes on the way: the old adapter polled LibreSign for a few seconds and then answered "pending" (202) and recorded nothing, so a signature placed later never reached the decision. Without LibreSign, the mock adapter wrote a made-up qualified signature onto the decision.
The R5 freeze, measured
gh pr list -R ConductionNL/dossiq --state open --limit 100gave 52 open PRs. For each, the changed files were listed (gh pr diff --name-only, and the files API where the diff was too large or empty). The only open, non-draft PR touchingBeschikkingServiceorBeschikking/*is #3726, the release PR merging development into beta, which carries development's own content. So the freeze no longer applies.Rollout, for an administrator
signingHint).occ config:app:set dossiq signing.level --value=QES(or AdES) when filinq's provider offers it (filinq's LibreSign provider offers QES only with itslibresign_qualifiedswitch on). Unset means SES.Shared files
appinfo/info.xmlversion moves to0.4.47-unstable.20261014210000; refactor(bag): the location check asks integriq, and refuses when it is on and unsure #3903 moves the same line. Whichever lands second takes a later number..procedure-code-baseline.json185 to 179 (gate 119 counts 179 on this head: six counted files went, no new counted file).l10n/*.json,tests/bootstrap.php,psalm.xml: additions only.Verified
Tests first where the behaviour is new:
BeschikkingServiceTest(22: waiting state, filinq absent, expired/declined/cancelled shown as not concluded and asked again, a stray conclusion ignored, the audit packet's report),SigningConcludedListenerTest, aCrossAppListenerRegistrarTestrow (the real stub event reaches the listener),BeschikkingControllerTest(202, 503, 409).Touched suites (every test file naming a changed class, 19 files): exit 0 (
refactor/r2/logs/sig-touched.log), and again after the last fixes (66 tests, exit 0).Stages, one at a time: lint 0, check:refusal-grounds-snapshot 0 (
sig-strict.log); phpcs 0 (sig-strict2.log); phpmd exit 2 with only the 2 inheritedTermLetters.php:401,425findings (after moving the conclusion out ofBeschikkingService, which had reached phpmd's class complexity ceiling, and naming two registrations by string); phpstan 0 and psalm 0 on f1c7754 (sig-strict3.log).phpunit --no-coverageon c3fd250 (sig-strict2.log): 8615 tests, 1 failure,Service/Money/PayoutServiceTest::testWithdrawAndRaiseAgain(two references equal, line 287); it passes alone on this branch and on refactor(bag): the location check asks integriq, and refuses when it is on and unsure #3903's, and touches nothing here. A time-based flake under load, inherited. The commits after c3fd250 touch the listener, one registrar and the settings controller; their suites pass.test:l10n,check:l10n-js,check:schema-l10n(0 uncovered), prettier on the l10n js: exit 0.openspec validate signing-through-filinq --strict: valid. Gate 119: 179, baseline 179.Merges clean into origin/development 1d3bd74 (
git merge-tree); none of its 18 new commits touches these files.Final head d81910f, stages once after the decision 242 change: phpcs 0, phpmd 2 (only the inherited
TermLetters.php:401,425), phpstan 0 (sig-strict4.log); psalm 0 andphpunit --no-coverageexit 0, 8617 tests, 82 skipped (sig-strict5.log, rerun after the WSL restart). The PayoutService flake did not recur.Not verified
PATCH /api/beschikkingen/{id}/ondertekenwith{"tspProvider":"filinq"}: 202 andsigning.state: requested; sign in filinq: the decision issigned. Set filinq'ssigning_request_expiry_dayslow and run itsSigningExpirationJob: the decision showssigning.state: not-concluded,signing.outcome: expired.