high priority low complexity integration pending integration specialist Tier 3

Acceptance Criteria

Service exposes: Future<ShareResult> share(GlobalKey repaintBoundaryKey, BenefitCalculationResultModel result)
Captures PNG from RepaintBoundary using RenderRepaintBoundary.toImage(pixelRatio: devicePixelRatio) then encodes to PNG bytes
Temporary PNG file written to application temp directory (path_provider) with a sanitised filename (benefit_summary.png)
share_plus ShareParams constructed with XFile pointing to the temp file plus a plain-text subject and text body as fallback
Plain-text fallback body contains all four metric values in Norwegian: e.g. '42 frivillige timer, 18 kontakter nådd, 54 berørte liv, 12 600 kr verdiskapning'
Temporary file is deleted after the share sheet is dismissed (regardless of whether user completed share or cancelled)
If toImage() throws, service returns ShareResult.error('capture_failed') without crashing the app
If share_plus throws (e.g. no share target available), service returns ShareResult.error('share_failed')
Service does NOT include any personal identity data (name, email, personnummer) in the shared content — only aggregate metrics
Service does NOT require any additional runtime permissions beyond what the app manifest already declares for share_plus
Returns ShareResult.success when the share sheet was opened (regardless of user action in the sheet)
Service is injectable and its share_plus dependency is abstracted behind an interface for testability

Technical Requirements

frameworks
Flutter
apis
share_plus (ShareParams, ShareResult)
performance requirements
PNG capture completes in < 500ms on a mid-range device at 3x pixel ratio
Temp file write is async and does not block the UI thread
security requirements
Shared content reviewed to ensure no PII included — only aggregated statistics and metric values per share_plus security guideline
Temp file stored in application-scoped temp directory, not external storage, to prevent other apps reading it before share completes
Temp file deleted after share sheet closes to minimise on-device data residency window
Receipt images or contact data must never be included in shareable content

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Abstract share_plus behind a thin IShareAdapter interface with a single share(ShareParams) method so tests can inject a mock. Use path_provider's getTemporaryDirectory() for the temp file path. After SharePlus.instance.share() returns, delete the temp file in a finally block (not just in then()) to guarantee cleanup even on exception. The plain-text string should use the same Norwegian locale number formatting as BenefitMetricTile to maintain consistency.

devicePixelRatio should be obtained from PlatformDispatcher.instance.views.first.devicePixelRatio rather than MediaQuery to avoid needing a BuildContext in the service layer. Document in code comments that the 500ms capture budget is the reason pixelRatio is capped at 3.0 — higher ratios produce negligibly better images but significantly slower capture times on older devices.

Testing Requirements

Unit tests: mock RenderRepaintBoundary and share_plus SharePlus interface. Test nominal path returns ShareResult.success and temp file is created then deleted. Test toImage() exception path returns ShareResult.error('capture_failed'). Test share_plus exception path returns ShareResult.error('share_failed').

Test plain-text fallback string contains all four expected metric values. Widget-level integration test: mount BenefitResultsCard with keyed RepaintBoundary, call service, verify no exception. Target coverage ≥ 85%.

Component
Benefit Share Service
service low
Epic Risks (3)
high impact medium prob technical

The RepaintBoundary PNG capture approach for sharing the results card may produce blurry or oversized images on high-DPI devices, or may silently fail on certain Android OEM configurations that restrict off-screen rendering. A failed share would break one of the core use cases (recruitment tool).

Mitigation & Contingency

Mitigation: Implement the capture using the established screenshot-capture-utility pattern already present in the Wrapped summary feature (component 542-screenshot-capture-utility). Test on a range of iOS and Android devices including Samsung and Huawei OEM builds during development. Set explicit pixel ratio (3.0) when calling toImage() to guarantee resolution.

Contingency: If image capture fails on a platform, the BenefitShareService falls back to sharing the plain-text summary only, with a user-facing message explaining the image could not be generated. This ensures the share flow never fully blocks.

high impact medium prob technical

Implementing full WCAG 2.2 AA compliance for the results card and metric tiles — including live regions, focus management, and semantic labels that read naturally in Norwegian — requires deep familiarity with Flutter semantics APIs. Gaps may only surface during screen reader testing on physical devices, late in the sprint.

Mitigation & Contingency

Mitigation: Use the existing semantics-wrapper-widget (606) and live-region-announcer (608) components from the accessibility feature rather than implementing custom semantics. Assign screen reader testing on a physical iPhone with VoiceOver as a mandatory acceptance gate, not an afterthought. Write widget tests using Flutter's AccessibilityGuideline matchers early in development.

Contingency: If screen reader issues are found late, the pure semantic markup approach (no Canvas numbers, all Semantics wrappers) limits the blast radius to label text corrections. Escalate to the accessibility feature team for a pairing session to resolve complex focus management issues.

medium impact low prob integration

The BenefitResultsCard must match the Wrapped design language used in the annual summary feature. If design tokens or widget patterns are inconsistent between the two features, the results card will look out of place and undermine the intended emotional impact for sharing.

Mitigation & Contingency

Mitigation: Review the existing Wrapped summary screen (529-wrapped-summary-screen) and stat card widget (530-stat-card-widget) implementations before building the results card. Reuse design tokens from the existing design-token-theme (200) system. Involve the designer in a review of the results card mock-up against the Wrapped language before implementation begins.

Contingency: If design parity issues are discovered post-implementation, isolate visual adjustments to the BenefitResultsCard widget. The feature's business logic and accessibility compliance are unaffected by visual polish changes.