Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
160 commits
Select commit Hold shift + click to select a range
a05919d
Apply bootstrap-openbuilt — core implementation (sections 1–3) (#2)
rubenvdlinde May 12, 2026
2515e7b
spec: openbuilt-versioning — draft/publish/rollback + manifest snapshots
rubenvdlinde May 11, 2026
a8ebd45
Apply openbuilt-versioning — backend (schema, listener, diff endpoint…
rubenvdlinde May 11, 2026
66ea58e
Apply openbuilt-versioning — frontend SFCs + review fixes
rubenvdlinde May 11, 2026
3e244d8
test(openbuilt-versioning): PHPUnit listener + diff controller + seed…
rubenvdlinde May 11, 2026
8c5af5b
test(openbuilt-versioning): integration publish→rollback + Vitest set…
rubenvdlinde May 11, 2026
217128b
test(openbuilt-versioning): Playwright version-rollback + Newman publ…
rubenvdlinde May 11, 2026
e5a4ff8
fix(ci): regenerate lockfile + stylelint auto-fixes
rubenvdlinde May 11, 2026
d59c43d
fix(quality): register ObjectTransitionedEvent in psalm UndefinedClas…
rubenvdlinde May 12, 2026
83f7862
Merge pull request #5 from ConductionNL/feature/spec-openbuilt-versio…
rubenvdlinde May 12, 2026
a113bd5
spec(openbuilt-rbac): add per-virtual-app RBAC change artifacts
rubenvdlinde May 11, 2026
ad1078d
Apply openbuilt-rbac change — controller enforcement, frontend gating…
rubenvdlinde May 11, 2026
efd59eb
fix(rbac): close list-endpoint IDOR + audit admin bypass to OR trail
rubenvdlinde May 11, 2026
c17ac34
fix(rbac): document <permission> navigation gate gap, link upstream N…
rubenvdlinde May 11, 2026
d847290
refactor(i18n): flip openbuilt.rbac.* dotted keys to plain English
rubenvdlinde May 11, 2026
3f259fd
fix(quality): clean up PHPCS errors + phpmd thresholds + psalm OR stubs
rubenvdlinde May 11, 2026
fd6e996
test(rbac): add Newman collection covering REQ-OBRBAC-002/003/005
rubenvdlinde May 11, 2026
fdfae30
test(rbac): add Playwright e2e — non-member blackout (REQ-OBRBAC-002/…
rubenvdlinde May 11, 2026
5715c1c
test(rbac): add Vitest — useRole (19) + PermissionsModal (8) = 27 tests
rubenvdlinde May 11, 2026
be76c74
fix(ci): regenerate lockfile + stylelint auto-fixes
rubenvdlinde May 11, 2026
3921843
fix(quality): raise ExcessiveClassComplexity threshold for the integr…
rubenvdlinde May 12, 2026
713c581
Merge pull request #6 from ConductionNL/feature/spec-openbuilt-rbac
rubenvdlinde May 12, 2026
e64bfb4
spec(openbuilt-schema-editor): visual schema designer for citizen dev…
rubenvdlinde May 11, 2026
4bc8e9f
Apply schema-editor source — store-based, hybrid register model
rubenvdlinde May 11, 2026
dabd032
test(schema-editor): set up Vitest + add SchemaListPanel + FieldEdito…
rubenvdlinde May 11, 2026
804eae6
test(schema-editor): add LifecycleEditor + SchemaDesigner unit specs
rubenvdlinde May 11, 2026
a07b4cb
test(schema-editor): add Newman + Playwright e2e + lint pass
rubenvdlinde May 11, 2026
58e6c1b
fix(ci): regenerate lockfile + stylelint auto-fixes
rubenvdlinde May 11, 2026
ebc8ffd
Merge pull request #3 from ConductionNL/feature/spec-openbuilt-schema…
rubenvdlinde May 12, 2026
54e93c2
spec(openbuilt-export-to-real-app): Phase-2 export pipeline
rubenvdlinde May 11, 2026
3267bca
feat(openbuilt-export-to-real-app): salvage Phase-2 export pipeline (…
rubenvdlinde May 11, 2026
e540d3a
fix(export): pascalCase camelCase boundaries + drop invalid ISimpleFo…
rubenvdlinde May 11, 2026
b1e26ee
fix(export): drive ExportJob lifecycle via OR TransitionEngine (CRITI…
rubenvdlinde May 11, 2026
27807c7
fix(export): close IDOR + add route-auth on ExportsController (CRITICAL)
rubenvdlinde May 11, 2026
b288afb
fix(export): make exported app a Tier-4 manifest consumer (ADR-024)
rubenvdlinde May 11, 2026
f77ad5e
fix(export): clean up PHPCS/PHPMD — named params, complexity split, e…
rubenvdlinde May 11, 2026
0369f21
fix(tests): make bootstrap work outside the docker container
rubenvdlinde May 11, 2026
0abbd2d
fix(export): drop unused container dep + green PHPStan
rubenvdlinde May 11, 2026
2943aab
test(exporter): cover PAT-handling contract for ExportJob + GitHub se…
rubenvdlinde May 11, 2026
9b74035
test(exporter): cover RunExportJob lifecycle + PAT-clear contract
rubenvdlinde May 11, 2026
ea34cc0
test(exporter): cover ExportsController submit/download HTTP surface
rubenvdlinde May 11, 2026
531f489
test(exporter): add Newman collection for export pipeline
rubenvdlinde May 11, 2026
7ad9d80
test(exporter): add Playwright e2e for ZIP export download
rubenvdlinde May 11, 2026
f026306
fix(ci): regenerate lockfile + stylelint and lint auto-fixes
rubenvdlinde May 11, 2026
9d2250a
Merge pull request #7 from ConductionNL/feature/spec-openbuilt-export…
rubenvdlinde May 12, 2026
5e9ffa4
build: fix frontend build (axios pin + SCSS + nc-vue beta.31) (#15)
rubenvdlinde May 12, 2026
c279bd1
fix: mount the app independently of translation loading (#16)
rubenvdlinde May 12, 2026
7aa2a1e
feat(listener): upsert the BuiltAppRoute on Application publish (#18)
rubenvdlinde May 12, 2026
6d7ebdb
feat: convert OpenBuilt's own shell to a manifest-driven Tier-4 app (…
rubenvdlinde May 12, 2026
3a071f2
chore(openspec): archive the 5 merged chain changes (#21)
rubenvdlinde May 12, 2026
20238ae
feat: re-apply openbuilt-templates-marketplace onto the Tier-4 shell …
rubenvdlinde May 12, 2026
c97f964
feat: re-apply openbuilt-page-editor onto the Tier-4 shell (closes #4…
rubenvdlinde May 12, 2026
b5df1e1
chore(openspec): archive openbuilt-templates-marketplace + openbuilt-…
rubenvdlinde May 12, 2026
853f70d
feat: adopt the Features & Roadmap menu (#25)
rubenvdlinde May 12, 2026
35f4046
feat: wire PageDesigner's manifest load/save (closes #26) (#27)
rubenvdlinde May 12, 2026
6b3c2ef
fix(ci): mock real OpenRegister classes in PHPUnit, sqlite for integr…
rubenvdlinde May 12, 2026
6591806
feat(mcp-tools): OpenBuiltToolProvider — AI companion MCP tools (MVP …
rubenvdlinde May 12, 2026
9b30df5
fix: white fill on app.svg so the navigation header icon renders corr…
rubenvdlinde May 12, 2026
88b0f5c
ci: install OpenRegister `development` (runtime-schema-API + lifecycl…
rubenvdlinde May 12, 2026
5b9de69
feat(dashboard): proper type:"dashboard" manifest page with OR-backed…
rubenvdlinde May 12, 2026
7f3fe95
test(seed): assert the hello-world manifest blob is structurally vali…
rubenvdlinde May 12, 2026
9b9168a
feat(page-editor): v1.1 — structured Logs/Settings/Chat/Files/Custom …
rubenvdlinde May 12, 2026
057b5de
docs(journeydoc): bootstrap capture-driven user documentation
rubenvdlinde May 12, 2026
6584ff5
feat(virtual-apps): CnIndexPage (custom cards, card-grid default) + C…
rubenvdlinde May 12, 2026
4da1dc9
test(virtual-apps): ApplicationCard spec + lint fixes; drop NcAppCont…
rubenvdlinde May 12, 2026
1e3578b
chore: remove orphaned src/views/settings/UserSettings.vue
rubenvdlinde May 12, 2026
7b8f34c
Merge branch 'feature/virtual-apps-index-detail-v2' into development
rubenvdlinde May 12, 2026
9d1d46d
Merge branch 'feat/manifest-nc-vue-beta38' (remove orphaned UserSetti…
rubenvdlinde May 12, 2026
f2da4ff
Merge branch 'feature/journeydoc-init' into development
rubenvdlinde May 12, 2026
c9b1716
chore(deps): bump @conduction/nextcloud-vue to ^1.0.0-beta.40
rubenvdlinde May 12, 2026
0a69645
Merge pull request #41 from ConductionNL/chore/bump-nc-vue-beta40
rubenvdlinde May 12, 2026
6a593d0
chore(docs): bump @conduction/docusaurus-preset to 1.5.1 in lockfile …
rubenvdlinde May 12, 2026
f858cf6
fix(docs): MDX-safe TODO placeholders in journeydoc tutorial skeleton…
rubenvdlinde May 12, 2026
81b2444
chore(docs): bump @conduction/docusaurus-preset to 2.6.1 (#45)
rubenvdlinde May 12, 2026
7e0dbbe
ci(newman): seed the OpenBuilt registers + hello-world app before the…
rubenvdlinde May 13, 2026
d8d32d2
Merge origin/development
rubenvdlinde May 13, 2026
717fc59
ci: keep PHPUnit (green); disable Newman until SeedHelloWorld's OR ru…
rubenvdlinde May 13, 2026
ca3c3e1
docs: fill journeydoc tutorials (content + capture spec + screenshots…
rubenvdlinde May 13, 2026
c8bf155
fix: detail-page routing + Newman collections (#33) (#48)
rubenvdlinde May 13, 2026
71e6d50
fix(rbac): namespace user-UID vs group-GID principals in permissions …
rubenvdlinde May 13, 2026
86af75c
fix(scaffold): ConfigurationService::importFromApp 4-arg signature in…
rubenvdlinde May 13, 2026
048566d
ci(docs): revert deploy source to documentation branch (docs CI separ…
rubenvdlinde May 13, 2026
c552362
refactor(versioning): split Application + ApplicationVersion (ADR-002)
rubenvdlinde May 15, 2026
ea90550
feat(versioning): ApplicationVersionService + controller + production…
rubenvdlinde May 15, 2026
0a9553c
feat(versioning): green-field migration + retire SeedHelloWorld
rubenvdlinde May 15, 2026
1750dad
docs(openspec): land ADR-002 + openbuilt-versioning-model change
rubenvdlinde May 15, 2026
0ec9cda
feat(schema): add top-level icon + iconDark properties to Application…
rubenvdlinde May 15, 2026
d8abca8
feat(icons): add IconService + IconController with fallback chain
rubenvdlinde May 15, 2026
34c551b
feat(nav): add AppNavigationService and wire navigation in Applicatio…
rubenvdlinde May 15, 2026
e2e918f
feat(ui): add icon display, upload section, and icon tab to Applicati…
rubenvdlinde May 15, 2026
f6db486
test(icons): add PHPUnit tests for IconService, IconController, AppNa…
rubenvdlinde May 15, 2026
5c5b388
fix(quality): resolve all 3 pre-existing Hydra gate failures (gate-1/…
rubenvdlinde May 15, 2026
cb77429
docs(openspec): land openbuilt-nextcloud-nav change spec with apply-n…
rubenvdlinde May 15, 2026
b5457e0
feat(openbuilt): version-promotion endpoint + dialog (spec D)
rubenvdlinde May 15, 2026
70bca0c
feat(version-routing): add ManifestResolverService + wire ?_version= …
rubenvdlinde May 15, 2026
02620db
feat(version-routing): add useApplicationVersion composable, router h…
rubenvdlinde May 15, 2026
6c721fe
test(version-routing): add PHPUnit + Vitest coverage for ManifestReso…
rubenvdlinde May 15, 2026
50a9ebf
fix(quality): resolve pre-existing PHPMD + ESLint violations encounte…
rubenvdlinde May 15, 2026
106751f
fix(card): remove regression-re-added Live badge (spec A's locked dec…
rubenvdlinde May 15, 2026
bb801ed
chore(test): add newman devDependency + test:newman/test:e2e:ui scripts
rubenvdlinde May 15, 2026
fac79e4
test(integration): Newman collections for specs C, D, A (task 4.9 / 7…
rubenvdlinde May 15, 2026
e5ed1f1
test(e2e): Playwright specs for specs A, D, E (tasks 7.4, 7.5, 5.1, 9…
rubenvdlinde May 15, 2026
be59a61
fix(card): read version/status from productionVersion + spec D unit t…
rubenvdlinde May 15, 2026
54e0e7e
feat(wizard): server-side endpoint + service + slug validator (spec F)
rubenvdlinde May 16, 2026
8135b65
feat(wizard): four-step creation dialog with auto-derive slugs (spec F)
rubenvdlinde May 16, 2026
666229f
feat(wizard): wire to Virtual apps index Add button (spec F)
rubenvdlinde May 16, 2026
165ea23
test(wizard): PHPUnit, Vitest, Newman, Playwright (spec F)
rubenvdlinde May 16, 2026
df6be7d
docs(openspec): land openbuilt-app-creation-wizard change with apply-…
rubenvdlinde May 16, 2026
e27c723
feat(insights): add ApplicationInsightsService + controller + route (…
rubenvdlinde May 16, 2026
af54b81
feat(detail): maintainer dashboard header + structural widgets (REQ-O…
rubenvdlinde May 16, 2026
a6b2ca1
test(detail-overview): PHPUnit + Vitest + Newman + Playwright for spec B
rubenvdlinde May 16, 2026
4dfc2a7
docs(openspec): land openbuilt-app-detail-overview change with apply-…
rubenvdlinde May 16, 2026
9c27176
fix(insights): PHPCS NamedParameters — pass named args to OR mapper c…
rubenvdlinde May 16, 2026
56f4585
fix(tests): stabilise 11 PHPUnit failures across F/E + pre-existing C…
rubenvdlinde May 16, 2026
cf95562
fix(listener): use getNewObject() on ObjectUpdatingEvent (real OR API)
rubenvdlinde May 16, 2026
ee1fd14
Merge pull request #58 from ConductionNL/feature/openbuilt-versioning…
rubenvdlinde May 16, 2026
22ccbb2
Merge pull request #59 from ConductionNL/feature/openbuilt-nextcloud-nav
rubenvdlinde May 16, 2026
bb3eb18
Merge pull request #60 from ConductionNL/feature/openbuilt-version-pr…
rubenvdlinde May 16, 2026
2493bee
Merge pull request #61 from ConductionNL/feature/openbuilt-version-ro…
rubenvdlinde May 16, 2026
33dd108
Merge pull request #62 from ConductionNL/feature/openbuilt-test-harness
rubenvdlinde May 16, 2026
ba26c9e
Merge pull request #63 from ConductionNL/feature/openbuilt-app-creati…
rubenvdlinde May 16, 2026
7937531
Merge pull request #64 from ConductionNL/feature/openbuilt-app-detail…
rubenvdlinde May 16, 2026
3488463
Merge pull request #65 from ConductionNL/fix/openbuilt-phpunit-stabil…
rubenvdlinde May 16, 2026
12986ee
fix(wizard): mount custom Add action + inline footer nav + namespaced…
rubenvdlinde May 16, 2026
55aae78
fix(wizard): send full payload on chain-wiring + productionVersion-se…
rubenvdlinde May 16, 2026
82dc21c
fix(detail): header fetches Application via OR API on mount
rubenvdlinde May 16, 2026
9fc9317
docs(tutorials): add 'Update a virtual app' tutorial with verified sc…
rubenvdlinde May 16, 2026
8ff0dab
Merge pull request #70 from ConductionNL/fix/openbuilt-wizard-and-dat…
rubenvdlinde May 16, 2026
f5a806c
fix(versions): render all version pills + filter schemas by tier (#74)
rubenvdlinde May 16, 2026
3702d85
fix(templates): scope owner filter under @self in slug-collision look…
rubenvdlinde May 16, 2026
ce64707
fix(#75): namespace manifest config.schema + test backfill + Playwrig…
rubenvdlinde May 16, 2026
cb6b01c
Playwright + bootstrap verification + page-editor v1.1 tests (closes …
rubenvdlinde May 17, 2026
71df7dd
chore(security): require 24h cooldown on npm packages (#80)
rubenvdlinde May 17, 2026
44c9ccb
fix(seed): migrate x-openregister-lifecycle to map-keyed transitions …
rubenvdlinde May 17, 2026
a7f04b8
feat(openspec): finish nextcloud-nav + drive 5 specs to 86% complete …
rubenvdlinde May 17, 2026
9d003f4
feat(specs): finish all 6 OpenSpec changes — ZERO active changes remain
rubenvdlinde May 17, 2026
fb60212
test(e2e): chat-companion streaming Playwright spec (#84)
rubenvdlinde May 18, 2026
b356be7
feat(docs): wire AI-crawler baseline (preset 3.4.0 + validator + llms…
rubenvdlinde May 18, 2026
fb13851
feat(docs): per-app OG card + accurate llms.txt links (#86)
rubenvdlinde May 18, 2026
81d865e
chore(docs): use validator bin from preset 3.5.0 (#87)
rubenvdlinde May 18, 2026
6a7b2c6
chore(docs): bump preset to ^3.6.0 + sync lockfile (#88)
rubenvdlinde May 18, 2026
7ee1b7d
chore(deps): upgrade preset lockfile to 3.6.1 (unbreaks deploy) (#90)
rubenvdlinde May 18, 2026
68eb81c
chore(deps): preset lockfile 3.6.1 -> 3.6.2 (validator patch) (#92)
rubenvdlinde May 18, 2026
8b22693
chore(deps): preset lockfile 3.6.2 -> 3.7.0 (sitemap lastmod auto-app…
rubenvdlinde May 19, 2026
a844ac6
fix(ci): dependabot should target development per branching strategy …
rubenvdlinde May 19, 2026
a5d17b2
chore(deps): preset lockfile 3.7.0 -> 3.7.1 (relaxed lastmod threshol…
rubenvdlinde May 19, 2026
5a9dc8e
chore(brand): align app-store hex to canonical cobalt #21468B (#56)
rubenvdlinde May 19, 2026
56a8793
chore(deps): preset lockfile 3.7.1 -> 3.8.0 (BreadcrumbList + TechArt…
rubenvdlinde May 19, 2026
e643d3f
chore(deps): preset lockfile 3.8.0 -> 3.9.0 (TechArticle gate) (#102)
rubenvdlinde May 19, 2026
585e014
fix(docs): descriptive homepage title (closes ConductionNL/.github#80)
rubenvdlinde May 19, 2026
cd7ba07
Merge pull request #104 from ConductionNL/seo/title-fix-80
rubenvdlinde May 19, 2026
a0da51b
fix(docs): hand-written meta descriptions on homepage + intro (#81)
rubenvdlinde May 19, 2026
c4a5b4e
Merge pull request #106 from ConductionNL/seo/meta-descriptions-81
rubenvdlinde May 19, 2026
857e2b9
chore(docs): bump @conduction/docusaurus-preset to 3.10.0 (#79)
rubenvdlinde May 19, 2026
4b6a0d5
Merge pull request #108 from ConductionNL/chore/preset-3.10.0
rubenvdlinde May 19, 2026
40e6c48
feat(manifest-v2): migrate to universal widget manifest (#110)
rubenvdlinde May 19, 2026
416f8f2
fix(quality): apply eslint --fix + peer-dep tree with nc-vue 1.x (#111)
rubenvdlinde May 19, 2026
9a2bed5
feat(manifest-v2): TemplateGallery→index, designers→detail, FeaturesR…
rubenvdlinde May 20, 2026
e260a33
chore(spec): merge openbuilt-exporter [auto] (#121)
rubenvdlinde May 20, 2026
9eff930
chore(spec): merge openbuilt-page-designer [auto] (#122)
rubenvdlinde May 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
  •  
  •  
  •  
223 changes: 223 additions & 0 deletions .claude/openspec/architecture/adr-001-data-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
- ALL domain data → OpenRegister objects. NO custom Entity/Mapper for domain data.
- App config → `IAppConfig`. NOT OpenRegister.
- Cross-entity references: OpenRegister relations (register+schema+objectId). NO foreign keys.
MUST NOT store foreign keys or embed full objects.

### Schema standards

- Schemas: PascalCase, schema.org vocabulary, explicit types + required flags + description field.
- MUST NOT invent custom property names when a schema.org equivalent exists.
- Contact schemas MUST align with vCard properties (fn, email, tel, adr).
- Dutch government fields SHOULD use a mapping layer translating between international standards
and Dutch specs — do not hardcode Dutch field names as primary.
- Schema changes that remove or rename properties are BREAKING. Adding optional properties is non-breaking.

### Register templates

- Location: `lib/Settings/{app}_register.json` (OpenAPI 3.0 + `x-openregister` extensions).
- Three template categories:
- **App configuration** — define data models (schemas/registers/views/mappings).
Mark with `x-openregister.type: "application"`.
- **Mock data** — fictional but realistic seed data for dev/test.
Mark with `x-openregister.type: "mock"`.
- **Government standards** — aligned to Dutch API specs (BAG, BRP, KVK, DSO).
- Import mechanism: `ConfigurationService::importFromApp(appId, data, version, force)` →
`ImportHandler::importFromApp()`. Called from repair step or `SettingsLoadService`.
- Idempotency: re-importing with `force: false` MUST NOT create duplicates. Match by slug
using `ObjectService::searchObjects` with `_rbac: false` and `_multitenancy: false`.
Use `version_compare` for skip logic.

### Seed data

Apps that store data in OpenRegister are empty on first install. An empty app cannot be
meaningfully tested — there are no objects to view, search, filter, or interact with.
This blocks both automated browser testing and manual QA. The Loadable Register Template
pattern (see Register templates above) already supports seed data via `components.objects[]`
with the `@self` envelope.

**Requirements:**

- Every app using OpenRegister MUST include 3-5 realistic objects per schema in
`lib/Settings/{app}_register.json`.
- Use `@self` envelope: `{ "@self": { "register": ..., "schema": ..., "slug": ... }, ...properties }`.
Register/schema MUST match keys; slug is unique human-readable identifier for matching.
- Use general organisation data (municipality, consultancy, travel agency, non-profit) —
NOT context-specific. Varied, realistic field values.
- Mock data quality: real Dutch street names, valid postcodes (`[1-9][0-9]{3}[A-Z]{2}`),
correct municipality/KVK codes, BSNs that pass 11-proef. Fictional but distinguishable from real.
- Cross-register consistency: BRP→BAG, KVK→BAG, DSO→BAG references must be valid.
- Loaded on install alongside schemas via same `importFromApp()` pipeline.
- MUST be idempotent — re-importing skips existing objects matched by slug.

**In OpenSpec artifacts:**

- **In design.md**: MUST include a Seed Data section when change introduces/modifies schemas —
define seed objects per schema with concrete field values and related items (files, notes, tasks, contacts).
- **In tasks.md**: MUST include a seed data generation task when change introduces/modifies schemas.

**Exceptions** (no seed data required):

- **nldesign** — has no OpenRegister schemas.
- **ExApp sidecar wrappers** (openklant, opentalk, openzaak, valtimo, n8n-nextcloud) — proxy
external services and do not use OpenRegister.
- **nextcloud-vue** — shared library, no seed data applicable.
- Changes that only modify frontend components or non-schema backend logic (e.g., settings,
permissions) do not require seed data.

**Limitations:** OpenRegister's `ImportHandler` currently supports only flat seed objects.
Related items (files, notes, tasks, contacts) linked through the relation system are tracked
in OpenRegister's pending `seed-related-items` openspec change (see
`openregister/openspec/changes/seed-related-items/`). Until that lands, seed data is limited
to object properties defined in schemas.

### Deduplication check

- Before proposing new capability: search `openspec/specs/` and `openregister/lib/Service/` for overlap
with ObjectService, RegisterService, SchemaService, ConfigurationService, and shared Vue components.
- If similar capability exists: MUST reference it and explain why new code is needed rather than extending.
- Proposals duplicating existing functionality without justification MUST be rejected.
- **In design.md**: MUST include a "Reuse Analysis" section listing existing OpenRegister services leveraged.
- **In tasks.md**: MUST include a "Deduplication Check" task verifying no overlap — document findings
even if "no overlap found".

### Schema migrations

- Breaking schema changes → new migration in repair step. NEVER modify existing migrations.

### OpenRegister + @conduction/nextcloud-vue — DO NOT REBUILD

The platform provides 258+ backend methods and 69+ frontend components. Apps ONLY build
custom logic for domain-specific business rules. Everything below is provided for FREE.

**CRUD & Data Management** (use ObjectService + CnIndexPage + CnDetailPage):
- Single & bulk create, read, update, delete — `ObjectService.saveObject()`, `deleteObject()`
- List with pagination, sorting, filtering — `ObjectService.findAll()` + `CnDataTable`
- Schema-driven forms — `CnFormDialog` (auto-generates from schema) or `CnAdvancedFormDialog`
- Detail views — `CnDetailPage` with `CnDetailGrid`, `CnDetailCard` sections
- Record merging/deduplication — `ObjectService.mergeObjects()`
- Object locking — `ObjectService.lockObject()` / `unlockObject()`

**Import & Export** (use ImportService/ExportService + CnMassImportDialog/CnMassExportDialog):
- CSV, Excel, JSON import with intelligent field mapping — `ImportService`
- CSV, Excel, JSON export with column selection — `ExportService`
- Bulk import with validation and progress — `CnMassImportDialog`
- Filtered export with format picker — `CnMassExportDialog`
- NO custom import dialogs, parsers, upload handlers, or export controllers

**Search & Discovery** (use IndexService + CnFilterBar + CnFacetSidebar):
- Full-text search with field weighting — `IndexService`
- Faceted navigation with counts — `FacetBuilder` + `CnFacetSidebar`
- Semantic search with embeddings — `VectorizationService`
- Hybrid search (keyword + semantic) — automatic
- Search analytics — `SearchTrailService` (popular terms, activity)
- NO custom search endpoints, query builders, or search pages

**File Management** (use FileService + CnObjectSidebar):
- Upload (single/multipart), download, share links — `FileService`
- File tagging, public/private toggle — `FileService`
- Bulk download as ZIP — `createObjectFilesZip()`
- Text extraction from PDFs/Office docs — `TextExtractionService`
- File tab in object sidebar — `CnObjectSidebar` → `CnFilesTab`
- NO custom file upload components, file controllers, or download handlers

**Audit & Compliance** (use AuditTrailService + CnObjectSidebar):
- Full change tracking with before/after snapshots — automatic
- Audit trail tab — `CnObjectSidebar` → `CnAuditTrailTab`
- GDPR data subject access requests — `inzageverzoek()`, `verwerkingsregister()`
- Audit export and analytics — `AuditTrailController`
- NO custom audit logging, change tracking, or compliance controllers

**Dashboard & Analytics** (use CnDashboardPage + CnChartWidget + CnStatsBlock):
- Drag-drop widget dashboard — `CnDashboardPage` with GridStack
- KPI cards — `CnKpiGrid`, `CnStatsBlock`, `CnStatsPanel`
- Charts (line/bar/pie/donut) — `CnChartWidget` (ApexCharts)
- Data tables as widgets — `CnTableWidget`
- Editable data grids — `CnObjectDataWidget`
- NO custom dashboard layouts, chart components, or KPI cards

**Forms & Dialogs** (use CnFormDialog + schema-driven generation):
- Auto-generated create/edit forms — `CnFormDialog` reads schema → generates fields
- JSON/metadata editing — `CnAdvancedFormDialog` with Properties/Data/Metadata tabs
- Schema editor — `CnSchemaFormDialog`
- Delete/Copy/Mass operations — `CnDeleteDialog`, `CnCopyDialog`, `CnMassDeleteDialog`
- NO custom form components, validation logic, or dialog wrappers

**Navigation & Pagination** (use CnPagination + CnActionsBar + useListView):
- Pagination control with size selector — `CnPagination`
- Action bar (add, search, toggle views) — `CnActionsBar`
- List state management — `useListView` composable (handles search, filter, sort, page)
- Detail state management — `useDetailView` composable
- NO custom pagination logic, debounced search, or list state management

**Authorization & RBAC** (use AuthorizationService + PropertyRbacHandler):
- Role-based access control — `AuthorizationService`
- Field-level permissions — `PropertyRbacHandler`
- Object-level restrictions — `PermissionHandler`
- Authorization audit — `AuthorizationAuditService`
- NO custom permission checks, role systems, or access control middleware

**Webhooks & Events** (use WebhookService):
- Create, test, retry webhooks — `WebhookService`
- CloudEvents format — automatic
- Event subscriptions — selective per schema/action
- NO custom webhook controllers or event dispatchers

**Notifications & Activity** (use NotificationService + ActivityService):
- Nextcloud notifications — `NotificationService`
- Activity feed — `ActivityService`
- Calendar events — `CalendarEventService`
- Deck/Kanban cards — `DeckCardService`

**Store & State** (use createObjectStore + plugins):
- Object stores — `createObjectStore(name)` generates Pinia CRUD store
- Store plugins: `auditTrails`, `files`, `lifecycle`, `relations`, `search`, `selection`
- Column/field/filter generation from schema — `columnsFromSchema()`, `fieldsFromSchema()`
- NO custom Pinia stores for CRUD, Vuex, or manual API call management

**Chat & AI** (use ChatService):
- Multi-turn conversation — `ChatService`
- RAG-based knowledge retrieval — `ContextRetrievalHandler`
- LLM response generation — `ResponseGenerationHandler`

**Data Retention & Archival** (use ArchivalService):
- Legal hold — `LegalHoldService`
- Destruction schedules — `DestructionService`
- Retention policies — `RetentionService`

**Semantic & Hybrid Search** (use SolrController + SettingsController):
- Semantic search via vector embeddings — `SettingsController.semanticSearch()`
- Hybrid search (keyword + semantic combined) — `SolrController.hybridSearch()`
- Vector embedding generation — `VectorizationService`
- NO custom search algorithms — configure via OpenRegister settings

**GraphQL API** (use GraphQLController):
- Query objects across schemas via GraphQL — `GraphQLController.execute()`
- Alternative to REST for complex cross-entity queries

**Organization / Multi-Tenancy** (use OrganisationController):
- Organization CRUD — `OrganisationController`
- Tenant-scoped data isolation — automatic via `TenantLifecycleService`
- NO custom multi-tenancy logic

**Task & Workflow Management** (use TasksController + WorkflowEngineController):
- Task creation and tracking — `TasksController`
- Workflow orchestration — `WorkflowEngineRegistry`
- Scheduled workflows — `ScheduledWorkflowController`
- NO custom task/workflow systems

**Text Extraction** (use FileTextController):
- Extract text from PDFs and Office docs — `TextExtractionService`
- Entity recognition (PII detection) — `EntityRecognitionHandler`
- Content anonymization — automatic

**Timeline & Stages** (use CnTimelineStages):
- Workflow progression visualization — `CnTimelineStages` component
- Stage tracking with status colors

### What apps SHOULD build (custom business logic only):
- External API integrations (SAP, Peppol, TenderNed, etc.)
- PDF/document generation with business-specific templates
- Workflow triggers and business rules specific to the domain
- Notification dispatch with app-specific event types
- Custom settings pages with app-specific configuration
- Background jobs for domain-specific processing
6 changes: 6 additions & 0 deletions .claude/openspec/architecture/adr-002-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- URL pattern: `/index.php/apps/{app}/api/{resource}` — lowercase plural, hyphens.
- Methods: GET=read, POST=create, PUT=update, DELETE=remove. No custom methods.
- Pagination: support `_page` + `_limit`. Response includes `total`, `page`, `pages`.
- Errors: appropriate HTTP status + `message` field. NO stack traces in responses.
- Auth: Nextcloud built-in only. NO custom login/session/token flows.
- Public endpoints: annotate `#[PublicPage]` + `#[NoCSRFRequired]`. Register CORS OPTIONS route.
14 changes: 14 additions & 0 deletions .claude/openspec/architecture/adr-003-backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- **Controller → Service → Mapper** (strict 3-layer). Controllers NEVER call mappers directly.
- Controllers: thin (<10 lines/method). Routing + validation + response only.
- Services: ALL business logic. Stateless — no instance state between requests.
- Mappers: DB CRUD only. No business logic.
- DI: constructor injection with `private readonly`. NO `\OC::$server` or static locators.
- Entity setters: POSITIONAL args only. `$e->setName('val')` — NEVER `$e->setName(name: 'val')`.
(`__call` passes `['name' => val]` but `setter()` uses `$args[0]`.)
- Routes: `appinfo/routes.php`. Specific routes BEFORE wildcard `{slug}` routes.
- Config: `IAppConfig` with sensitive flag for secrets. NEVER read DB directly.
- Lifecycle: schema init via repair steps (`IRepairStep`), background via job queue, events via dispatcher.
- **Spec traceability**: every class and public method MUST have `@spec` PHPDoc tag(s) linking to
the OpenSpec change that caused it: `@spec openspec/changes/{name}/tasks.md#task-N`.
Multiple `@spec` tags allowed (code touched by multiple changes). File-level `@spec` in header docblock.
This enables: code → docblock → spec traceability alongside code → git blame → commit → issue → spec.
Loading
Loading