Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
452 commits
Select commit Hold shift + click to select a range
01600c5
chore(license): normalise stray AGPL-3.0 SPDX declarations to EUPL-1.2
Aug 5, 2026
e6f4db3
Merge pull request #161 from ConductionNL/chore/eupl-license-normalis…
rubenvdlinde Aug 5, 2026
ae2cb62
fix(apphost): register OpenRegister's autoloader instead of guessing …
rubenvdlinde Aug 5, 2026
7385601
ci(quality): give main/development push runs their own concurrency la…
rubenvdlinde Aug 6, 2026
72a6a59
fix(ci): compare the coverage ratchet against the measured merge base…
rubenvdlinde Aug 6, 2026
6d9980b
docs(adr): ADR-004 — Doriath stores secrets in app-local encrypted ta…
rubenvdlinde Aug 6, 2026
095dc34
chore(ci): stop pinning hydra-gates — track the package at @main (#163)
rubenvdlinde Aug 6, 2026
1c0d8c0
ci: publish an installable build of development (#169)
rubenvdlinde Aug 6, 2026
c60f2f8
fix(security): PHP_CodeSniffer 3.13.5 -> 3.13.6 (CVE-2026-67434, OS c…
rubenvdlinde Aug 6, 2026
d66bd01
fix: unbounded RSA keygen timing out the unit gate + the two Newman c…
rubenvdlinde Aug 6, 2026
50b0711
chore(deps): clear all critical + high security advisories (npm + CVE…
rubenvdlinde Aug 6, 2026
3c9f2d9
chore(deps): axe-core is a testing library — move it to devDependenci…
rubenvdlinde Aug 6, 2026
c5c62c7
fix(l10n): extract the 352 source strings the UI uses but en.json nev…
rubenvdlinde Aug 6, 2026
f8dbd32
fix(encryption-suites): gate every screen behind the master password
rjzondervan Aug 7, 2026
86b852d
ci: drop the stable31 leg — openregister cannot install there (#177)
rubenvdlinde Aug 7, 2026
4389fd1
chore: raise the Nextcloud floor to 32 (#178)
rubenvdlinde Aug 7, 2026
af83fa5
fix: restore the pre-32 Nextcloud floor — this repo tests stable31 (#…
rubenvdlinde Aug 7, 2026
48d0a3d
style(router): add missing trailing newlines to the vault-guard files
rjzondervan Aug 7, 2026
455f092
chore(coverage): ratchet baseline 55.78 -> 55.79 (measured) (#165)
rubenvdlinde Aug 7, 2026
812fc54
fix(l10n): extract the 352 t()/n() source strings missing from en.jso…
rubenvdlinde Aug 7, 2026
09fb28b
fix(l10n): wire up the parity gate that has never run, behind a no-re…
rubenvdlinde Aug 8, 2026
04d56a1
build(deps): take the 8 docs security bumps from #175 without its bro…
rubenvdlinde Aug 8, 2026
ff872c2
fix(a11y): clear five accessibility gates, and raise the NC floor to …
rubenvdlinde Aug 8, 2026
46f39cb
fix(l10n): make the parity gate refuse to pass when it measured nothi…
rubenvdlinde Aug 8, 2026
b11ee90
fix(manifest): drop the dead `example` deep link that routes nowhere …
rubenvdlinde Aug 8, 2026
4bfeab7
fix(e2e): retain-on-failure traces + a globalTimeout under the 45m CI…
rubenvdlinde Aug 8, 2026
b766af9
fix(settings): PUT /api/settings 500s — the routed update() does not …
rubenvdlinde Aug 8, 2026
da830e2
fix(settings): the master-password policy panel has never persisted a…
rubenvdlinde Aug 9, 2026
8e2e379
fix(ci): a basename-wide ignore rule, five waits that cannot settle, …
rubenvdlinde Aug 9, 2026
7579916
fix(a11y): name every unlabelled control and scope every column heade…
rubenvdlinde Aug 9, 2026
f13ad8e
fix(security): the CXP relay authorized nothing, and the admin handov…
rubenvdlinde Aug 9, 2026
9e965ef
fix(a11y): give the last three inline dialogs their own files (ADR-00…
rubenvdlinde Aug 9, 2026
da102d1
fix(spec): retarget 70 dangling @spec anchors to canonical requiremen…
rubenvdlinde Aug 9, 2026
507d0b4
test(contract): cover all 35 publicly-routed endpoints that had no wi…
rubenvdlinde Aug 9, 2026
90c1c12
test(appinfo): hold the Nextcloud floor and the tested CI matrix toge…
rubenvdlinde Aug 10, 2026
2338c82
chore(deps): pin @conduction/nextcloud-vue to 2.2.0-vue3.9 (#202)
rubenvdlinde Aug 10, 2026
a822fb4
Merge branch 'development' into fix/vault-lock-router-guard-vue3
rjzondervan Aug 10, 2026
d878888
fix(phpmd): clear all 35 architectural findings by extraction (#204)
rubenvdlinde Aug 10, 2026
df8666d
fix(gates): resolve every dangling @spec anchor and isolate the last …
rubenvdlinde Aug 10, 2026
381f504
fix(waivers): replace three false coverage waivers with the tests the…
rubenvdlinde Aug 11, 2026
50606be
fix(encryption-suites): stop compromise recovery locking the user out…
rjzondervan Aug 11, 2026
cef4ab3
docs(openspec): add the restore-suite-migration-loop change
rjzondervan Aug 11, 2026
4a8fde9
fix(waivers): cover suite revocation and the generated-key floor (#207)
rubenvdlinde Aug 11, 2026
6409d15
Merge branch 'fix/vault-lock-router-guard-vue3' into feat/restore-sui…
rjzondervan Aug 11, 2026
44d278b
fix(crypto): decode RSA chunks once so multi-byte characters survive
rjzondervan Aug 11, 2026
b0497fc
feat(encryption-suites): add the queries suite migration derives its …
rjzondervan Aug 11, 2026
94fd1a5
feat(encryption-suites): add MigrationWorkService for per-record migr…
rjzondervan Aug 11, 2026
2b2cda2
feat(encryption-suites): expose the migration work API and give a mig…
rjzondervan Aug 11, 2026
590fbaa
feat(encryption-suites): actually migrate the vault during compromise…
rjzondervan Aug 11, 2026
9f18c41
docs(openspec): record the termination and suite-resolution rules
rjzondervan Aug 11, 2026
dea0cb2
feat(encryption-suites): make the recovery dialog tell the truth and …
rjzondervan Aug 11, 2026
bfd6da6
fix(gates): cover every routed page in the suite CI runs, and repoint…
rubenvdlinde Aug 11, 2026
0ce6654
fix(ui): stop status panels falling back to light-theme tints in dark…
rjzondervan Aug 11, 2026
c19c171
fix(ui): pair semantic colours with their matching text variants for …
rjzondervan Aug 11, 2026
f5dfdfe
feat(encryption-suites): enforce the write lock beyond secret writes …
rjzondervan Aug 11, 2026
d0d17ef
feat(secrets): clear the possibly-compromised flag only on a real val…
rjzondervan Aug 11, 2026
21355dc
build(deps): phpcsstandards/phpcsutils 1.2.2 -> 1.2.3 (CVE-2026-65954…
rubenvdlinde Aug 12, 2026
ea864b8
fix(security): revoking an encryption suite never checked who owned i…
rubenvdlinde Aug 12, 2026
b1b31d0
style(secrets): add the missing //end if marker phpcs requires
rjzondervan Aug 12, 2026
a67e247
feat(secrets): warn on the row and in the detail view when a value is…
rjzondervan Aug 12, 2026
a00a908
feat(encryption-suites): add the resume banner for an interrupted rot…
rjzondervan Aug 12, 2026
00455c0
test(encryption-suites): add the compromise-recovery e2e workflow (6.5)
rjzondervan Aug 12, 2026
c4aa3be
Merge origin/development into feat/restore-suite-migration-loop
rjzondervan Aug 12, 2026
2314977
docs(secrets): line up the flag-clearing spec, code and docblock
rjzondervan Aug 12, 2026
e4741ed
test(encryption-suites): drive the recovery e2e on a fresh vault inst…
rjzondervan Aug 12, 2026
a7c2df7
fix(encryption-suites): stop the migration loop spinning when a page …
rjzondervan Aug 12, 2026
0649bcc
test(encryption-suites): close the four gaps /opsx-verify found
rjzondervan Aug 12, 2026
34f5a92
chore: adopt Nextcloud's coding standard, .editorconfig and NC 34 (#216)
rubenvdlinde Aug 12, 2026
dcb44f1
docs(openspec): sync the migration-loop deltas into the main specs
rjzondervan Aug 12, 2026
a4a2e00
chore(openspec): add plan.json for restore-suite-migration-loop
rjzondervan Aug 12, 2026
821c8ea
test(encryption-suites): escape control characters in the mismatch spec
rjzondervan Aug 12, 2026
4664322
chore(quality): adopt the shared Stylelint preset from @conduction/ne…
rubenvdlinde Aug 12, 2026
47e7134
Merge branch 'development' into feat/restore-suite-migration-loop
rjzondervan Aug 12, 2026
54a7f02
i18n(encryption-suites): translate the 36 new recovery strings into 3…
rjzondervan Aug 12, 2026
d5c4ba5
fix(encryption-suites): gate every screen behind the master password
rjzondervan Aug 7, 2026
aa99e87
style(router): add missing trailing newlines to the vault-guard files
rjzondervan Aug 7, 2026
2011438
fix(ui): pair semantic colours with their text variants for dark mode
rjzondervan Aug 12, 2026
3dea15f
fix(ci): provision the e2e vault fixture and close four Hydra gates
rjzondervan Aug 12, 2026
538b608
test(e2e): drop the last networkidle wait from the vault-unlock spec
rjzondervan Aug 12, 2026
ff6a98c
fix(ci): test the whole declared Nextcloud range, not only the ceilin…
rubenvdlinde Aug 12, 2026
717ee3e
chore: delete the inert .prettierrc (#223)
rubenvdlinde Aug 12, 2026
c82da26
chore(quality): point PHPMD at the central ruleset (#224)
rubenvdlinde Aug 12, 2026
6dce1ab
chore(quality): adopt the central PHPStan base config (#225)
rubenvdlinde Aug 12, 2026
e45f603
chore(deps): pin @conduction/nextcloud-vue to 2.2.0-vue3.16 (#226)
rubenvdlinde Aug 12, 2026
85d4c7d
chore(deps): resolve conduction/hydra-gates v1.7.3 (#227)
rubenvdlinde Aug 12, 2026
e63d5ec
feat(format): adopt Nextcloud's prettier config, so styles are tabs t…
rubenvdlinde Aug 13, 2026
fc8e004
test(link-sharing): make the no-persistence assertion able to fail
rjzondervan Aug 13, 2026
f150e0c
Merge remote-tracking branch 'origin/development' into fix/linkshare-…
rjzondervan Aug 13, 2026
b94f65e
style(link-sharing): satisfy the prettier config adopted on development
rjzondervan Aug 13, 2026
c72054e
ci: run `format` (prettier --check) as a Frontend Check leg (#230)
rubenvdlinde Aug 13, 2026
3346458
Merge branch 'development' into fix/ui-dark-mode-semantic-colours
rjzondervan Aug 13, 2026
d1c16f8
fix(ui): pair the offline banner's foreground with its warning tint
rjzondervan Aug 13, 2026
28249b4
Merge branch 'development' into fix/vault-master-password-gate
rjzondervan Aug 13, 2026
2968f6c
fix(encryption-suites): address the review on the vault gate
rjzondervan Aug 13, 2026
6cfb1c4
Merge branch 'development' into feat/restore-suite-migration-loop
rjzondervan Aug 13, 2026
5229e38
fix(encryption-suites): close the review findings on the vault gate
rjzondervan Aug 13, 2026
64462ca
fix(encryption-suites): make migration failure accounting per-record
rjzondervan Aug 13, 2026
904057c
chore(release): bump to 0.2.28 for the migration-failures table
rjzondervan Aug 13, 2026
c15e960
Merge pull request #231 from ConductionNL/fix/linkshare-storage-asser…
rjzondervan Aug 14, 2026
1e79da8
Merge pull request #221 from ConductionNL/fix/vault-master-password-gate
rjzondervan Aug 14, 2026
e4a2ce2
Merge pull request #220 from ConductionNL/fix/ui-dark-mode-semantic-c…
rjzondervan Aug 14, 2026
b0a2e1f
Merge branch 'development' into feat/restore-suite-migration-loop
rjzondervan Aug 14, 2026
fce6771
docs(openspec): recover the secret-export-gdpr and secret-import prop…
rubenvdlinde Aug 14, 2026
bc424d3
Merge pull request #233 from ConductionNL/feat/secret-export-gdpr-and…
rubenvdlinde Aug 14, 2026
f8c7e9d
Merge pull request #219 from ConductionNL/feat/restore-suite-migratio…
rubenvdlinde Aug 14, 2026
99642d0
fix(secret-requests): store the values a fill-in link submits
rjzondervan Aug 14, 2026
e06a6e8
build(lint): migrate to eslint 10 + @nextcloud/eslint-config 9
rubenvdlinde Aug 14, 2026
a442cd0
fix(security): rate-limit the three unthrottled secrets endpoints (#232)
rubenvdlinde Aug 14, 2026
de61def
docs(openspec): bring the application-secret-request change onto deve…
rjzondervan Aug 14, 2026
76e1306
feat(secret-requests): request every field a secret supports
rjzondervan Aug 14, 2026
25610ad
Merge branch 'fix/secret-request-fill-persistence' into feature/120/a…
rjzondervan Aug 14, 2026
9d74b43
ci: re-trigger the quality workflow
rubenvdlinde Aug 14, 2026
0de4d38
feat(secret-store-api): machine secret-request creation for applications
rjzondervan Aug 14, 2026
7c45a77
Merge remote-tracking branch 'origin/development' into feat/eslint-10
rubenvdlinde Aug 14, 2026
d196ee3
test(secret-store-api): cover the machine secret-request surface
rjzondervan Aug 14, 2026
bb37cd9
fix(security): rate-limit the last four public endpoints (#238)
rubenvdlinde Aug 14, 2026
bded8d9
chore: re-apply the autofix chain after merging development
rubenvdlinde Aug 14, 2026
5118813
Merge pull request #235 from ConductionNL/feat/eslint-10
rubenvdlinde Aug 14, 2026
103c2eb
ci: a branch nobody named got no checks at all (#237)
rubenvdlinde Aug 14, 2026
de11460
chore(deps): track @conduction/nextcloud-vue ^2.3.0 (#241)
rubenvdlinde Aug 15, 2026
776cf1e
chore(deps): move @conduction/nextcloud-vue to ^2.3.0 (#242)
rubenvdlinde Aug 15, 2026
688e74e
fix(build): make local-lib opt-in and validate the sibling by semver …
rubenvdlinde Aug 16, 2026
73d4489
fix(supply-chain): make the npm cooldown actually work (gate-84) (#244)
rubenvdlinde Aug 16, 2026
435a20f
ci: run every npm job on Node 24 (#245)
rubenvdlinde Aug 16, 2026
42a9eb0
fix(lint): clear all 13 tranche-A suppressions — 11 were disables for…
rubenvdlinde Aug 16, 2026
d6a6c5a
merge: development into fix/secret-request-fill-persistence
rubenvdlinde Aug 16, 2026
3e03d26
Merge pull request #236 from ConductionNL/fix/secret-request-fill-per…
rubenvdlinde Aug 16, 2026
7324a08
chore(deps): raise hydra-gates to v1.8.0 so gates 65-84 exist locally
rubenvdlinde Aug 16, 2026
15e77de
Merge pull request #249 from ConductionNL/chore/hydra-gates-1.8.0
rubenvdlinde Aug 16, 2026
4cf64ba
docs(security): waive gate-7 on four endpoints that address no object
rubenvdlinde Aug 16, 2026
0dc75cc
fix(gates): clear gate-25 and gate-26
rubenvdlinde Aug 16, 2026
13960b4
Merge pull request #251 from ConductionNL/fix/gates-green
rubenvdlinde Aug 16, 2026
7a45bda
fix(lint): sort secretRequest.js imports so lint-check can go green (…
rubenvdlinde Aug 16, 2026
3c0015d
test(e2e): the locked-vault leak assertion was flagging CnAppRoot's s…
rubenvdlinde Aug 16, 2026
07b252d
fix(test): the two view constants were self-referential
rubenvdlinde Aug 16, 2026
59b032e
Merge pull request #252 from ConductionNL/fix/gates-green
rubenvdlinde Aug 16, 2026
fa7467c
style: format the spec file my constant edit left unformatted
rubenvdlinde Aug 16, 2026
b521a2b
fix(phpmd): document the coupling SecretRequestService cannot shed
rubenvdlinde Aug 16, 2026
2675ea3
Merge pull request #253 from ConductionNL/fix/gates-green
rubenvdlinde Aug 16, 2026
392b3bb
fix(coverage-guard): scope the ratchet to the files a change touches …
rubenvdlinde Aug 17, 2026
6388891
build(deps): bump the npm_and_yarn group across 1 directory with 5 up…
dependabot[bot] Aug 17, 2026
837b31e
fix(phpcs): clear the 3 PHPCS errors in lib/Controller (#254)
rubenvdlinde Aug 17, 2026
8cef952
chore(deps): add dependabot.yml with composer cooldown (#255)
rubenvdlinde Aug 17, 2026
d9fabd7
build(deps-dev): bump squizlabs/php_codesniffer from 3.13.6 to 4.0.4
dependabot[bot] Aug 17, 2026
4634170
build(deps-dev): bump phpmetrics/phpmetrics from 2.9.1 to 2.11.0
dependabot[bot] Aug 17, 2026
1e56d00
build(deps-dev): bump phpcsstandards/phpcsextra from 1.5.0 to 1.5.1
dependabot[bot] Aug 17, 2026
dea1c2d
build(deps-dev): bump nextcloud/ocp from 34.0.2 to 34.0.3
dependabot[bot] Aug 17, 2026
7f96000
build(deps): bump ramsey/uuid from 4.9.2 to 4.9.3
dependabot[bot] Aug 17, 2026
f23589e
feat(secret-requests): signed-proof creation, guard parity and audit
rjzondervan Aug 17, 2026
f5b94b3
Merge branch 'development' into feature/120/application-secret-reques…
rjzondervan Aug 17, 2026
132a952
docs(secret-store-api): document the request surface and both DI seams
rjzondervan Aug 17, 2026
96d2702
docs(secret-store-api): waive gate-57 on the signed-proof seam
rjzondervan Aug 17, 2026
5a43714
fix(secret-requests): make the machine request surface actually work
rjzondervan Aug 17, 2026
61a83a8
chore(openspec): sync and archive application-secret-request-creation
rjzondervan Aug 17, 2026
e1c23a0
fix(core): render the anonymous public shell instead of a blank page
rjzondervan Aug 17, 2026
08bfeee
fix(secret-requests): make the create dialog produce a usable fill link
rjzondervan Aug 17, 2026
8e5b9f6
fix(secret-requests): anchor the changed dialog methods to their spec
rjzondervan Aug 17, 2026
9361c00
docs(secret-requests): spec the request-first flow the code was meant…
rjzondervan Aug 18, 2026
2c56285
Merge pull request #265 from ConductionNL/feature/120/application-sec…
rjzondervan Aug 18, 2026
a2ba5be
docs(secret-requests): spec the request indicator and the expiry life…
rjzondervan Aug 18, 2026
5c5e01c
docs(secret-requests): split the expiry lifecycle into its own change
rjzondervan Aug 18, 2026
097e809
chore(openspec): add tracking issues for both secret-request changes
rjzondervan Aug 18, 2026
65b1c98
Merge remote-tracking branch 'origin/development' into fix/public-she…
rjzondervan Aug 18, 2026
d2b16d1
fix(phpmd): justify the $allowUnfilled flag rather than redesign it (…
rubenvdlinde Aug 18, 2026
e5ec9df
Merge remote-tracking branch 'origin/development' into fix/public-she…
rjzondervan Aug 18, 2026
e649ad5
Merge branch 'openspec/request-first-secret-requests' into feature/26…
rjzondervan Aug 18, 2026
74e26ef
feat(secret-requests): let a request create its own unfilled Secret
rjzondervan Aug 18, 2026
78c09ea
feat(secret-requests): ask for a credential without owning a Secret f…
rjzondervan Aug 18, 2026
5192365
test(secret-requests): cover the request-first flow and translate it
rjzondervan Aug 18, 2026
bb78333
fix(secret-requests): stop destroying the fill link the moment it is …
rjzondervan Aug 18, 2026
c184a99
fix(secret-requests): make filling a request work, and recover its link
rjzondervan Aug 18, 2026
844d641
feat(secret-requests): tell the recipient when their browser cannot e…
rjzondervan Aug 18, 2026
74e94e2
fix(secret-requests): anchor fillLinkFor to the requirement it implem…
rjzondervan Aug 18, 2026
e6b13ac
fix(core): no donation appeal on the pages we hand to strangers
rjzondervan Aug 18, 2026
e8d3fde
docs(application-mgmt): spec admin visibility of application secret r…
rjzondervan Aug 18, 2026
4b3501a
docs(secrets-write-ui): spec owner-editable additional fields
rjzondervan Aug 18, 2026
af14355
docs(secrets-write-ui): give the spec the tracking header it never had
rjzondervan Aug 18, 2026
e57836d
chore(openspec): add tracking issues for the two changes found today
rjzondervan Aug 18, 2026
4fb9799
feat(secret-requests): make an expiry something that is set and acted on
rjzondervan Aug 18, 2026
2b6c228
test(secret-requests): cover the create endpoint and the rollback paths
rjzondervan Aug 18, 2026
48bc913
fix(secret-requests): stop a revoke from deleting a filled secret
rjzondervan Aug 18, 2026
d481eb7
chore(hooks): make the committed pre-commit hook executable
rjzondervan Aug 18, 2026
67a1770
Revert "docs(secrets-write-ui): give the spec the tracking header it …
rjzondervan Aug 18, 2026
cadc00e
Merge feature/267 into feature/268
rjzondervan Aug 18, 2026
7bf3c2b
test(secret-requests): pin the expiry path against the same data loss
rjzondervan Aug 18, 2026
dc94eba
chore(secret-requests): close out the expiry-lifecycle change
rjzondervan Aug 18, 2026
51ebe10
ci(release): converge on the shared release.yml (#274)
rubenvdlinde Aug 18, 2026
f1472b2
fix(deps): paragonie/sodium_compat v2.5.0 -> v2.5.1 (PKSA-32g2-byr9-d…
rubenvdlinde Aug 18, 2026
bce2b36
build(deps): bump phpseclib/phpseclib from 3.0.55 to 3.0.56
dependabot[bot] Aug 18, 2026
54d9e78
docs(openspec): product-page programme changes — leaf-integrations, h…
rubenvdlinde Aug 18, 2026
ebcd978
test(secret-requests): test the expiry job, which nothing tested
rjzondervan Aug 19, 2026
548091f
Merge pull request #269 from ConductionNL/fix/public-shell-anonymous-…
rjzondervan Aug 19, 2026
831b263
chore(release): 0.1.6-unstable.20260819081801 [skip ci]
github-actions[bot] Aug 19, 2026
dbb6237
fix(secret-requests): show the recipient a translated refusal, and no…
rjzondervan Aug 19, 2026
ed9d8c8
docs(secret-requests): sync the expiry-lifecycle deltas into the main…
rjzondervan Aug 19, 2026
777f65d
docs(secret-requests): archive secret-request-expiry-lifecycle
rjzondervan Aug 19, 2026
2bc7808
Merge remote-tracking branch 'origin/development' into feature/267/re…
rjzondervan Aug 19, 2026
5f0eb6b
Merge pull request #270 from ConductionNL/feature/267/request-first-s…
rjzondervan Aug 19, 2026
877935d
Added docker compose
remko48 Aug 19, 2026
2750359
feat(application-mgmt): let an administrator see and revoke an applic…
rjzondervan Aug 19, 2026
108bdf0
fix(application-mgmt): list the expiry, which the scenario required a…
rjzondervan Aug 19, 2026
48a76d4
docs(application-mgmt): sync the admin-visibility delta into the main…
rjzondervan Aug 19, 2026
521a183
fix(spec-anchors): stop pointing @spec at change dirs that archiving …
rjzondervan Aug 19, 2026
641e4b1
docs(application-mgmt): archive admin-application-request-visibility
rjzondervan Aug 19, 2026
4fcc170
docs(openspec): archive two completed changes and repair what blocked…
rjzondervan Aug 19, 2026
8620079
test(secrets-write-ui): cover the last three unclaimed scenarios in t…
rjzondervan Aug 19, 2026
6259378
Merge pull request #256 from ConductionNL/dependabot/composer/squizla…
rubenvdlinde Aug 19, 2026
78be20c
build(deps-dev): bump twig/twig from 3.27.0 to 3.28.0
dependabot[bot] Aug 19, 2026
64ae828
Merge branch 'development' into feature/271/admin-application-request…
rubenvdlinde Aug 19, 2026
0cb3600
Merge branch 'development' into feature/268/secret-request-expiry-lif…
rubenvdlinde Aug 19, 2026
99fc86d
Merge branch 'development' into release/v0.1.6-unstable.20260819081801
rubenvdlinde Aug 19, 2026
0118c81
Merge branch 'development' into dependabot/composer/ramsey/uuid-4.9.3
rubenvdlinde Aug 19, 2026
9b15e0e
Merge branch 'development' into dependabot/composer/nextcloud/ocp-34.0.3
rubenvdlinde Aug 19, 2026
f2ee1d3
Merge branch 'development' into dependabot/composer/phpseclib/phpsecl…
rubenvdlinde Aug 19, 2026
9138b07
Merge branch 'development' into dependabot/composer/phpcsstandards/ph…
rubenvdlinde Aug 19, 2026
734e0c7
Merge branch 'development' into dependabot/composer/phpmetrics/phpmet…
rubenvdlinde Aug 19, 2026
3ea1812
Merge pull request #281 from ConductionNL/release/v0.1.6-unstable.202…
rubenvdlinde Aug 19, 2026
b0e488b
Merge pull request #264 from ConductionNL/dependabot/composer/ramsey/…
rubenvdlinde Aug 19, 2026
e6b0038
Merge pull request #263 from ConductionNL/dependabot/composer/nextclo…
rubenvdlinde Aug 19, 2026
fd738fb
Merge pull request #261 from ConductionNL/dependabot/composer/phpsecl…
rubenvdlinde Aug 19, 2026
4a32567
Merge pull request #260 from ConductionNL/dependabot/composer/twig/tw…
rubenvdlinde Aug 19, 2026
44e804e
Merge pull request #258 from ConductionNL/dependabot/composer/phpcsst…
rubenvdlinde Aug 19, 2026
b5fbff6
Merge pull request #257 from ConductionNL/dependabot/composer/phpmetr…
rubenvdlinde Aug 19, 2026
9417593
chore(deps): take hydra-gates v1.8.1 — the contract v1.8.0 shipped br…
juanclaude-conduction Aug 20, 2026
6c2298b
Merge pull request #287 from ConductionNL/chore/hydra-gates-v1.8.1
rubenvdlinde Aug 20, 2026
7b44f92
fix(ci): make the three failing frontend checks pass on this branch
rjzondervan Aug 20, 2026
d6af33e
Merge remote-tracking branch 'origin/feature/268/secret-request-expir…
rjzondervan Aug 20, 2026
4b11658
Merge pull request #288 from ConductionNL/fix/development-openspec-ch…
rubenvdlinde Aug 20, 2026
ac8d861
Merge branch 'feature/268/secret-request-expiry-lifecycle' into featu…
rjzondervan Aug 20, 2026
dd3ffae
fix(ci): format and prune suppressions on this branch too
rjzondervan Aug 20, 2026
89eabf0
Merge pull request #282 from ConductionNL/feature/268/secret-request-…
rubenvdlinde Aug 20, 2026
1db114a
test(application-mgmt): cover the error paths the coverage ratchet wa…
rjzondervan Aug 20, 2026
7a15380
docs(gate-7): declare the k-anonymity range proxy exempt, with its re…
rubenvdlinde Aug 20, 2026
1844299
feat(dev): enable openregister and doriath automatically on compose s…
remko48 Aug 20, 2026
20931ad
fix(l10n): ship the frontend translation files the browser actually l…
remko48 Aug 20, 2026
de87edd
feat(l10n): translate the new lock-screen strings in all 37 locales
remko48 Aug 20, 2026
7b26a72
feat(lockscreen): exclusive fail-closed lock screen with login-style …
remko48 Aug 20, 2026
13f6f9d
chore(deps): take @conduction/nextcloud-vue 2.8.2 (was 2.3.0)
juanclaude-conduction Aug 20, 2026
061826c
Merge remote-tracking branch 'origin/development' into feature/fronte…
remko48 Aug 20, 2026
ac045c7
fix(l10n): use ellipsis character in progress labels
remko48 Aug 20, 2026
9fcd263
Merge pull request #290 from ConductionNL/fix/gate-7-breach-proxy-exe…
rubenvdlinde Aug 20, 2026
61956e8
Merge remote-tracking branch 'origin/development' into feature/fronte…
remko48 Aug 20, 2026
062a182
Merge pull request #291 from ConductionNL/chore/nc-vue-2.8.2
rubenvdlinde Aug 20, 2026
315756e
fix(quality): satisfy the PR gates after the lock-screen rework
remko48 Aug 20, 2026
6b5df34
fix(secret-requests): make expiry an atomic transition and clean up t…
rjzondervan Aug 20, 2026
1c18b31
Merge fix/expiry-cleanup-and-race into feature/271
rjzondervan Aug 20, 2026
2a976fa
fix(application-mgmt): make the admin revoke an atomic transition
rjzondervan Aug 20, 2026
34d1b56
Merge remote-tracking branch 'origin/feature/271/admin-application-re…
rjzondervan Aug 20, 2026
2945536
Merge pull request #292 from ConductionNL/feature/frontend-improvements
rubenvdlinde Aug 20, 2026
8acb487
Merge pull request #286 from ConductionNL/feature/271/admin-applicati…
rubenvdlinde Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .coverage-baseline
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
55.79
16 changes: 16 additions & 0 deletions .doriath-csp.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { chromium } from '@playwright/test'
const BASE='http://localhost:8088'
const b=await chromium.launch(); const c=await b.newContext(); const p=await c.newPage()
let csp=null
p.on('response',r=>{ if(r.url().endsWith('/apps/doriath/') || r.url().includes('/apps/doriath/#')) { const h=r.headers(); if(h['content-security-policy']) csp=h['content-security-policy'] } })
await p.goto(`${BASE}/index.php/login`,{waitUntil:'domcontentloaded'})
await p.locator('input[name="user"]').fill('admin'); await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click(); await p.waitForSelector('#header',{timeout:30000})
const resp = await p.goto(`${BASE}/index.php/apps/doriath/`,{waitUntil:'domcontentloaded'})
const h = resp.headers()['content-security-policy'] || '(none)'
console.log('CSP on the doriath SPA page:')
console.log(h)
console.log()
console.log("contains 'wasm-unsafe-eval':", h.includes('wasm-unsafe-eval'))
console.log("contains 'unsafe-eval':", /(?<!wasm-)unsafe-eval/.test(h))
await b.close()
30 changes: 30 additions & 0 deletions .doriath-detail.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { chromium } from '@playwright/test'
const BASE='http://localhost:8088'
const b=await chromium.launch(); const c=await b.newContext(); const p=await c.newPage()
const errs=[]; p.on('pageerror',e=>errs.push(String(e).slice(0,200)))
p.on('console',m=>{if(m.type()==='error')errs.push('c:'+m.text().slice(0,160))})
await p.goto(`${BASE}/index.php/login`,{waitUntil:'domcontentloaded'})
await p.locator('input[name="user"]').fill('admin'); await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click(); await p.waitForSelector('#header',{timeout:30000})
await p.goto(`${BASE}/index.php/apps/doriath/`,{waitUntil:'domcontentloaded'}); await p.waitForTimeout(3000)
await p.locator('.lock-screen input[type="password"]').first().fill('Oj',{force:true}); await p.waitForTimeout(400)
await p.evaluate(()=>{const bs=[...document.querySelectorAll('.lock-screen button')];const u=bs.find(b=>/Unlock/i.test(b.textContent||''));if(u)u.click()})
await p.waitForTimeout(4000)
await p.evaluate(()=>{const as=[...document.querySelectorAll('.app-navigation a')];const v=as.find(a=>/Vault/i.test(a.textContent||''));if(v)v.click()})
await p.waitForTimeout(3000)
errs.length=0
const rows = await p.locator('.secret-list-item, [data-testid="secret-row"]').count()
console.log('secret rows:', rows)
await p.evaluate(()=>{const r=document.querySelector('.secret-list-item');if(r)r.click()})
await p.waitForTimeout(3500)
console.log('url:',p.url())
const probe = await p.evaluate(()=>({
detail: !!document.querySelector('.secret-detail'),
pwField: document.querySelectorAll('.secret-detail .doriath-password-field').length,
pwInput: document.querySelectorAll('.secret-detail .doriath-password-field input').length,
anyInput: document.querySelectorAll('.secret-detail input').length,
detailText: (document.querySelector('.secret-detail')?.innerText||'').slice(0,200)
}))
console.log(JSON.stringify(probe,null,1))
console.log('errors:', errs.slice(0,5))
await b.close()
17 changes: 17 additions & 0 deletions .doriath-href.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { chromium } from '@playwright/test'
const BASE='http://localhost:8088'
const b=await chromium.launch(); const c=await b.newContext(); const p=await c.newPage()
await p.goto(`${BASE}/index.php/login`,{waitUntil:'domcontentloaded'})
await p.locator('input[name="user"]').fill('admin')
await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click()
await p.waitForSelector('#header',{timeout:30000})
await p.goto(`${BASE}/index.php/apps/doriath/`,{waitUntil:'domcontentloaded'})
await p.waitForTimeout(4000)
const r = await p.evaluate(() => {
const nav = document.querySelector('.app-navigation')
const as = nav ? Array.from(nav.querySelectorAll('a')) : []
return { navPresent: !!nav, hrefs: as.slice(0,10).map(a => a.getAttribute('href')), texts: as.slice(0,10).map(a=>(a.textContent||'').trim().slice(0,20)) }
})
console.log(JSON.stringify(r,null,1))
await b.close()
23 changes: 23 additions & 0 deletions .doriath-nav.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { chromium } from '@playwright/test'
const BASE='http://localhost:8088'
const b=await chromium.launch(); const c=await b.newContext(); const p=await c.newPage()
await p.goto(`${BASE}/index.php/login`,{waitUntil:'domcontentloaded'})
await p.locator('input[name="user"]').fill('admin')
await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click()
await p.waitForSelector('#header',{timeout:30000})
await p.goto(`${BASE}/index.php/apps/doriath/`,{waitUntil:'domcontentloaded'})
await p.waitForTimeout(3000)
// unlock with the seeded dev master password
await p.locator('.lock-screen input[type="password"]').first().fill('Oj',{force:true})
await p.waitForTimeout(400)
await p.evaluate(()=>{const bs=[...document.querySelectorAll('.lock-screen button')];const u=bs.find(b=>/Unlock/i.test(b.textContent||''));if(u)u.click()})
await p.waitForTimeout(4000)
console.log('after unlock, lock-screen count:', await p.locator('.lock-screen').count())
console.log('url:', p.url())
// click the Vault nav entry natively and see if the route changes
await p.evaluate(()=>{const as=[...document.querySelectorAll('.app-navigation a')];const v=as.find(a=>/Vault/i.test(a.textContent||''));if(v)v.click()})
await p.waitForTimeout(2500)
console.log('after clicking Vault -> url:', p.url())
console.log('secret-list present:', await p.locator('[data-testid="secret-list-view"], .secret-list-view').count())
await b.close()
17 changes: 17 additions & 0 deletions .doriath-neterr.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { chromium } from '@playwright/test'
const BASE = 'http://localhost:8088'
const b = await chromium.launch(); const c = await b.newContext(); const p = await c.newPage()
const bad = []
p.on('response', r => { if (r.status() >= 400) bad.push(`${r.status()} ${r.request().method()} ${r.url()}`) })
await p.goto(`${BASE}/index.php/login`, { waitUntil: 'domcontentloaded' })
await p.locator('input[name="user"]').fill('admin')
await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click()
await p.waitForSelector('#header', { timeout: 30000 })
bad.length = 0
await p.goto(`${BASE}/index.php/apps/doriath/`, { waitUntil: 'domcontentloaded' })
await p.waitForTimeout(6000)
console.log('--- failing requests on app root ---')
bad.forEach(x => console.log(x))
console.log('--- doriath-owned failures:', bad.filter(x => x.includes('/doriath')).length)
await b.close()
30 changes: 30 additions & 0 deletions .doriath-share.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { chromium } from '@playwright/test'
const BASE='http://localhost:8088'
const b=await chromium.launch(); const c=await b.newContext(); const p=await c.newPage()
const errs=[]; const reqs=[]
p.on('pageerror',e=>errs.push('PE:'+String(e).slice(0,220)))
p.on('console',m=>{if(m.type()==='error')errs.push('C:'+m.text().slice(0,220))})
p.on('response',r=>{if(r.url().includes('/doriath/'))reqs.push(`${r.status()} ${r.request().method()} ${r.url().replace(BASE,'')}`)})
await p.goto(`${BASE}/index.php/login`,{waitUntil:'domcontentloaded'})
await p.locator('input[name="user"]').fill('admin'); await p.locator('input[name="password"]').fill('admin')
await p.locator('button[type="submit"]').first().click(); await p.waitForSelector('#header',{timeout:30000})
await p.goto(`${BASE}/index.php/apps/doriath/`,{waitUntil:'domcontentloaded'}); await p.waitForTimeout(2500)
await p.locator('.lock-screen input[type="password"]').first().fill('Oj',{force:true}); await p.waitForTimeout(400)
await p.evaluate(()=>{const bs=[...document.querySelectorAll('.lock-screen button')];const u=bs.find(b=>/Unlock/i.test(b.textContent||''));if(u)u.click()})
await p.waitForTimeout(3500)
await p.evaluate(()=>{const as=[...document.querySelectorAll('.app-navigation a')];const v=as.find(a=>/Vault/i.test(a.textContent||''));if(v)v.click()})
await p.waitForTimeout(2500)
await p.evaluate(()=>{const r=document.querySelector('.secret-list-item');if(r)r.click()})
await p.waitForTimeout(2500)
await p.evaluate(()=>{const bs=[...document.querySelectorAll('.secret-detail__actions button')];const s=bs.find(b=>/Share/i.test(b.textContent||''));if(s)s.click()})
await p.waitForTimeout(2000)
console.log('share-dialog present:', await p.locator('.share-dialog').count())
const btns = await p.evaluate(()=>[...document.querySelectorAll('body button')].map(b=>(b.textContent||'').trim()).filter(Boolean).slice(0,25))
console.log('buttons:', JSON.stringify(btns))
errs.length=0; reqs.length=0
await p.evaluate(()=>{const bs=[...document.querySelectorAll('body button')];const s=bs.find(b=>/Create link/i.test(b.textContent||''));if(s)s.click(); else console.error('NO CREATE LINK BUTTON')})
await p.waitForTimeout(5000)
console.log('reveal present:', await p.locator('.share-dialog__reveal').count())
console.log('requests:', reqs)
console.log('errors:', errs.slice(0,6))
await b.close()
36 changes: 36 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# https://editorconfig.org

# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

[*.yml]
indent_size = 2
indent_style = space

[*.md]
trim_trailing_whitespace = false

[*.svg]
insert_final_newline = false

[package*.json]
indent_size = 2
indent_style = space

[build/psalm-baseline.xml]
indent_size = 2
indent_style = space

[config/*config.php]
indent_size = 2
indent_style = space
4 changes: 4 additions & 0 deletions .forgejo/workflows/pre-merge-check-strict.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
apt-get install -y --no-install-recommends \
git curl ca-certificates gnupg jq unzip zip \
libzip-dev libpng-dev python3
# Node is required by actions/checkout@v4 (a JS action) which runs
# inside this php:8.3-cli container; the stock image ships no node.
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y --no-install-recommends nodejs
docker-php-ext-install -j"$(nproc)" zip gd
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Expand Down
32 changes: 32 additions & 0 deletions .forgejo/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ jobs:
apt-get install -y --no-install-recommends \
git curl ca-certificates gnupg jq unzip zip \
libzip-dev libpng-dev python3
# Node is required by actions/checkout@v4 (a JS action) which runs
# inside this php:8.3-cli container; the stock image ships no node.
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y --no-install-recommends nodejs
docker-php-ext-install -j"$(nproc)" zip gd
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Expand Down Expand Up @@ -105,6 +109,30 @@ jobs:
- name: Assert every t() source string is in l10n/en.json
run: node tests/l10n/check-l10n.js

# ---------------------------------------------------------------------------
# HARD GATE 3 — frontend unit suite (Vitest, OFFLINE; no NC needed).
#
# Runs the pure-logic Vitest suite under tests/vitest/** (Pinia store
# state transitions, util/formatter calc, form-validation mappers, and any
# offline component mounts). These need no DOM/NC runtime — @nextcloud/* and
# @conduction/nextcloud-vue are aliased to deterministic stubs in
# vitest.config.js. Always gating.
# ---------------------------------------------------------------------------
frontend-unit:
name: Frontend unit (Vitest — ${{ inputs.app-id }})
runs-on: codeberg-medium
container:
image: node:${{ inputs.node-version }}
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4

- name: Install npm deps
run: npm ci --legacy-peer-deps || npm install --legacy-peer-deps

- name: Run Vitest unit suite
run: npm run test:unit

# ---------------------------------------------------------------------------
# COVERAGE GATE A — PHPUnit COVERAGE RATCHET (PCOV clover line coverage).
# Fails a PR that drops backend coverage below tests/.coverage-baseline.json
Expand All @@ -125,6 +153,10 @@ jobs:
apt-get install -y --no-install-recommends \
git curl ca-certificates gnupg jq unzip zip \
libzip-dev libpng-dev python3
# Node is required by actions/checkout@v4 (a JS action) which runs
# inside this php:8.3-cli container; the stock image ships no node.
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y --no-install-recommends nodejs
docker-php-ext-install -j"$(nproc)" zip gd
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Expand Down
16 changes: 16 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Revisions to skip in `git blame`.
#
# Enable locally, once:
# git config blame.ignoreRevsFile .git-blame-ignore-revs
#
# GitHub reads this file automatically. Your terminal does not, until you run
# the line above.
#
# Only ever add commits that change formatting and NOTHING else. A commit listed
# here becomes invisible to blame, so a behaviour change hidden inside one would
# be very hard to find later.

# style: reformat with nextcloud/coding-standard — whitespace only
# The fleet-wide move from a PEAR-derived PHPCS ruleset (4 spaces, next-line
# braces) to Nextcloud's own standard (tabs, same-line braces).
8f2ab30687aaf70359a4c7383765e8144232a0ba
38 changes: 38 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/sh
# Committed pre-commit hook (activated via `git config core.hooksPath .githooks`,
# which `npm install` / `composer install` set automatically — see package.json
# "prepare" and composer.json "post-install-cmd").
#
# Regenerates docs/features.json whenever staged changes touch openspec/specs/
# or the features overlay, so the commercial capability list can never go
# stale. CI (features-check / features-extract) only VERIFIES — generation
# happens here, before the commit, never in the pipeline.
#
# Best-effort by design: any failure only warns and never blocks the commit —
# the CI gate is the enforcement backstop.

if git diff --cached --name-only | grep -qE "^openspec/(specs/|features\.overlay\.json)"; then
CACHE=".git/extract-features.py"
# Fetch the canonical script (single source of truth in ConductionNL/.github);
# fall back to a previously cached copy when offline.
curl -sf --max-time 10 \
https://raw.githubusercontent.com/ConductionNL/.github/main/scripts/extract-features.py \
-o "$CACHE" 2>/dev/null || true

if [ -f "$CACHE" ]; then
if command -v python3 >/dev/null 2>&1; then PY="python3";
elif command -v py >/dev/null 2>&1; then PY="py -3";
else PY="python"; fi

if $PY "$CACHE" --app-root . >/dev/null 2>&1; then
git add docs/features.json
echo "pre-commit: docs/features.json regenerated from openspec/specs/."
else
echo "pre-commit: WARNING — could not regenerate docs/features.json (python or pyyaml missing?). CI features-check will verify." >&2
fi
else
echo "pre-commit: WARNING — could not fetch extract-features.py (offline?). CI features-check will verify." >&2
fi
fi

exit 0
19 changes: 19 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: 2

# This repo had no dependabot.yml at all — Dependabot was not configured for
# any ecosystem. Scoped narrowly here to what the fleet-wide composer
# cooldown rollout needs: a composer entry meeting the floor new gate 93
# (composer-cooldown-config) enforces. Adding npm/github-actions coverage
# for this repo is a separate decision, not folded in here.
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
cooldown:
default-days: 2
include:
- "*"
exclude:
- "conduction/*"
10 changes: 7 additions & 3 deletions .github/workflows/branch-protection.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ on:
pull_request:
branches: [main, beta]

permissions: {}

jobs:
protect:
uses: Conduction/.github/.github/workflows/branch-protection.yml@main
secrets: inherit
# Job id must stay `branch-protection` so the check reports as
# `branch-protection / check-branch`, which is the context name the org
# ruleset requires.
branch-protection:
uses: ConductionNL/.github/.github/workflows/branch-protection.yml@main
Loading
Loading