diff --git a/.specter-prompt.txt b/.specter-prompt.txt index 38992dc5..76d94445 100644 --- a/.specter-prompt.txt +++ b/.specter-prompt.txt @@ -3,14 +3,10 @@ You are generating OpenSpec change artifacts for a Nextcloud app. You are running HEADLESS. Do NOT use AskUserQuestion, interactive prompts, or skills. Write files directly using the Write tool. -## App Context -Project: Decidesk -Repo: ConductionNL/decidesk -Type: Nextcloud App (PHP backend + Vue 2 frontend) -Description: Universal decision-making platform for governance bodies — manages meetings, agendas, motions, amendments, voting, minutes, and decision tracking with configurable workflows per organization type. -Key components: Dashboard, Meeting Management, Agenda Builder, Motion/Voting, Minutes/Decisions, Governance Bodies, Citizen Participation -Database: PostgreSQL (via OpenRegister's ObjectService) -Mount path: /var/www/html/custom_apps/decidesk +## Inputs +- Change: p2-meeting-management-core-t3 (title: Meeting Management — Core T3) +- Context brief: openspec/changes/p2-meeting-management-core-t3/context-brief.md +- Data model ADR: openspec/architecture/adr-000-data-model.md Governance Domains: 1. Legislative/democratic bodies (municipalities, provinces, water boards) @@ -33,12 +29,38 @@ Project guidelines: See ../project.md for workspace-wide standards **Spec type:** capability ## Step 1: Read context Read these files COMPLETELY before writing anything: -- openspec/changes/p3-citizen-participation/context-brief.md (features, stories, stakeholders, journeys) +- openspec/changes/p2-meeting-management-core-t3/context-brief.md (features, stories, stakeholders, journeys) - openspec/architecture/adr-000-data-model.md (entity definitions) - All files in openspec/architecture/ (app ADRs) - All files in .claude/openspec/architecture/ (company ADRs, if present) -## Global Rules +## Step 2: Get artifact templates +Run: `openspec instructions proposal --change p2-meeting-management-core-t3 --json` +This returns the template and rules for the proposal artifact. +Then do the same for: design, specs, tasks (in that order). + +## Step 3: Write artifacts +For each artifact (proposal → design → specs → tasks): +1. Read the template from openspec instructions +2. Fill it using the REAL data from context-brief.md: + - Features with their demand scores and descriptions + - User stories with acceptance criteria (GIVEN/WHEN/THEN) + - Customer journeys with triggers and pain points + - Stakeholder profiles with responsibilities and goals + - Entity schemas from ADR-000 (do NOT invent new entities) +3. Write the artifact file using the Write tool +4. Verify it exists + +## Step 4: Commit +After all 4 artifacts are written: +```bash +git add openspec/changes/p2-meeting-management-core-t3/ +git commit -m 'feat: Add OpenSpec change p2-meeting-management-core-t3 from Specter' +``` +Do NOT push — the caller handles pushing. +Do NOT create branches — stay on the current branch. + +## Rules - Use REAL data from context-brief.md — NEVER invent features, stories, or entities - Entities MUST match ADR-000 exactly ## Your Task: Write design.md and specs/spec.md diff --git a/openspec/changes/p2-meeting-management-core-t3/.openspec.yaml b/openspec/changes/p2-meeting-management-core-t3/.openspec.yaml new file mode 100644 index 00000000..3a54a172 --- /dev/null +++ b/openspec/changes/p2-meeting-management-core-t3/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-04-16 diff --git a/openspec/changes/p2-meeting-management-core-t3/context-brief.md b/openspec/changes/p2-meeting-management-core-t3/context-brief.md new file mode 100644 index 00000000..cab31adb --- /dev/null +++ b/openspec/changes/p2-meeting-management-core-t3/context-brief.md @@ -0,0 +1,2983 @@ +# Context Brief: Meeting Management — Core T3 + +**App:** Decidesk — Universal decision-making platform for governance bodies, associations, corporate boards, and operational meetings +**Spec:** p2-meeting-management-core-t3 +**Platform:** Nextcloud + OpenRegister + +**Depends on:** p2-meeting-management + +## Dependency Specs (content) + +These specs were already decided/implemented. Use them as context. + +### p2-meeting-management +# Context Brief: Meeting Management + +**App:** Decidesk — Universal decision-making platform for governance bodies, associations, corporate boards, and operational meetings +**Spec:** p2-meeting-management +**Platform:** Nextcloud + OpenRegister + +**Depends on:** p1-schemas-and-data-model, p1-dashboard-and-navigation, p1-crud-operations + +## Dependency Specs (content) + +These specs were already decided/implemented. Use them as context. + +### p1-schemas-and-data-model +# Context Brief: Schemas and Data Model + +**App:** Decidesk — Universal decision-making platform for governance bodies, associations, corporate boards, and operational meetings +**Spec:** p1-schemas-and-data-model +**Platform:** Nextcloud + OpenRegister + +## Features (6 total, sorted by market demand) + +### Resolution Register +**demand: 206** (66 tender mentions) | Category: core + +### Identity Governance Management +**demand: 91** (27 tender mentions) | Category: governance + +### Register to speak at committee meeting +**demand: 56** (18 tender mentions) | Category: core + +### Voter Register +**demand: 26** (6 tender mentions) | Category: other + +### Attendance Register +**demand: 26** (6 tender mentions) | Category: other + +### Link emails to specific decisions via OpenRegister _mail metadata +**demand: unknown** | Category: other + +## User Stories (6 linked) + +### Story 1: Configure SAML 2.0 identity provider +**Priority:** should +As an IAM administrator, I want to configure a SAML 2.0 identity provider using a metadata XML file, so that I can integrate with government identity federations that do not support OIDC. + +**Acceptance Criteria:** +GIVEN the IdP configuration screen WHEN I upload a SAML metadata XML file THEN the entity ID, SSO URL, and signing certificate are parsed and pre-filled +GIVEN a saved SAML configuration WHEN I download the OpenRegister service provider metadata THEN I receive a valid SAML metadata XML I can import into the identity provider + +### Story 2: View provenance and update metadata for a dataset +**Priority:** should +As a researcher, I want to view the provenance metadata of a register dataset including its source organisation, data steward, creation date, and last update timestamp, so that I can assess whether the dataset is authoritative and current enough for my research. + +**Acceptance Criteria:** +GIVEN a public register WHEN I open the dataset information page THEN I see the responsible organisation (OIN), data steward contact, creation date, last modified timestamp, and the update frequency commitment +GIVEN the dataset page THEN it links to the processing register entry and any applicable open data licence + +### Story 3: Link Nextcloud Mail emails to invoices +**Priority:** must-have +As a Nextcloud user, I want to link emails from Nextcloud Mail to invoice/expense records using OpenRegister _mail metadata, creating a native email-to-invoice connection. + +### Story 4: Link to Nextcloud Contacts +**Priority:** must-have +As a Nextcloud user, I want invoicing contacts to sync with Nextcloud Contacts via OpenRegister _contacts metadata, so I have one unified address book. + +### Story 5: Link emails to specific decisions via OpenRegister _mail metadata +**Priority:** must +As a decision maker, I want emails related to a decision to be automatically linked via the _mail metadata column so that all correspondence is part of the decision dossier and visible in the Mail app sidebar. + +**Acceptance Criteria:** +GIVEN an email mentioning a decision reference number WHEN the email is received THEN it appears linked to the decision object in OpenRegister AND is visible in the Nextcloud Mail sidebar + +### Story 6: Unsubscribe directly from email +**Priority:** must +As a subscriber, I want to unsubscribe from a mailing list by clicking a single link in the email footer, so that I stop receiving unwanted emails immediately. + +**Acceptance Criteria:** +Unsubscribe link visible in email footer; single click completes unsubscribe (no login required); confirmation page shown; no further emails sent from that list + +## Customer Journeys (15 linked) + +### AV & Webcast Infrastructure Management +Managing AV infrastructure in raadzaal and commissiekamers. Discussion systems, PTZ cameras, AV control, webcast/streaming, microphone management. +**Trigger:** Meeting scheduled requiring AV support; system maintenance/upgrade +**Desired outcome:** Reliable AV infrastructure supporting meetings with high-quality recording and streaming +**Current pain:** Complex multi-vendor systems; AV-RIS integration for indexing; maintenance windows; high costs; rapid tech evolution +**Frequency:** Every meeting (setup/support) + periodic maintenance + +### Handle Complex Multi-Domain Citizen Question +A citizen has a question spanning multiple domains (e.g., housing benefit, parking permit, and social assistance). The front desk officer creates linked zaken or a combined intake and routes each to the correct department. +**Trigger:** Citizen presents with multiple interconnected service needs in a sing +... (truncated) + +## Features (14 total, sorted by market demand) + +### Historical Meeting Trend Analysis and Tracking +**demand: 36** (10 tender mentions) | Category: core + +### Configure and enforce no-meeting days and focus time blocks +**demand: 36** (11 tender mentions) | Category: core + +### Send automated post-meeting effectiveness surveys +**demand: 35** (10 tender mentions) | Category: core + +### Display live meeting cost ticker during meetings +**demand: 35** (11 tender mentions) | Category: core + +### Virtual Shareholder Meeting Hosting +**demand: 35** (10 tender mentions) | Category: core + +### Meeting Load Assessment +**demand: 34** (10 tender mentions) | Category: core + +### Virtual Annual General Meeting Support +**demand: 34** (11 tender mentions) | Category: core + +### Inter-Meeting Progress Documentation and Communication +**demand: 31** (10 tender mentions) | Category: core + +### Track meeting efficiency KPIs on personal scorecard +**demand: 31** (10 tender mentions) | Category: core + +### Video Meeting Integration with Multiple Platforms +**demand: 31** (10 tender mentions) | Category: core + +### Meeting invitations with RSVP +**demand: 22** (1 tender mentions) | Category: core + +### Log meeting notes +**demand: 20** (1 tender mentions) | Category: core + +### Meeting scheduler +**demand: 20** (1 tender mentions) | Category: core + +### Rate meetings on a 1-10 scale after each session +**demand: 15** (5 tender mentions) | Category: core + +## User Stories (135 linked) + +### Story 1: Real Time Meeting Cost Ticker +**Priority:** wont +As a organizational leader, I want to have real-time meeting cost ticker capabilities, so that meeting effectiveness can be measured and improved. + +### Story 2: Real Time Progress Tracking +**Priority:** wont +As a meeting participant, I want to have real-time progress tracking capabilities, so that meetings produce richer outcomes through active participation. + +### Story 3: Real Time Cost Ticker +**Priority:** wont +As a meeting participant, I want to have real-time cost ticker capabilities, so that meetings produce richer outcomes through active participation. + +### Story 4: Live Visualization +**Priority:** wont +As a organizational leader, I want to have live-visualization capabilities, so that meeting effectiveness can be measured and improved. + +### Story 5: Participation Rate Analysis +**Priority:** wont +As a organizational leader, I want to have participation rate analysis capabilities, so that meeting effectiveness can be measured and improved. + +### Story 6: Deliberation Platforms +**Priority:** wont +As a presiding officer, I want to use deliberation platforms, so that meetings follow established rules fairly. + +### Story 7: Timeboxing +**Priority:** wont +As a meeting facilitator, I want to have timeboxing capabilities, so that meetings are productive and engaging. + +### Story 8: Live Dialogue +**Priority:** wont +As a citizen, I want to have live dialogue capabilities, so that the platform meets diverse organizational needs. + +### Story 9: Virtual Shareholder Meeting Hosting +**Priority:** wont +As a corporate secretary, I want to have virtual shareholder meeting hosting capabilities, so that the platform meets diverse organizational needs. + +### Story 10: Integrated Decision Log +**Priority:** wont +As a project manager, I want to have integrated decision log capabilities, so that nothing falls through the cracks after meetings. + +### Story 11: Meeting Cost Calculator +**Priority:** wont +As a organizational leader, I want to use meeting cost calculator, so that meeting effectiveness can be measured and improved. + +### Story 12: Customise rejection email templates per selection phase +**Priority:** should +As an HR Recruiter, I want to use different rejection email templates depending on how far an applicant progressed in the process, so that a candidate rejected after a first interview receives a more personal message than one rejected at initial screening. + +**Acceptance Criteria:** +GIVEN I am managing email templates WHEN I create a template THEN I can link it to one or more selection phases (screening, first interview, assessment, final interview) +GIVEN an applicant is rejected from a specific phase WHEN I send rejection communication THEN the system pre-selects the template associated with that phase + +### Story 13: Send automated post-meeting effectiveness surveys +**Priority:** should +As a meeting secretary, I want to automatically send a brief effectiveness survey (1-10 rating + optional comments) to all attendees after each meeting, so that meeting quality trends can be tracked and improved over time. + +**Acceptance Criteria:** +["Survey sent automatically after meeting ends", "Rating scale 1-10 (EOS Level 10 format)", "Optional anonymous comments", "Trend data aggregated per meeting series", "12.5% productivity improvement benchmark tracked (Gallup)"] + +### Story 14: Rate meetings on a 1-10 scale after each session +**Priority:** should +As a meeting participant, I want to rate each meeting on a 1-10 scale (inspired by EOS Level 10) with optional dimension ratings (preparation, facilitation, outcomes, time management), so that meeting quality is continuously measured and improved. + +**Acceptance Criteria:** +["Quick 1-10 overall rating at meeting end", "Optional dimension ratings (preparation, facilitation, outcomes, time)", "Trend data per meeting series", "Average rating visible to organizer", "Alert when rating drops below threshold", "Benchmarking against organizational average"] + +### Story 15: Track cost price trend over multiple years +**Priority:** should +As a Management Accountant, I want to track the cost price trend for each product over multiple years, so that I can identify structural cost increases and inform the meerjarenbegroting. + +**Acceptance Criteria:** +GIVEN cost prices have been calculated for at least two years WHEN the accountant opens the trend view for a product THEN the system displays a chart showing cost price per year with direct and indirect cost layers +GIVEN a cost component has grown by more than 10% year-on-year WHEN the accountant reviews the trend THEN the system highlights the component and links to the underlying cost centre +GIVEN the accountant selects a multi-year range WHEN they export the trend THEN the system produces an Excel file with one column per year and rows for each cost component + +### Story 16: Define volume drivers for product cost price calculation +**Priority:** should +As a Management Accountant, I want to define and maintain volume drivers (e.g. number of permits issued, hours delivered) per product, so that unit cost prices can be calculated accurately. + +**Acceptance Criteria:** +GIVEN a product is configured WHEN the accountant sets a volume driver and enters the actual volume for the period THEN the system uses this to divide total product cost into a unit cost price +GIVEN the volume driver value is zero WHEN the cost price calculation runs THEN the system skips the unit price calculation and shows a warning instead of dividing by zero +GIVEN the volume driver is updated WHEN the accountant saves it THEN the system recalculates the unit cost price immediately and shows the before/after comparison + +### Story 17: Select KPIs for public infographic +**Priority:** should +As a communication-advisor, I want to select a curated set of approved KPIs from goviq to include in a public infographic, so that I base citizen communications on verified municipal data. + +**Acceptance Criteria:** +GIVEN I open the infographic builder WHEN I browse the KPI library THEN I can only see KPIs flagged as 'public-safe' by the privacy officer +GIVEN I add a KPI to the infographic WHEN I configure it THEN I can choose to display the value, trend, target, or a combination +GIVEN a KPI's public-safe flag is revoked WHEN I next open the infographic THEN the KPI is replaced with a placeholder and I am notified + +### Story 18: Rate own competencies against job profile +**Priority:** should +As an Employee, I want to rate myself on the competencies defined in my job profile, so that my self-perception is part of the performance conversation alongside my manager's assessment. + +**Acceptance Criteria:** +GIVEN I open the competency section of my self-assessment WHEN the page loads THEN I see only the competencies linked to my specific job profile (functieprofiel) +GIVEN I rate a competency WHEN I choose a score on the 1–5 scale THEN I can add a required written example to substantiate my rating +GIVEN I submit my self-assessment WHEN my manager opens the review THEN they see my competency ratings alongside the space for their own rating on the same scale + +### Story 19: Ensure HR personal data is handled according to AVG requirements +**Priority:** should +As an ict-architect, I want personal data from the HR system to be handled according to AVG (GDPR) requirements during transit and storage, so that the integration is legally compliant. + +**Acceptance Criteria:** +GIVEN the HR integration transfers employee data WHEN data is received THEN only the minimum required fields (employee ID, availability hours, role) are stored; names and personal identifiers are not persisted beyond the sync session +GIVEN the integration configuration is saved WHEN I view the data retention settings THEN I can specify a retention period after which capacity snapshots are anonymised + +### Story 20: Submit a deliverable status update as a supplier +**Priority:** should +As an external-supplier, I want to update the status of my assigned deliverables and upload supporting documents, so that the project team has up-to-date information on supplier progress. + +**Acceptance Criteria:** +GIVEN I am logged in and viewing my assigned deliverables WHEN I update a deliverable status to 'Completed' and upload an acceptance document THEN the project manager is notified and the deliverable shows the new status +GIVEN I submit a status update WHEN the project manager views the deliverable THEN they see the supplier's update, the uploaded file, and the submission timestamp + +## Customer Journeys (15 linked) + +### AV & Webcast Infrastructure Management +Managing AV infrastructure in raadzaal and commissiekamers. Discussion systems, PTZ cameras, AV control, webcast/streaming, microphone management. +**Trigger:** Meeting scheduled requiring AV support; system maintenance/upgrade +**Desired outcome:** Reliable AV infrastructure supporting meetings with high-quality recording and streaming +**Current pain:** Complex multi-vendor systems; AV-RIS integration for indexing; maintenance windows; high costs; rapid tech evolution +**Frequency:** Every meeting (setup/support) + periodic maintenance + +### Handle Complex Multi-Domain Citizen Question +A citizen has a question spanning multiple domains (e.g., housing benefit, parking permit, and social assistance). The front desk officer creates linked zaken or a combined intake and routes each to the correct department. +**Trigger:** Citizen presents with multiple interconnected service needs in a single interaction +**Desired outcome:** All needs are captured, routed, and tracked under a single citizen profile; no request is lost or duplicated +**Current pain:** Systems do not support grouped intake; officer must create each zaak separately and manually inform all receiving departments +**Frequency:** weekly + +### Meeting Recording Publication +Video and audio recordings processed, indexed (linked to agenda items), captioned, and published in RIS for on-demand viewing. +**Trigger:** Completion of a recorded meeting +**Desired outcome:** Indexed, accessible recordings published and linked to relevant agenda items in the RIS +**Current pain:** Long processing times; manual indexing; accessibility requirements (captions); large file storage +**Frequency:** After every recorded meeting + +### System Integration & Data Exchange +Managing integrations between RIS and other systems: zaaksysteem, DMS, AV/webcast, archiving, PLOOI platform. +**Trigger:** New system implementation, upgrade, or integration requirement +**Desired outcome:** Seamless data flow between RIS and connected systems with no manual re-entry +**Current pain:** Legacy APIs; proprietary interfaces; vendor lock-in; complex AV integration; multiple auth systems +**Frequency:** Ongoing (initial setup + continuous maintenance) + +### Water Board General Assembly Meeting +Water board general assembly meets at least 6x/year. Sets policy, approves budgets, oversees executive board. Chaired by dijkgraaf. Secretary-director maintains minutes. +**Trigger:** Scheduled general assembly meeting (minimum 6x/year) +**Desired outcome:** Policy decisions made, budgets approved, oversight exercised, complete minutes maintained +**Current pain:** Similar needs as municipalities but different governance; fewer commercial RIS options; unique stakeholder categories +**Frequency:** Minimum 6 times per year (general assembly); bi-weekly (executive board) + +### Test BPMN Process in Staging Environment +Before publishing, the process designer runs the BPMN model with test cases to verify gateway conditions, timer behaviour, and task routing behave as intended. +**Trigger:** Process model is completed and ready for validation before go-live +**Desired outcome:** All process paths are verified correct; edge cases and error paths are handled without unexpected process suspension +**Current pain:** No integrated test runner; testing requires manual zaak creation and step-by-step verification which is slow and incomplete +**Frequency:** monthly + +### Presidium Agenda Setting +The presidium (faction leaders + chair) meets to set the agenda. Decides which items go to which committee, hamerstuk vs bespreekstuk, and overall meeting planning. +**Trigger:** Scheduled presidium meeting at start of each meeting cycle +**Desired outcome:** Approved agenda with clear assignment of items to committees and plenary +**Current pain:** Manual compilation of agenda proposals; difficulty balancing workload across committees +**Frequency:** Every meeting cycle (approximately every 3-4 weeks) + +### Faction Position Coordination +Faction leader coordinates positions on upcoming agenda items through faction meetings. Distributes preparatory work, aligns voting positions, assigns spokespersons. +**Trigger:** Publication of agenda for upcoming council/committee meeting +**Desired outcome:** Aligned faction positions on all agenda items, assigned spokespersons, coordinated motion/amendment strategy +**Current pain:** Fragmented communication tools; no shared workspace; difficulty tracking faction-wide positions across multiple agenda items +**Frequency:** Weekly during active meeting periods + +### Open Data Publication (ORI) +Publishing council information as open data following the ORI standard. API access, linked data, integration with PLOOI. Over 100 Dutch municipalities participate. +**Trigger:** New meeting data or documents are published in the RIS +**Desired outcome:** Council data available as structured open data via standardized API, compliant with ORI and Woo +**Current pain:** Vendor-specific connectors required; inconsistent data quality; evolving standard; limited real-time capability +**Frequency:** Continuous (automated sync) + +### Press Coverage & Media Access +Journalists access council meetings, documents, and officials for reporting. Includes press pass registration, gallery access, post-meeting briefings, and RIS research. +**Trigger:** Newsworthy item on council agenda or need for background research +**Desired outcome:** Journalist can efficiently access all public council information, attend meetings, contact officials +**Current pain:** Complex registration; limited press facilities; restrictions on filming/quoting; delayed recordings; declining journalism resources +**Frequency:** Continuous (more intense around plenary meetings) + +### Decision Execution & Follow-up +After council makes a decision, the executive is responsible for executing it. Includes implementing policy changes, allocating budgets, and reporting back to council. +**Trigger:** Council adopts a proposal, motion, or amendment requiring executive action +**Desired outcome:** Decision is fully implemented and the council is informed of completion +**Current pain:** Difficulty linking decisions to implementation; no automated tracking; reporting often delayed; unclear accountability +**Frequency:** Continuous (each adopted decision requires follow-up) + +### Live Meeting Following & Webcasting +Citizens and journalists follow meetings in real-time, physically or via live webcast/stream. Includes viewing agenda in real-time and tracking which item is being discussed. +**Trigger:** Council or committee meeting is in session +**Desired outcome:** Interested parties can follow the meeting in real-time with access to relevant documents +**Current pain:** Webcast quality varies; no real-time agenda tracking; difficult to find relevant document during live viewing; no live captions +**Frequency:** Every public meeting (3-6 per month) + +### RIS Platform Migration & Transition +Migrating from one RIS to another including data migration of historical records, user transition, integration reconfiguration, and training. +**Trigger:** Contract expiration, dissatisfaction with current RIS, or need for new features +**Desired outcome:** Successful migration with complete data transfer, minimal disruption, and satisfied users +**Current pain:** Complex data migration from proprietary formats; risk of data loss; user resistance; training needs; vendor lock-in +**Frequency:** Every 4-8 years (contract cycles) + +### Provincial States Meeting Cycle +Provincial States follow similar BOB model but larger scale. CdK chairs, griffier supports, factions coordinate through presidium. State proposals through statencommissies before statendag. +**Trigger:** Monthly meeting cycle of provincial states +**Desired outcome:** Provincial policy decisions made through structured committee and plenary process +**Current pain:** Similar to municipal pain points but larger scale; more formal procedures +**Frequency:** Monthly (statendag) plus committee meetings + +### Complete Intake Form on Behalf of Citizen +When a citizen cannot use digital channels (due to limited digital literacy or accessibility needs), a front desk officer fills in the digital intake form on their behalf, with the citizen's verbal consent recorded. +**Trigger:** Citizen is unable to self-serve digitally and requests counter or telephone assistance +**Desired outcome:** Same data quality and automated zaak creation as a self-service submission, with the assisting officer's identity logged for audit purposes +**Current pain:** Officer-assisted intake often bypasses digital forms entirely, resulting in manually created zaken with less structured data +**Frequency:** daily + +## Stakeholders (383 linked) + +### CEO / Managing Director +Chief Executive Officer or managing director responsible for day-to-day management of the company. In Dutch two-tier model, member of the Raad van Bestuur (management board). +**Responsibilities:** Setting corporate strategy, executing board decisions, representing the company externally, reporting to supervisory board, preparing annual accounts, convening shareholder meetings +**Pain points:** Complex approval chains for strategic decisions, balancing stakeholder interests, ensuring compliance with Dutch Corporate Governance Code, managing conflict of interest declarations, coordinating between management board and supervisory board +**Goals:** Efficient decision-making processes, clear audit trails for all governance decisions, streamlined communication with supervisory board and shareholders, digital-first governance workflows + +### CFO / Financial Director +Chief Financial Officer responsible for financial reporting, internal controls, SOX compliance (if applicable), and financial governance. Interfaces with audit committee and external auditors. +**Responsibilities:** Financial reporting and annual accounts, internal controls (SOX Section 302/404 certification), risk management, treasury, tax compliance, audit coordination, dividend proposals +**Pain points:** SOX compliance documentation burden, coordinating with external auditors, ensuring internal control effectiveness, managing financial reporting deadlines, audit committee preparation workload +**Goals:** Automated internal control documentation, streamlined audit processes, real-time financial governance dashboards, efficient committee reporting + +### Board Secretary / Company Secretary +Corporate governance professional who manages all governance processes, board meetings, minutes, compliance, and stakeholder communication. Guardian of governance procedures and compliance. +**Responsibilities:** Preparing board packs and agendas, taking and distributing minutes, managing governance calendar, ensuring quorum, advising on governance procedures, maintaining corporate registers, coordinating AGM logistics, filing with KVK/AFM +**Pain points:** Manual board pack assembly, version control of sensitive documents, tracking action items across multiple boards and committees, ensuring timely distribution, managing multiple meeting calendars, paper-based minute signing processes +**Goals:** Digital board portal with secure document distribution, automated meeting scheduling and reminders, electronic minute approval workflows, integrated governance calendar, real-time action item tracking + +### Supervisory Board Chair +Chair of the supervisory board (Raad van Commissarissen) in Dutch two-tier governance model. Leads supervisory oversight, sets RvC agenda, and maintains relationship with management board. +**Responsibilities:** Chairing supervisory board meetings, setting RvC agenda, appointing committee chairs, leading board evaluations, maintaining dialogue with CEO and shareholders, ensuring proper governance, managing conflicts of interest within RvC +**Pain points:** Limited visibility into management decisions between meetings, difficulty coordinating dispersed supervisory board members, managing information asymmetry with management board, ensuring all members are adequately informed +**Goals:** Secure digital workspace for supervisory board, real-time access to management information, efficient virtual meeting capabilities, structured oversight and approval workflows + +### Supervisory Board Member +Individual member of the supervisory board. Provides oversight, advice, and approval on management decisions. May serve on audit, remuneration, or nomination committees. +**Responsibilities:** Attending supervisory board and committee meetings, reviewing management decisions, approving major transactions and appointments, monitoring risk management, evaluating management board performance +**Pain points:** Information overload from board packs, limited time for preparation, difficulty accessing documents on mobile devices, lack of annotation and collaboration tools, managing multiple board memberships +**Goals:** Mobile-friendly board portal with offline access, smart document summaries, annotation and note-taking tools, secure communication with fellow board members, clear voting and resolution tracking + +### Shareholder +Owner of shares in a BV or NV. Has voting rights at the Algemene Vergadering van Aandeelhouders (AVA/AGM). Dutch law provides specific rights for minority shareholders. +**Responsibilities:** Attending and voting at AVA/AGM, approving annual accounts, appointing/dismissing directors, approving statute amendments, exercising inquiry rights (enquêterecht) +**Pain points:** Complex proxy voting processes, lack of transparency in pre-meeting information, difficulty participating in hybrid/digital meetings, limited engagement between AGMs, unclear resolution outcomes +**Goals:** Easy digital proxy voting, transparent access to meeting agendas and documents, real-time participation in hybrid AGMs, clear dividend and resolution information, accessible corporate governance information + +### Institutional Investor +Large-scale investor (pension fund, asset manager, insurance company) with significant shareholdings. Subject to Shareholder Rights Directive II (SRD II) stewardship obligations. +**Responsibilities:** Stewardship and engagement with portfolio companies, proxy voting across hundreds of AGMs, ESG assessment, compliance with SRD II disclosure requirements, filing substantial holdings notifications +**Pain points:** Managing proxy voting at scale across many companies, reliance on proxy advisors (ISS/Glass Lewis), cross-border voting complexity, meeting SRD II engagement and disclosure requirements, lack of standardized governance data +**Goals:** Automated proxy voting workflows, integrated ESG governance scoring, efficient engagement tracking, SRD II compliance automation, standardized corporate governance data feeds + +### Proxy Advisor +Firm that provides voting recommendations to institutional investors (ISS, Glass Lewis). Analyzes governance proposals and issues benchmark voting policies. Controls 90%+ of proxy advisory market. +**Responsibilities:** Analyzing AGM agenda items and resolutions, issuing voting recommendations, maintaining benchmark voting policies, researching corporate governance practices, reporting on voting outcomes +**Pain points:** Accessing timely and accurate meeting information across jurisdictions, analyzing large volumes of AGM proposals, maintaining consistent governance standards globally, adapting to regulatory changes +**Goals:** Standardized digital access to AGM agendas and resolutions, automated governance data collection, efficient cross-border meeting analysis, real-time resolution tracking + +### Province IT Security Officer +Provincial security officer assessing sovereignty risks across regional government services +**Responsibilities:** Regional cloud policy enforcement; vendor assessment; data classification +**Pain points:** Diverse IT landscapes across municipalities; no standardized sovereignty assessment +**Goals:** Unified sovereignty dashboard for the region; standardized assessment methodology + +### External Auditor +Independent auditor who audits annual accounts and reports to shareholders. In Dutch governance, appointed by AGM and reports to audit committee. Subject to auditor rotation requirements. +**Responsibilities:** Auditing annual financial statements, reporting to audit committee, attending AGM for shareholder questions, assessing internal controls (SOX 404 if applicable), issuing management letter, evaluating going concern +**Pain points:** Limited digital access to governance documentation, manual evidence collection for audit procedures, difficulty tracking management representations, coordinating with internal audit and audit committee +**Goals:** Digital audit evidence repository, secure access to board minutes and resolutions, automated management representation tracking, integrated communication with audit committee + +## Other App Entities (do NOT redefine) + +ActionItem, AgendaItem, Amendment, Area, ContactDetail, Decision, DigitalDocument, GovernanceBody, Meeting, Membership, Minutes, MonetaryAmount, Motion, Offer, Order, Participant, Person, Post, Product, Report, Speech, Vote, VotingRound + +## Company-Wide Architecture Rules (17 ADRs) + +These rules are MANDATORY for all Conduction apps. + +### ADR-001-data-layer +- 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 +on the product roadmap. Until then, 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 + +### ADR-002-api +- 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. + +### ADR-003-backend +- **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. + +### ADR-004-frontend +- **Vue 2 + Pinia + @nextcloud/vue + @conduction/nextcloud-vue**. NO Vuex. Options API only. +- State: Pinia stores in `src/store/modules/`. Use `createObjectStore` for OpenRegister CRUD. +- API calls: `axios` from `@nextcloud/axios` — auto-attaches CSRF token. NEVER raw `fetch()` for mutations. + Loading state with `try/finally`. +- Translations: ALL user-visible strings via `t(appName, 'text')`. NO hardcoded strings. + Translation keys MUST be English — Dutch translations go in `l10n/nl.json`. +- CSS: ONLY Nextcloud CSS variables (`var(--color-primary-element)`, etc.). NO hardcoded colors. + NEVER reference `--nldesign-*` directly — nldesign app handles theming. +- Router: history mode, base `generateUrl('/apps/{app}/')`. Requires matching PHP routes in `routes.php`. + Deep link URL templates MUST match the router mode — use path format (`/apps/{app}/entities/{uuid}`), + NOT hash format (`/apps/{app}/#/entities/{uuid}`). +- OpenRegister dependency: settings returns `openRegisters` (bool) + `isAdmin`. + Show empty state if OR missing. NEVER use `OC.isAdmin` — get from backend. +- NEVER `window.confirm()` or `window.alert()` — use `NcDialog` or `CnFormDialog` (WCAG, theming). +- NEVER read app state from DOM (`document.getElementById`, `dataset`) — use backend API or store. +- EVERY `await store.action()` call MUST be wrapped in `try/catch` with user-facing error feedback. +- NEVER import from `@nextcloud/vue` directly — use `@conduction/nextcloud-vue` which re-exports all + NC components plus Conduction components. This ensures consistent theming and component versions. +- EVERY component used in `