# Requirements and Design Traceability

## Purpose

Provide a business analyst trace from business need to implemented design, verification evidence, risks, and validation needs for the Odin to Lunchtab Balance Transfer project.

## Inputs

- User request: "business analyst deliverable for requirements and design tracability" with heavy alignment.
- Product documentation: `README.md`.
- Core implementation: `src/odin_lunchtab/workflow.py`, `managed.py`, `manual_reconciliation.py`, `initial_balances.py`, `profiles.py`, `exception_candidates.py`, `candidate_viewer.py`, `gui_controller.py`, `run_reports.py`, `audit_control.py`.
- Verification evidence: `tests/test_workflow.py`, `tests/test_managed.py`, `tests/test_manual_reconciliation.py`, `tests/test_initial_balances.py`, `tests/test_matching_profiles.py`, `tests/test_exception_candidates.py`, `tests/test_candidate_viewer.py`, `tests/test_gui_controller.py`, `tests/test_sandbox_data.py`.

## BA Activities

- Plan and monitor analysis work: scoped this artifact to current implementation traceability, not solution redesign.
- Elicit and collaborate: captured the user-provided need for requirements and design traceability.
- Manage requirements lifecycle: assigned stable requirement, design, rule, risk, and test-reference IDs.
- Analyze requirements and define design options: mapped observable behavior to design choices and validation needs.
- Evaluate solution: compared implemented behavior and tests against trace coverage.

## Techniques Applied

- Document analysis: used README, code, and tests as evidence.
- Interface analysis: traced file inputs, CSV/XLSX contracts, generated artifacts, manifests, and GUI controller states.
- Business rules analysis: identified validation, matching, quarantine, audit, and publication rules.
- Data modeling: traced key data objects such as Odin records, Lunchtab users, transfer rows, InitialBalances rows, profiles, candidates, manifests, and audit summaries.
- Acceptance criteria: derived testable criteria from observed tests and business rules.
- Risk analysis: linked high-risk operational behaviors to existing controls and validation needs.

## Requirement Trace Catalog

| Requirement ID | Requirement Statement | Evidence Quality | Business Rule Links | Design Links | Verification Links | Risk Links | Lifecycle Status |
| --- | --- | --- | --- | --- | --- | --- | --- |
| REQ-001 | The system shall transfer Odin account balances into a copy of the Lunchtab users export without changing the selected source files. | Observed | BR-001, BR-008 | DES-001, DES-010 | TEST-001, TEST-002, TEST-017 | RISK-001, RISK-006 | Draft |
| REQ-002 | The system shall preserve every Lunchtab user row and add `OdinBalanceAmount` immediately after `DefaultFamilyBalanceAmount`. | Observed | BR-002 | DES-001 | TEST-002, TEST-009 | RISK-001 | Draft |
| REQ-003 | The system shall quarantine unsafe, ambiguous, malformed, duplicate, stale, unmatched, or name-validation-failed records instead of guessing. | Observed | BR-003, BR-004, BR-005 | DES-002, DES-003, DES-004 | TEST-003, TEST-004, TEST-010, TEST-011, TEST-012 | RISK-002, RISK-003 | Draft |
| REQ-004 | The system shall support venue-specific matching profiles with ordered rules, transforms, crosswalks, account-type scope, email username matching, and optional name fallback. | Observed | BR-004, BR-006 | DES-003, DES-005 | TEST-010, TEST-011, TEST-012, TEST-013 | RISK-002, RISK-007 | Draft |
| REQ-005 | The system shall require surname and first/preferred-name compatibility for identifier and crosswalk matches. | Observed | BR-004 | DES-002, DES-003 | TEST-003, TEST-011, TEST-012 | RISK-002 | Draft |
| REQ-006 | The system shall provide accepted-match audit evidence for automated reconciliation without adding matching metadata to the Lunchtab import CSV. | Observed | BR-008 | DES-006, DES-010 | TEST-009, TEST-017 | RISK-004 | Draft |
| REQ-007 | The system shall provide reconciliation audit-control totals that prove valid Odin dollars equal matched dollars plus valid exception dollars. | Observed | BR-007 | DES-006 | TEST-005 | RISK-004, RISK-005 | Draft |
| REQ-008 | The system shall create manual-review exception and candidate-match artifacts for unresolved reconciliation cases. | Observed | BR-003, BR-009 | DES-004, DES-007 | TEST-014, TEST-015, TEST-016 | RISK-003 | Draft |
| REQ-009 | The candidate viewer shall support filtering, ambiguity awareness, actionable selection, proposed transfer generation, and decision audit output while preserving the original transfer file. | Observed | BR-009, BR-010 | DES-007 | TEST-016 | RISK-003, RISK-006 | Draft |
| REQ-010 | The manual reconciliation review shall compare original and edited transfer files, classify edits by severity, and block invalid manual amounts. | Observed | BR-011 | DES-008 | TEST-006, TEST-007 | RISK-003, RISK-005 | Draft |
| REQ-011 | The InitialBalances workflow shall validate the reconciled transfer and target InitialBalances schema before writing a processed import. | Observed | BR-012, BR-013 | DES-009 | TEST-018, TEST-019 | RISK-005, RISK-006 | Draft |
| REQ-012 | The InitialBalances workflow shall aggregate populated `OdinBalanceAmount` values by case-sensitive `DefaultFamilyCode`, add them to target `Amount`, and preserve target rows. | Observed | BR-013, BR-014 | DES-009 | TEST-018 | RISK-001, RISK-005 | Draft |
| REQ-013 | The InitialBalances workflow shall omit the processed import when blocking exceptions exist while still writing audit evidence. | Observed | BR-015 | DES-009, DES-010 | TEST-019, TEST-020 | RISK-005, RISK-006 | Draft |
| REQ-014 | Managed desktop workflows shall publish completed run folders atomically after staging all outputs and manifests. | Observed | BR-016 | DES-010 | TEST-017, TEST-020, TEST-023 | RISK-006 | Draft |
| REQ-015 | Run manifests shall record filenames, hashes, summary counts, profile details where applicable, generated artifact hashes, and avoid absolute source paths or row-level private data. | Observed | BR-017 | DES-010 | TEST-017, TEST-020, TEST-023 | RISK-004, RISK-008 | Draft |
| REQ-016 | The desktop GUI shall enforce validation before processing and reset prior validation/results when inputs or profiles change. | Observed | BR-018 | DES-011 | TEST-021 | RISK-003, RISK-006 | Draft |
| REQ-017 | The application shall decode supported CSV encodings safely and reject unsupported, ambiguous, or binary-looking content. | Observed | BR-019 | DES-012 | TEST-022 | RISK-008 | Draft |
| REQ-018 | The sandbox generator shall create deterministic synthetic data packs and verify production reconciliation and InitialBalances workflows. | Observed | BR-020 | DES-013 | TEST-023 | RISK-009 | Draft |
| REQ-019 | Windows packaging shall support a per-user installer, Start Menu entries, uninstall support, and release checks. | Observed | BR-021 | DES-014 | TEST-024 | RISK-010 | Draft |

## Business Rule Trace

| Rule ID | Rule Statement | Evidence | Enforcement Point | Related Requirements | Evidence Strength |
| --- | --- | --- | --- | --- | --- |
| BR-001 | Source files are selected as inputs and are not changed, moved, or deleted by the normal workflow. | `README.md`; `run_workflow`; `run_managed_workflow` writes to output/staging directories. | `src/odin_lunchtab/workflow.py`; `src/odin_lunchtab/managed.py` | REQ-001 | Strong |
| BR-002 | Transfer output preserves Lunchtab headers and inserts `OdinBalanceAmount` after `DefaultFamilyBalanceAmount`. | `workflow.py` builds `final_headers` using the position of `DefaultFamilyBalanceAmount`. | `run_workflow` | REQ-002 | Strong |
| BR-003 | Non-safe reconciliation outcomes are reported as exceptions rather than applied to transfer rows. | README exception language; `match_balances_detailed` exception branches. | `workflow.py` | REQ-003, REQ-008 | Strong |
| BR-004 | Identifier and crosswalk matches require compatible names. | `names_compatible`; crosswalk and rule branches reject failed validation. | `workflow.py` | REQ-003, REQ-005 | Strong |
| BR-005 | Duplicate Odin identities and multiple Odin records targeting one Lunchtab user are quarantined. | `odin_id_counts`; `target_counts`. | `workflow.py` | REQ-003 | Strong |
| BR-006 | Profiles support approved target fields, transforms, email-domain filters, scoped rules, crosswalks, and protected legacy default behavior. | `MatchingRule`, `TransformStep`, `CrosswalkEntry`, `MatchingProfile`, `LEGACY_DEFAULT_PROFILE`. | `profiles.py`; `workflow.py`; `profile_gui.py` | REQ-004 | Strong |
| BR-007 | Reconciliation control totals must pass before workflow completion. | `write_reconciliation_audit_control` status checked for `PASS`. | `workflow.py`; `audit_control.py` | REQ-007 | Strong |
| BR-008 | Matching metadata belongs in audit outputs, not the upload CSV. | README; accepted match audit headers; transfer schema test. | `workflow.py` | REQ-006 | Strong |
| BR-009 | Candidate reports are advisory and ranked by evidence; actionable candidates require unique transfer trace and blank current balance. | `exception_candidates.py`; `candidate_viewer.py`. | Candidate report and viewer services | REQ-008, REQ-009 | Strong |
| BR-010 | Proposed transfer creation from candidate selections writes a copy and audit; it does not mutate the original transfer. | `write_proposed_transfer_from_selections`. | `candidate_viewer.py` | REQ-009 | Strong |
| BR-011 | Manual reconciliation review distinguishes normal manual resolutions from risky or blocking edits. | Severity classification in `manual_reconciliation.py`. | `audit_manual_reconciliation` | REQ-010 | Strong |
| BR-012 | InitialBalances input must be exactly `FamilyName,FamilyCode,Amount`; reconciled transfer must include `DefaultFamilyCode` and `OdinBalanceAmount`. | `INITIAL_BALANCE_HEADERS`; `TRANSFER_HEADERS`. | `inspect_initial_balances_inputs` | REQ-011 | Strong |
| BR-013 | Populated transfer balances are aggregated by trimmed, case-sensitive family code. | `amounts_by_code`; `target_indexes`; README count definitions. | `_analyze_initial_balances` | REQ-012 | Strong |
| BR-014 | Blank InitialBalances `Amount` values are treated as zero; invalid target amounts block affected rows. | `_decimal(blank_as_zero=True)`; exception path for invalid target amount. | `_analyze_initial_balances` | REQ-012, REQ-013 | Strong |
| BR-015 | A blocked InitialBalances run writes audit, exception, control, summary, and manifest evidence but omits the processed import. | `processed = None` when blocked. | `process_initial_balances`; `run_initial_balances_workflow` | REQ-013 | Strong |
| BR-016 | Managed workflows publish output only after staging succeeds, and staging is removed after failure. | Staging directory creation, rename, and exception cleanup. | `managed.py`; `manual_reconciliation.py`; `initial_balances.py` | REQ-014 | Strong |
| BR-017 | Manifests use filenames and hashes, not absolute input paths or row-level data. | Manifest builders; README privacy statement. | `managed.py`; `manual_reconciliation.py`; `initial_balances.py` | REQ-015 | Strong |
| BR-018 | GUI state must require validation before processing and invalidate stale validation when inputs/profile change. | Controller state transitions. | `gui_controller.py` | REQ-016 | Strong |
| BR-019 | CSV decoding accepts UTF-8, Windows-1252, and BOM-marked UTF-16; unsafe text is rejected. | `_decode_csv_bytes`; `_validate_csv_text`. | `workflow.py` | REQ-017 | Strong |
| BR-020 | Sandbox data must be deterministic and must verify against production workflows. | Sandbox README and tests. | `sandbox_data.py`; `sandbox_gui.py` | REQ-018 | Strong |
| BR-021 | Windows installer supports per-user install and uninstall behavior. | README release guidance; packaging tests. | `packaging/installer.iss`; `scripts/build-release.ps1` | REQ-019 | Moderate |

## Design Element Trace

| Design ID | Design Element | Design Purpose | Evidence | Related Requirements | Evidence Strength |
| --- | --- | --- | --- | --- | --- |
| DES-001 | Transfer CSV generation with inserted `OdinBalanceAmount`. | Produce Lunchtab-compatible copy carrying Odin balances. | `workflow.py` output path and header construction. | REQ-001, REQ-002 | Strong |
| DES-002 | Name normalization and compatibility functions. | Reduce false positives while allowing preferred names, initials, accents, and punctuation variance. | `normalize_name`, `first_names_compatible`, `names_compatible`. | REQ-003, REQ-005 | Strong |
| DES-003 | Profile-driven matching engine. | Support venue-specific matching without code changes. | `profiles.py`; `match_balances_detailed`. | REQ-003, REQ-004, REQ-005 | Strong |
| DES-004 | Exception and manual-review report partitioning. | Route unresolved and high-risk cases to operational review. | `EXCEPTION_HEADERS`; `MANUAL_REVIEW_EXCEPTIONS_OUTPUT_NAME`. | REQ-003, REQ-008 | Strong |
| DES-005 | Profile editor and preview model. | Let operators configure and compare profile effects before processing. | `preview_profile`; `profile_gui.py`; tests. | REQ-004, REQ-016 | Moderate |
| DES-006 | Audit-control summaries. | Provide control-total traceability for financial reconciliation. | `audit_control.py`; `run_reports.py`. | REQ-006, REQ-007, REQ-013 | Strong |
| DES-007 | Candidate review services and viewer state. | Support guided manual resolution of exception accounts. | `exception_candidates.py`; `candidate_viewer.py`; `candidate_viewer_gui.py`. | REQ-008, REQ-009 | Strong |
| DES-008 | Manual reconciliation delta audit. | Detect whether staff edits are normal, risky, or blocking before InitialBalances. | `manual_reconciliation.py`. | REQ-010 | Strong |
| DES-009 | InitialBalances preflight and processor. | Validate, aggregate, block, audit, and produce final import. | `initial_balances.py`. | REQ-011, REQ-012, REQ-013 | Strong |
| DES-010 | Managed staging, timestamped run folders, manifests, and hashes. | Protect output integrity and support auditability. | `managed.py`; manifest builders in workflow modules. | REQ-001, REQ-014, REQ-015 | Strong |
| DES-011 | GUI controllers with explicit workflow phases. | Prevent invalid operations and stale results in desktop tabs. | `gui_controller.py`. | REQ-016 | Strong |
| DES-012 | Shared CSV reader with encoding metadata. | Make ingestion safer across Windows/Excel exports. | `read_csv_with_metadata`; `_decode_csv_bytes`. | REQ-017 | Strong |
| DES-013 | Sandbox data generator and verifier. | Provide synthetic test packs for non-live validation. | `sandbox_data.py`; `sandbox_gui.py`. | REQ-018 | Strong |
| DES-014 | Windows packaging and release scripts. | Distribute the app without requiring Python or admin install. | `packaging/installer.iss`; `scripts/build-release.ps1`; README. | REQ-019 | Moderate |

## Verification Trace

| Test ID | Verification Evidence | Protects | Notes |
| --- | --- | --- | --- |
| TEST-001 | `tests/test_managed.py::test_inspect_inputs_reports_counts` | REQ-001, REQ-016 | Validates input inspection and counts. |
| TEST-002 | `tests/test_workflow.py::test_end_to_end_writes_expected_files_columns_and_rows` | REQ-001, REQ-002, REQ-006 | Confirms key output files, columns, and rows. |
| TEST-003 | `tests/test_workflow.py::test_quarantines_conflicts_ambiguous_names_and_unmatched_records` | REQ-003, REQ-005 | Confirms ambiguous and unmatched paths. |
| TEST-004 | `tests/test_workflow.py::test_quarantines_duplicate_odin_ids` and `test_quarantines_multiple_odin_records_targeting_one_lunchtab_user` | REQ-003 | Confirms duplicate safety behavior. |
| TEST-005 | `tests/test_workflow.py::test_reconciliation_audit_control_reconciles_matched_exceptions_and_malformed` | REQ-007 | Confirms control totals and operator summary. |
| TEST-006 | `tests/test_manual_reconciliation.py::test_audit_records_manual_resolutions_without_flagging_unchanged_matches` | REQ-010 | Confirms normal manual-resolution classification. |
| TEST-007 | `tests/test_manual_reconciliation.py::test_audit_flags_risky_balance_family_and_identity_edits` and `test_audit_blocks_invalid_manual_amount` | REQ-010 | Confirms high-risk and blocking classifications. |
| TEST-008 | `tests/test_manual_reconciliation.py::test_audit_rejects_structural_mismatches` | REQ-010 | Confirms edited transfer structure must match. |
| TEST-009 | `tests/test_matching_profiles.py::test_workflow_writes_match_audit_without_changing_transfer_schema` | REQ-002, REQ-006 | Confirms metadata separation. |
| TEST-010 | `tests/test_matching_profiles.py::test_custom_rule_supports_arbitrary_mixed_identifier_and_external_id` | REQ-004 | Confirms non-barcode identifier support. |
| TEST-011 | `tests/test_matching_profiles.py::test_crosswalk_has_precedence_and_does_not_fall_through_when_stale` and `test_name_validation_is_mandatory_for_rules_and_crosswalks` | REQ-003, REQ-004, REQ-005 | Confirms crosswalk and name-validation controls. |
| TEST-012 | `tests/test_matching_profiles.py::test_email_username_matching_is_case_insensitive_and_preserves_plus_tag` and domain/malformed email tests | REQ-004, REQ-005 | Confirms email username semantics. |
| TEST-013 | `tests/test_profiles.py` profile storage, validation, migration, protection, and crosswalk tests | REQ-004 | Confirms profile lifecycle behavior. |
| TEST-014 | `tests/test_exception_candidates.py::test_candidate_report_ranks_preferred_name_and_identifier_evidence` | REQ-008 | Confirms candidate ranking evidence. |
| TEST-015 | `tests/test_exception_candidates.py::test_candidate_report_traces_candidates_to_transfer_rows` | REQ-008 | Confirms candidate transfer trace fields. |
| TEST-016 | `tests/test_candidate_viewer.py` candidate viewer filtering, grouping, selection, proposed transfer, and decision audit tests | REQ-009 | Confirms candidate review workflow behavior. |
| TEST-017 | `tests/test_managed.py::test_managed_run_publishes_complete_folder_and_private_manifest` | REQ-014, REQ-015 | Confirms managed publication and manifest privacy. |
| TEST-018 | `tests/test_initial_balances.py::test_process_aggregates_adds_and_preserves_target_rows` | REQ-011, REQ-012 | Confirms aggregation, row preservation, and audit totals. |
| TEST-019 | `tests/test_initial_balances.py::test_process_blocks_import_and_writes_exception_reports` | REQ-011, REQ-013 | Confirms blocked-run output behavior. |
| TEST-020 | `tests/test_initial_balances.py::test_managed_run_publishes_clean_or_blocked_run_atomically` | REQ-013, REQ-014, REQ-015 | Confirms clean and blocked managed publication. |
| TEST-021 | `tests/test_gui_controller.py` controller validation, invalidation, and phase tests | REQ-016 | Confirms workflow gating. |
| TEST-022 | `tests/test_workflow.py::test_read_csv_accepts_supported_encodings` and `test_read_csv_rejects_unsafe_or_unsupported_content` | REQ-017 | Confirms CSV encoding behavior. |
| TEST-023 | `tests/test_sandbox_data.py` deterministic generation, presets, manifests, and production workflow round trips | REQ-018 | Confirms synthetic test-pack behavior. |
| TEST-024 | `tests/test_packaging.py` installer and release-builder tests | REQ-019 | Confirms packaging checks at repository level. |

## Risk Trace

| Risk ID | Risk Statement | Related Requirements | Current Mitigations | Evidence Quality | Validation Need |
| --- | --- | --- | --- | --- | --- |
| RISK-001 | A balance could be applied to the wrong Lunchtab row or family. | REQ-001, REQ-002, REQ-012 | Name validation, duplicate quarantine, transfer row preservation, InitialBalances family audit. | Observed | Confirm residual risk acceptance. |
| RISK-002 | Venue-specific identifier differences could produce false matches or excessive exceptions. | REQ-003, REQ-004, REQ-005 | Matching profiles, transforms, crosswalks, preview, mandatory name validation. | Observed | Confirm profile ownership and approval process. |
| RISK-003 | Manual review could introduce incorrect or unaudited changes. | REQ-003, REQ-008, REQ-009, REQ-010, REQ-016 | Candidate audit, proposed transfer copy, manual reconciliation delta audit, GUI state gates. | Observed | Confirm manual approval workflow. |
| RISK-004 | Audit evidence may be insufficient for financial or operational review. | REQ-006, REQ-007, REQ-015 | Accepted-match audit, audit-control summaries, run summaries, manifests, hashes. | Observed | Confirm audit evidence expectations. |
| RISK-005 | Financial totals could fail to reconcile across source, exceptions, and import files. | REQ-007, REQ-010, REQ-011, REQ-012, REQ-013 | Reconciliation and InitialBalances control totals; blocked invalid/manual amounts. | Observed | Confirm control-total review ownership. |
| RISK-006 | Partial or stale outputs could be used by operators. | REQ-001, REQ-009, REQ-013, REQ-014, REQ-016 | Staging folders, timestamped run folders, original-file preservation, controller invalidation. | Observed | Confirm output retention and naming policy. |
| RISK-007 | Profile changes could alter matching behavior without business approval. | REQ-004 | Protected Legacy Default, import/export, validation, preview comparison. | Observed | Define profile change control. |
| RISK-008 | Source data privacy could be weakened by logs, manifests, or encoding failures. | REQ-015, REQ-017 | Manifests use names/hashes/counts; logs are operational; unsafe CSV content rejected. | Observed | Validate against data-handling policy. |
| RISK-009 | Synthetic testing could miss real operational edge cases. | REQ-018 | Multiple deterministic presets and production workflow verification. | Observed | Compare presets to known historical exceptions. |
| RISK-010 | Release packaging could fail in clean operator environments. | REQ-019 | Release script, installer configuration, packaging tests, README checklist. | Moderate | Capture install/upgrade/uninstall acceptance evidence. |

## Traceability

- REQ-001 through REQ-003 form the primary reconciliation safety chain: source input protection, transfer output preservation, and exception quarantine.
- REQ-004 through REQ-006 form the matching-governance chain: configurable matching, mandatory name validation, and metadata separation.
- REQ-007, REQ-014, and REQ-015 form the auditability chain: control totals, staged publication, manifests, and artifact hashes.
- REQ-008 through REQ-010 form the manual-resolution chain: candidate recommendations, selection audit, and edited-transfer audit.
- REQ-011 through REQ-013 form the InitialBalances import-control chain: schema validation, aggregation, and blocked-run evidence.
- REQ-016 through REQ-019 form the operational enablement chain: desktop state control, robust CSV ingestion, sandbox validation, and Windows packaging.

## Validation Needs

| Validation ID | Item Needing Validation | Why It Matters | Suggested Validation Owner | Current Status |
| --- | --- | --- | --- | --- |
| VAL-001 | Whether all listed requirements are business-approved, not just implementation-observed. | Code proves behavior, not stakeholder approval. | Product owner or operations lead | Unknown |
| VAL-002 | Whether `no Lunchtab match` should continue to be excluded from manual-review exceptions. | This shapes staff workload and unresolved-account handling. | Operations lead | Observed behavior, business approval unknown |
| VAL-003 | Whether candidate score thresholds and evidence weights match staff confidence expectations. | Candidate ranking affects manual review prioritization. | Reconciliation staff lead | Inferred intent |
| VAL-004 | Whether blocked InitialBalances runs should always omit processed import even for partial safe rows. | This is a strong safety posture with operational tradeoffs. | Finance/operations approver | Observed behavior, business approval unknown |
| VAL-005 | Whether manifest privacy controls satisfy internal data-handling policy. | Manifests include hashes and filenames but not row-level details. | Data owner or compliance reviewer | Unknown |
| VAL-006 | Whether Windows packaging requirements include formal install/upgrade/uninstall acceptance evidence beyond current tests. | Packaging tests inspect files but do not prove clean-machine install behavior. | Release owner | Unknown |
