Skip to content

feat(publication): keep contacts, costs and internal judgements private when the landscape is published - #1206

Merged
rubenvdlinde merged 23 commits into
developmentfrom
feature/publication-field-rules
Oct 1, 2026
Merged

rubenvdlinde merged 23 commits into
developmentfrom
feature/publication-field-rules

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What this does

This keeps contacts, costs, service desk references and internal assessments private when OpenCatalogi publishes stackiq's landscape (opencatalogi#1708).

  • Property read rules. 52 fields of module, moduleVersion, suite, catalogService, connection, usage and organization are now readable by signed-in users only. The list is lane oc-pub's draft (oc-pub-logs/stackiq-publication-field-rules.json). usage.interneAnnotation and organization.contactpersonen keep their own rules.
  • usage is public from its publicationDate. A fragment replaces an authorization list, so the fragment repeats usage's four organisation read rules next to the new public one. The draft listed only the public rule, which would have removed every organisation's own read access.
  • A module version is public only while its application is. OpenRegister read rules only match fields of the object itself. So each version now mirrors modulePublicationDate and moduleRegisteredBy from its module:
    • ModuleVersionPublicationService keeps them in step. A listener calls it when a module or a version is saved, and it writes only when a value differs, so the event chain ends.
    • The repair step BackfillModuleVersionPublication fills them in for existing versions on upgrade.
    • The version's read rule becomes: signed in, or public under the same two conditions as its module.
  • The highest schema version wins when register fragments merge (SettingsService::keepHighestSchemaVersions). Before, the fragment with the last file name decided, so a version bump in an earlier-named fragment could be lost and its change never deployed.

OpenSpec change publication-field-rules, validates with --strict.

Stacked on #1205 (feature/sharing-itsm-exchange). Several rules cover fields that branch adds, such as serviceDesk* and installedVersion. Merge #1205 first; until then this diff includes its commits.

Verified

  • Live on :8096, after a forced register import (module 0.3.5, moduleVersion 0.1.6, usage 1.5.5 deployed). tests/live/publication-field-rules-live.sh, run in the container, ended ALL PASSED. Anonymous reads through the OpenRegister object API:
    • A published application keeps its name. dpiaDocumentRef and verwerkingsregisterRef are absent, and the admin still reads them.
    • The version of an unpublished application is not listed. It is listed once its application gets a publication date in the past.
    • A usage with a publication date in the past is listed, without timeClassification or installedVersion. A usage without one is not listed.
  • Checks:
    • composer check:strict exit 0.
    • phpunit -c phpunit-unit.xml: 981 tests. The new PublicationFieldRulesTest and ModuleVersionPublicationServiceTest pass. The 20 errors are the inherited ones below.
    • check:schema-l10n, test:l10n and check:l10n-js exit 0. No JS changed.

Not covered here

OpenRegister still returns property-ruled values through @self.relations, through @self.description (copied from longDescription), and in explicit _facets buckets. Lane or-gh is fixing that in OpenRegister. These rules are proven on the object body only.

Inherited, not fixed here

20 unit tests error outside a Nextcloud server tree because Doctrine\DBAL\ParameterType and Symfony\...\HeaderUtils are missing. They fail the same way on development.

🤖 Generated with Claude Code

contactsUid was required on organization and contactPerson. OpenRegister
creates a required property's column NOT NULL, and the app import writes
seed objects without validation, so every organisation nested in a seed
usage failed to insert and the organization table stayed empty.
contactsUid is a link the contacts sync fills in after the record exists,
so it is optional now (organization 0.5.2, contactPerson 0.0.28, register
2.5.6). The nested seed organisations also carry their type, the other
required field, and the seed usages move to 0.0.2 so an existing install
retries them.
Import creates and updates applications, relations, licences and
contracts; export sends what stackiq owns; per-field ownership in the
integriq mapping decides conflicts; disjoint field sets plus a hash per
direction keep writes from echoing; a CSV or XLSX file feeds the same
flow.
…rvice desk exchange

The fragment adds the service desk reference to usage, connection and
contract, the installed version and publication date to usage, and the
licence fields still missing to contract; a contract no longer needs a
catalogue service. Five flow templates (three imports, the export, the
file import) are filled per desk by ItsmExchangeService, checked with
OpenRegister's preflight, and only saved when all pass.
…k column

The CMDB page says what stackiq records and what it does not, shows the
exchange and takes a file import from admins. The admin section sets the
exchange up for TOPdesk or ServiceNow and shows what OpenRegister refused,
word for word. Applications in use gets a Service desk column and the
usage page a Service desk widget. English and Dutch.
…g-itsm-exchange

# Conflicts:
#	lib/Settings/softwarecatalogus_register.json
…, TOPdesk relations per application

Imports put _desk.baseUrl on the record before mapping; the export puts
the base and the TOPdesk asset template on usage and sends the mapped
object with bodyFrom. TOPdesk lists asset links one asset at a time, so
its relations flow reads them per imported application.
…low; precise live checks

OpenRegister refuses a definition change to a published flow, so a
re-run of the set-up failed. The gateway now drafts first. The live
script runs cron twice per step (queued runs) and checks that no update
sends a desk-owned field, that one change makes one call, and that an
import after an export calls nothing.
…ion; live script waits for queued export runs

phpcs and phpmd findings on the new classes: long lines, inline ifs,
named arguments, a complexity of 11 in setUp(), an error control
operator and unimported exceptions. The live script now runs cron until
no export run is queued, because the flow run worker takes them at most
once a minute.
…template id; tasks ticked after the live runs
…te when the landscape is published

Property read rules (signed-in users only) on 52 fields of module,
moduleVersion, suite, catalogService, connection, usage and organization,
from lane oc-pub's draft. usage becomes public from its publicationDate,
keeping every organisation read rule (a fragment replaces an
authorization list). A module version is public only while its
application is, through two mirrored fields kept in step by a listener
and backfilled on upgrade. The merge keeps the highest schema version
any fragment declares, so file names no longer decide it.
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ 97b348e

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
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-01 07:56 UTC

Download the full PDF report from the workflow artifacts.

…hook names its spec

Hydra gate 53 requires a _note on every custom page, and gate 16 an
@SPEC on every changed method, mounted() included.
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ 529c8bd

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
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-01 11:44 UTC

Download the full PDF report from the workflow artifacts.

…duleVersionPublication step

Hydra gate 110: a repair step added without moving <version> never runs,
because occ upgrade answers No upgrade required.
…erview widget

Hydra gate 69 does not let the custom page count grow. The page is now a
type:dashboard: four stat tiles for the lists that hold the CMDB, and
the existing CmdbOverview as a widget type registered in main.js, the
way catalog-panels is. The e2e test names the component it drives.
…rt (#1209) also declares

Two fragments declaring the same version: an instance that already
imported one never deploys the other's properties.
…ation-field-rules

# Conflicts:
#	l10n/en.js
#	l10n/en.json
#	l10n/nl.js
#	l10n/nl.json
…ation-field-rules

# Conflicts:
#	l10n/en.js
#	l10n/en.json
#	l10n/nl.js
#	l10n/nl.json
@rubenvdlinde
rubenvdlinde merged commit 3f263cb into development Oct 1, 2026
5 checks passed
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ 8f4a014

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
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-01 20:31 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/stackiq @ 248f88c

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue-demi ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
composer ✅ ✅ 130/130
npm ✅ ✅ 807/807
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
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-01 20:36 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde added a commit that referenced this pull request Oct 2, 2026
… publication field rules

With the bootstrap fixed, CI ran stackiq's unit tests for the first time in a
while and found two merged PRs disagreeing: #1209's test said usage may have no
public read rule, while #1206 gives usage a public rule conditional on
publicationDate. Owners stay private either way: contactPerson has no public
rule, the import never sets a usage's publicationDate, and usage.businessOwner,
technicalOwner and contactPerson carry authenticated-only property rules. The
test now pins exactly that, and fails if any of those person properties is made
public (control run: businessOwner set to public fails it).
rubenvdlinde added a commit that referenced this pull request Oct 2, 2026
A test stub extending OCP\EventDispatcher\Event (tests/Stubs/Event/ObjectCreatedEvent.php, added in #1197) sat inside the bootstrap's early stub glob and loaded before Nextcloud booted, so every PHPUnit leg died at tests/bootstrap.php:62 with 'Class OCP\EventDispatcher\Event not found' and no stackiq unit test ran in CI on any PR. The stub now loads after Nextcloud boots, only when the real OpenRegister event is absent. With tests running again (1071 in CI), one revealed conflict between #1209 and #1206 is resolved: the owner-privacy test now pins that contactPerson is never public, a usage is public only once published, and its person properties never are.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant