high priority high complexity backend pending backend specialist Tier 1

Acceptance Criteria

BufdirPdfGenerator produces a valid PDF/A or standard PDF that opens in iOS Files app, Android default PDF viewer, and desktop PDF readers without errors
PDF page contains an organization header block with: organization name, chapter name, organization number, and contact person
Reporting period block displays start date and end date in DD.MM.YYYY format with Norwegian labels
Activity summary table lists each activity type with total count and total hours, matching the data from BufdirActivityRecord list
Participant counts section displays total unique participants and total activity sessions
Signature field section is present at the bottom of the final page with coordinator name, date line, and signature line
PDF is formatted for A4 page size with Norwegian language content throughout
If activity data spans multiple pages, table header row repeats on each page
Generator accepts List<BufdirActivityRecord> and BufdirReportMetadata (org info, period, coordinator) and returns Future<Uint8List>
Generated PDF is readable without accessibility barriers β€” text is selectable (not image-based), font size is minimum 10pt
Unit test verifies PDF byte output is non-empty and begins with the PDF magic bytes (%PDF)

Technical Requirements

frameworks
Dart
pdf (pub.dev dart PDF library)
printing (pub.dev, for sharing/saving PDF on device)
Flutter
data models
BufdirActivityRecord
BufdirReportMetadata
BufdirPdfLayout
Organization
Chapter
performance requirements
PDF generation for a standard quarterly report (up to 500 activity rows, ~10 page summary table) must complete in under 5 seconds
PDF file size must not exceed 2MB for a standard report to remain shareable via standard messaging apps
Avoid embedding high-resolution images unless strictly required by the Bufdir template β€” use vector drawing instead
security requirements
PDF metadata (Author, Creator, Producer fields) must not expose internal system information β€” set to neutral values (app name and version only)
Generated PDF must not be cached in a public app temp directory β€” pass bytes directly to share sheet
Signature fields are visual placeholders only β€” no digital signature cryptography is in scope for this task

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use the 'pdf' Dart package (pub.dev) β€” it is pure Dart, requires no native code, and works on both Flutter mobile and server-side Dart. Combine with 'printing' package only for device share/print UI, keeping the generator itself free of Flutter UI dependencies. Define all layout constants (margins, font sizes, column widths, colors) in a BufdirPdfTheme class so the template can be adjusted without touching generator logic. Use a TtfFont loaded from app assets for Norwegian character support β€” the default Helvetica built into the pdf package does not include Γ¦/ΓΈ/Γ₯.

Embed NotoSans or similar open-source font that covers Latin Extended-A. Structure the generator around a BufdirPdfLayout builder that assembles: (1) header widget, (2) period widget, (3) activity table widget (using pdf package's TableHelper or custom table with page break handling), (4) participant counts widget, (5) signature widget. The activity table should aggregate data by activity type rather than listing every individual activity row β€” confirm this grouping matches Bufdir's expected format. The Bufdir PDF template details must be confirmed with the client by reviewing the actual Word template before finalizing layout implementation.

Testing Requirements

Unit tests using flutter_test with the pdf Dart package. Test cases: (1) output is non-empty Uint8List beginning with '%PDF' magic bytes, (2) generator completes without throwing for a minimal valid input (1 activity, full metadata), (3) generator handles empty activity list β€” produces PDF with header and period blocks but empty summary table with 'Ingen aktiviteter' message, (4) Norwegian characters (Γ¦, ΓΈ, Γ₯) are embedded correctly (requires a font that supports the full Latin Extended-A range), (5) metadata object with null optional fields (e.g., no coordinator name) β€” assert graceful fallback text rather than exception. For visual validation, generate a sample PDF during development and manually review against the actual Bufdir Word template provided by the organizations. Screenshot/golden testing of PDF output is not required for CI but a reference PDF fixture should be stored in test/fixtures/ for manual comparison.

Component
Bufdir PDF Report Generator
infrastructure medium
Epic Risks (3)
high impact medium prob technical

NHF contacts can belong to up to five local chapters simultaneously. If the deduplication logic in the activity query service incorrectly attributes cross-chapter activities, organisations will either under-report or over-report to Bufdir, which could trigger grant clawback or compliance investigations.

Mitigation & Contingency

Mitigation: Implement deduplication using the existing multi-chapter membership service as the source of truth for chapter affiliation. Write test fixtures covering all known multi-chapter edge cases and validate outputs against manually prepared reference exports from NHF.

Contingency: If deduplication cannot be made deterministic for complex hierarchies before release, gate the export behind an org-level feature flag and require NHF to validate a preview export against their manual Excel before enabling in production.

medium impact medium prob dependency

Server-side Dart libraries for Excel generation are less mature than equivalents in Node.js or Python. The chosen library may lack support for Bufdir-required formatting features (merged cells, data validation, specific date formats), requiring significant workaround effort or a library switch mid-implementation.

Mitigation & Contingency

Mitigation: Evaluate the top two Dart xlsx libraries (excel, spreadsheet_decoder) against a Bufdir template sample file before committing. Identify all required formatting features and verify library support in a spike.

Contingency: If no Dart library meets requirements, implement the Excel generation as a Supabase Edge Function in TypeScript using the well-supported ExcelJS library, exposing it to the Dart backend via an internal RPC call.

medium impact medium prob integration

The attachment bundler must retrieve documents from Supabase Storage that were uploaded by the document attachments feature. If storage paths, RLS policies, or signed URL expiry have not been standardised across features, the bundler may fail to retrieve attachments at export time.

Mitigation & Contingency

Mitigation: Audit the document attachments feature's storage schema and RLS policies before implementing the bundler. Agree on a stable internal service-account access pattern for cross-feature storage reads.

Contingency: If cross-feature storage access cannot be made reliable, implement the bundler to include only attachments that can be retrieved successfully and produce a manifest listing any attachments that could not be bundled, rather than failing the entire export.