Skip to content

Feature Specification

Purpose

A feature spec is the feature-level authority for behavior and boundaries. It translates PRD requirements into precise feature behavior, functional areas, non-functional expectations, edge cases, and feature-specific success measures. Acceptance criteria belong to user stories (ADR-009) and are not defined here.

It sits between the PRD (which defines product scope) and user stories (which define vertical slices through the feature). The feature spec owns feature behavior. User stories own user journeys. Solution and technical designs own how the behavior will be built.

Authoring guidance

  • Future state before current pain — describe the desired user-visible outcome before optimizing around today’s broken surface. The problem statement explains why the change is needed; it should not be the only organizing frame.
  • Scope, not solution — describe what the feature must do, not how to build it. Implementation details belong in design docs.
  • Behavior, not journey — specify feature behavior and boundaries. Put end-to-end user flow narrative and acceptance criteria in user stories.
  • One feature, one capability — a feature spec covers exactly one capability (≈ one PRD subsystem). If it covers two, split it; apply the Decomposition test below to decide. A functional area is a sub-part of one capability, not a second capability.
  • Functional areas before requirements — when a feature spans multiple surfaces, stages, or domain objects within the one capability, name those

Additional guidance continues in the full prompt below.

Quality checklist from the prompt

After drafting, verify every item. If any blocking check fails, revise before committing.

Blocking

  • Overview links to a specific PRD requirement
  • Ideal Future State is present for broad product-surface, workflow, IA, or documentation features
  • Functional Areas is present when the feature spans multiple surfaces, workflows, user modes, or domain objects
  • Similar domain objects are separated before requirements are written
  • Functional requirements are grouped by area when a flat list would mix unrelated scopes
  • Every functional requirement is testable
  • Non-functional requirements have specific numeric targets
  • User stories are referenced by ID (not duplicated inline)
  • Dependencies name specific feature IDs and external systems
  • Exact API/CLI/event/schema/config/telemetry/adapter surface is linked to a Contract, not defined inline
  • No [NEEDS CLARIFICATION] markers remain

Warning

  • Problem statement quantifies the pain
  • At least one feature-level edge case documented
  • Success metrics are feature-specific (not product-level)
  • Out of scope excludes something plausible

Example

Show a worked example of this artifact
---
ddx:
  id: example.feature-specification.depositmatch.csv-import
  depends_on:
    - example.product-vision.depositmatch
    - example.prd.depositmatch
    - example.principles.depositmatch
    - example.concerns.depositmatch
  review:
    self_hash: d85530eb091209cf9989c9cac3bc1f1063358a5b79964ca0e5e7a384fa77c44a
    deps:
      example.concerns.depositmatch: 34738dd02d95489bcc3c00b5be15b630ae9fb15ab4f99f45d0ec1ecd1d3f1c6e
      example.prd.depositmatch: c9c24e1694af4548a6deaad8d92059e365da110148bd9adc44d8640dff9770a4
      example.principles.depositmatch: bb37a1addd5c152f068dd5c416b6a4ae217847242d0d1b7f9e64406b671de0ed
      example.product-vision.depositmatch: 8abbb2fcb552b536f07829f57d91ef3ae8dbf52a6066955222e83d196b59b5ae
    reviewed_at: "2026-05-15T04:11:24Z"
---

# Feature Specification: FEAT-001 - CSV Import and Column Mapping

**Feature ID**: FEAT-001
**Status**: Specified
**Priority**: P0
**Owner**: Product and Engineering

## Overview

CSV Import and Column Mapping implements the PRD requirement to import bank
deposit CSV files and invoice export CSV files for a client. The feature gives
reviewers a dependable way to bring source data into DepositMatch while
preserving the source-row identity needed for matching evidence and audit logs.

## Ideal Future State

Maya uploads bank and invoice exports for a client, confirms the saved column
mapping, and sees a clean import summary before matching begins. If a file is
ambiguous or missing required columns, DepositMatch explains the issue before
any rows enter the review queue. Source rows remain traceable through matching,
exceptions, reports, and corrections.

## Problem Statement

- **Current situation**: Reviewers reconcile deposits from bank exports,
  invoice exports, spreadsheets, and email notes.
- **Pain points**: CSV layouts differ by client and system. A silent mapping
  error can make match suggestions look plausible while pointing to the wrong
  source row.
- **Desired outcome**: Reviewers can import valid files quickly and trust that
  invalid files stop before they pollute the matching workflow.

## Functional Areas

| Area | User question or job | Feature responsibility |
|------|----------------------|------------------------|
| Upload | Can I provide the bank and invoice files for this client? | Accept CSV files and associate them with one client and import session. |
| Mapping | Does DepositMatch understand the columns in these files? | Require mappings for amount, date, identifier, and source-specific optional fields. |
| Validation | Are these files safe to import? | Detect missing columns, duplicate source identifiers, malformed dates, and invalid amounts before import. |
| Import Summary | What happened during import? | Show accepted rows, rejected rows, warnings, and saved mappings. |
| Traceability | Can every later match point back to source data? | Preserve file identity, row number, source identifier, and normalized values. |

## Requirements

### Functional Requirements by Area

#### Upload

UP-01. The system must accept one bank deposit CSV and one invoice export CSV
for a selected client and import session.

UP-02. The system must reject non-CSV files before parsing.

#### Mapping

MAP-01. The system must require mappings for amount, date, and source
identifier in both bank and invoice files.

MAP-02. The system must save a confirmed mapping for reuse on the next import
for the same client and source type.

MAP-03. The system must let the reviewer adjust a saved mapping before rows
are imported.

#### Validation

VAL-01. The system must reject an import when required mapped columns are
missing from either file.

VAL-02. The system must reject rows with invalid amounts, invalid dates, or
duplicate source identifiers within the same file.

VAL-03. The system must show rejected rows with the source row number and a
plain-language reason.

#### Import Summary

SUM-01. The system must show accepted row count, rejected row count, warning
count, and saved mapping status before the reviewer proceeds to matching.

SUM-02. The system must not create match suggestions until the reviewer
confirms the import summary.

#### Traceability

TRC-01. The system must preserve source file name, import session, row number,
source identifier, normalized amount, and normalized date for every accepted
deposit and invoice row.

TRC-02. The system must make preserved source-row fields available to match
evidence, exception records, and reconciliation exports.

### Acceptance Criteria

| Requirement | Scenario | Given | When | Then |
|-------------|----------|-------|------|------|
| UP-01 | Valid bank and invoice exports | Maya selected Acme Dental and chose two valid CSV files | She uploads both files | DepositMatch opens mapping review for the import session |
| MAP-02 | Reused client mapping | Acme Dental has a saved bank mapping | Maya uploads the same source type next week | The saved mapping is preselected and editable before import |
| VAL-01 | Missing required column | The invoice file lacks a mapped amount column | Maya confirms the mapping | The import is rejected before rows are accepted |
| VAL-03 | Row-level validation error | A bank row has `12OO.00` in the amount column | Maya validates the file | The row is rejected with its source row number and reason |
| SUM-02 | Reviewer has not confirmed summary | Validation completed with accepted and rejected rows | Matching would otherwise begin | No match suggestions are created until Maya confirms the summary |
| TRC-02 | Accepted row appears in evidence | A deposit row was accepted during import | Maya later reviews a suggested match | Match evidence includes the source file, row number, amount, date, and identifier |

### Non-Functional Requirements

- **Performance**: Validate and summarize files totaling 10,000 rows in under
  5 seconds on the supported production environment.
- **Security**: Do not send raw financial row values to analytics or logging
  systems.
- **Reliability**: Import confirmation must be atomic; either all accepted rows
  for the session are recorded with traceability fields or none are.
- **Usability**: All validation errors must identify the file, row number, and
  field in plain language.

## User Stories

- [US-001 - Upload CSV files for a client](../user-stories/US-001-upload-csv-files.md)
- [US-002 - Confirm or adjust column mappings](../user-stories/US-002-confirm-column-mappings.md)
- [US-003 - Review import validation results](../user-stories/US-003-review-import-validation.md)

## Edge Cases and Error Handling

- **Duplicate source identifiers**: Reject duplicate identifiers within the
  same file and show each duplicate row.
- **Locale-specific amounts**: Reject ambiguous amount formats unless the
  mapping defines the decimal and thousands separators.
- **Partial upload**: If only one file is uploaded, keep the import session in
  draft and do not validate matching readiness.
- **Saved mapping drift**: If a saved mapping references a missing column,
  require the reviewer to repair the mapping before import.

## Success Metrics

- 95% of valid pilot-firm CSV import sessions reach the import summary without
  support intervention.
- 100% of accepted rows used in match evidence include file name, row number,
  source identifier, amount, and date.
- Fewer than 1% of import sessions require mapping correction after reviewer
  confirmation.

## Constraints and Assumptions

- CSV import is the only v1 ingestion path.
- Pilot firms can provide sample bank and invoice exports before launch.
- Source files may contain customer financial data and must follow the
  `financial-data-security` concern.

## Dependencies

- **Other features**: FEAT-002 Match Suggestion Review depends on accepted
  deposits and invoices from this feature.
- **External services**: None for v1.
- **PRD requirements**: P0-1 import CSV files; P0-4 preserve match evidence;
  P0-5 create exceptions for unmatched deposits.

## Out of Scope

- Bank feed integration.
- Accounting platform API sync.
- Automatic correction of malformed CSV values.
- Matching deposits to invoices before the reviewer confirms import summary.

Reference

ActivityFrame — Define what the system should do, for whom, and how success will be measured.
Default locationdocs/helix/01-frame/features/
RequiresNone
EnablesNone
InformsUser Stories
Solution Design
Contract
Test Plan
HELIX documentsdocs/helix/01-frame/features/FEAT-013-runtime-install-coverage.md
Generation prompt
Show the full generation prompt
# Feature Specification Generation Prompt

Create a feature specification that is precise enough to support design,
user story creation, and test planning. The feature spec owns FR-IDs,
functional areas, and the decomposition test — acceptance criteria live in
user-stories (see ADR-009) and must not be restated here.

## Storage Location

Store at: `docs/helix/01-frame/features/FEAT-NNN-<name>.md`

## Purpose

A feature spec is the **feature-level authority for behavior and boundaries**.
It translates PRD requirements into precise feature behavior, functional areas,
non-functional expectations, edge cases, and feature-specific success measures.
Acceptance criteria belong to user stories (ADR-009) and are not defined here.

It sits between the PRD (which defines product scope) and user stories (which
define vertical slices through the feature). The feature spec owns feature
behavior. User stories own user journeys. Solution and technical designs own
how the behavior will be built.

## Reference Anchors

Use these local resource summaries as grounding:

- `docs/resources/ibm-requirements-management.md` grounds traceable,
  prioritized, verifiable requirements.
- `docs/resources/cucumber-executable-specifications.md` grounds concrete
  examples as readable acceptance specifications without prescribing
  implementation or tooling.

## Active Concerns

For each concern selected in `docs/helix/01-frame/concerns.md`, apply its declared
`## Artifact Impact` (from `workflows/concerns/<name>/concern.md`) to THIS feature spec — realize the
FEAT-level obligations it names (usage-metering -> which actions are billable; multi-tenancy -> tenant-scoped ACs). A selected concern whose Artifact Impact names FEAT
but leaves no trace here is drift (reconcile-alignment Concern->Artifact Realization check).

## Key Principles

- **Future state before current pain** — describe the desired user-visible
  outcome before optimizing around today's broken surface. The problem statement
  explains why the change is needed; it should not be the only organizing frame.
- **Scope, not solution** — describe what the feature must do, not how to
  build it. Implementation details belong in design docs.
- **Behavior, not journey** — specify feature behavior and boundaries.
  Put end-to-end user flow narrative and acceptance criteria in user stories.
- **One feature, one capability** — a feature spec covers exactly one capability
  (≈ one PRD subsystem). If it covers two, split it; apply the Decomposition test
  below to decide. A functional *area* is a sub-part of one capability, not a
  second capability.
- **Functional areas before requirements** — when a feature spans multiple
  surfaces, stages, or domain objects *within the one capability*, name those
  areas before writing requirements and group requirements by area instead of
  producing one flat list. (Areas are subordinate parts of one capability — if an
  "area" would pass the Decomposition test as its own capability, it is a separate
  feature, not an area.)
- **Separate similar domain objects** — if readers might confuse two things,
  define them separately before requirements. For example, "Artifacts" are
  project-specific instances; "Artifact Types" are reusable methodology
  definitions.
- **Stories by reference** — list user story IDs, don't duplicate story
  content. Stories are separate files with their own lifecycle.
- **Testable requirements** — every functional requirement should be
  verifiable. If you can't describe how to test it, it's too vague.
- **Leave unknowns explicit** — use Open Questions at the bottom rather than
  inventing detail you don't have.

## Boundary Test

| If you are writing... | Put it in... |
|---|---|
| Product goals, personas, launch priority, or product-level metrics | PRD |
| Feature behavior, boundaries, and edge cases | Feature Specification |
| A vertical user journey through one or more feature requirements, with acceptance criteria | User Story |
| Exact API/CLI/event/schema surface, commands, flags, fields, payloads, status codes, error semantics, or compatibility rules | Contract |
| Feature-level technical approach, component choices, domain/data model, interface usage, or implementation approach | Solution/Technical Design |
| Detailed test cases, fixtures, or automation strategy | Test Plan or Story Test Plan |
| Build sequencing and work slices | Implementation Plan |

## Decomposition — is it a FEAT or a functional area?

The brief decomposes into features at one granularity: **one feature per
capability**, anchored to the PRD's `### Subsystem:` groupings (~one subsystem →
one `FEAT-NNN`). Use these **layered tests** to place a candidate:

1. **Primary — ship / cut / metric.** A candidate is its own **feature** if all
   hold:
   - **Ship/cut:** it could be removed or deferred **without making another
     *named* capability incoherent** (it stands alone in the parking-lot).
   - **Metric:** it carries its own **feature-level product/user outcome** as a
     success metric — not a local counter (a button click or a row count is not a
     feature metric).
   If a candidate fails these — it cannot stand alone and has no outcome of its
   own — it is a **functional area** within a feature, not a feature.
2. **Tie-breaker — bounded context.** When ship/cut is genuinely ambiguous, split
   on bounded context / aggregate root: one feature per bounded context; areas are
   views/stages over the *same* aggregate.

**Anchor:** the PRD names the subsystems; each maps to ~one feature. A
multi-subsystem brief that produces a single mega-feature, or that produces zero
feature specs (PRD → stories directly), has skipped this tier — reconcile-alignment
flags both. A deliberately cross-subsystem feature (the workflow that spans them
*is* the feature) is allowed, but must say so explicitly in the template's
**Cross-Subsystem Rationale** field (the "Covered PRD Subsystem(s)" /
"Covered PRD Requirements" fields hold the subsystem names and FR IDs).
## Section-by-Section Guidance

### Overview
Connect this feature to a specific PRD requirement. "This feature implements
PRD P0-3" is better than "This feature improves the user experience."

### Ideal Future State
Describe the target state in user-visible terms. A good future state answers:

- What can the user understand, decide, or accomplish?
- What does the product surface make clear?
- How should the feature feel when it is working well?

For IA, documentation, onboarding, workflow, or product-surface features, this
section is mandatory. It should lead the spec toward the desired experience,
not merely away from the current failure mode.

### Problem Statement
Same standard as the PRD: describe the failure mode, not the absence of your
feature. Quantify where possible. Keep it subordinate to the future state; do
not let the spec become a list of current complaints.

### Functional Areas
Use this section whenever a feature has more than one surface, stage, or domain
object **within its one capability**. The area map should make clear what belongs
where before requirements are written. Areas are *subordinate parts* of the
feature — each fails the Decomposition test on its own (it cannot ship/cut
independently and has no feature-level outcome of its own).

Examples (areas *inside one capability*):

- CSV lead import → field mapping, validation, duplicate handling, confirmation
- Template editor → block palette, variable insertion, live preview, save/version
- Campaign scheduler → recipient selection, send-time rules, blackout handling

**Caution:** lists of *roles* ("Admin, Operator, Auditor"), *lifecycle stages*
("Intake, Planning, Execution, Review"), or *distinct domain objects* ("Leads,
Lists, Segments", "API, CLI, docs") are usually **separate features**, not areas
of one — each typically passes the Decomposition test as its own capability.
Apply the test before treating them as areas.

### Functional Requirements
Number each requirement for traceability. Group requirements by functional
area when the feature spans multiple areas. Use stable prefixes that make the
scope clear (`NAV-01`, `TYPE-01`, `ART-01`) or use plain `FR-01` for narrow
single-area features.

Each requirement should be independently testable. These are what the feature
must do — user stories describe how users interact with these capabilities.
A feature spec may name a high-level interface dependency such as "depends on a
search API", but exact endpoints, commands, flags, payload fields, status codes,
error semantics, config keys, telemetry fields, event schemas, and adapter
signatures are normative surface and belong in a Contract.

If a requirement mentions two areas joined by "and", split it unless the
relationship between those areas is itself the requirement.

### Non-Functional Requirements
Every NFR needs a specific target. "Must be fast" is not a requirement.
"95th percentile response under 200ms" is. Only include NFRs relevant to
this specific feature, not product-wide NFRs from the PRD.

### User Stories
Reference by ID and title with a relative link. Do not duplicate story
content — the story file is the source of truth. If stories haven't been
written yet, list placeholders with `[TODO: create story]` and note it in
Open Questions.

### Edge Cases and Error Handling
Feature-level edge cases that span multiple stories. If an edge case is
specific to one story, it belongs in that story's file.

### Success Metrics
Feature-specific metrics, not product-level metrics from the PRD. How do
you know this specific feature is working as intended?

### Dependencies
Name specific feature IDs, external APIs, and PRD requirement numbers.
"Depends on auth" is too vague. "Depends on FEAT-002 (auth middleware)
and the OAuth2 provider API" is specific.

### Out of Scope
Each item should prevent a plausible scope question during implementation.
"Not a replacement for the database" is only useful if someone might think
it is.

## Quality Checklist

After drafting, verify every item. If any blocking check fails, revise before
committing.

### Blocking

- [ ] Overview links to a specific PRD requirement
- [ ] Ideal Future State is present for broad product-surface, workflow, IA, or documentation features
- [ ] Functional Areas is present when the feature spans multiple surfaces, workflows, user modes, or domain objects
- [ ] Similar domain objects are separated before requirements are written
- [ ] Functional requirements are grouped by area when a flat list would mix unrelated scopes
- [ ] Every functional requirement is testable
- [ ] Non-functional requirements have specific numeric targets
- [ ] User stories are referenced by ID (not duplicated inline)
- [ ] Dependencies name specific feature IDs and external systems
- [ ] Exact API/CLI/event/schema/config/telemetry/adapter surface is linked to a Contract, not defined inline
- [ ] No `[NEEDS CLARIFICATION]` markers remain

### Warning

- [ ] Problem statement quantifies the pain
- [ ] At least one feature-level edge case documented
- [ ] Success metrics are feature-specific (not product-level)
- [ ] Out of scope excludes something plausible
Template
Show the template structure
---
ddx:
  id: FEAT-XXX
---

# Feature Specification: FEAT-XXX — [Feature Name]

**Feature ID**: FEAT-XXX
**Status**: [Draft | Specified | Approved]
**Priority**: [P0 | P1 | P2]
**Owner**: [Team/Person]
**Covered PRD Subsystem(s)**: [Subsystem name(s) from the PRD — normally exactly one]
**Covered PRD Requirements**: [FR-n, FR-m — the PRD FRs this feature owns]
**Cross-Subsystem Rationale**: [None — single subsystem. | If more than one subsystem
is listed above: the rationale that the cross-subsystem workflow IS the feature;
otherwise split it per the Decomposition test.]
<!-- reconcile-alignment reads these three fields: a feature spanning >1 subsystem
with no Cross-Subsystem Rationale is a mega-FEAT finding. -->

## Overview

[What this feature is and why it exists. 2-3 sentences connecting this feature
to a specific PRD requirement.]

## Ideal Future State

[Describe the future product behavior once this feature is working well. Focus
on what users can understand, decide, or accomplish. For broad product-surface,
workflow, IA, or documentation features, this section should come before the
problem framing so requirements are pulled toward the desired outcome instead
of only reacting to current pain.]

## Problem Statement

- **Current situation**: [What exists now — be specific]
- **Pain points**: [What is not working and for whom]
- **Desired outcome**: [What success looks like — measurable]

## Functional Areas

[For features with more than one surface or stage **within this one capability**,
map the subordinate areas before writing requirements. Areas are parts of one
capability — each fails the ship/cut/metric test on its own. Lists of roles,
lifecycle stages, or distinct domain objects are usually *separate features*, not
areas (apply the Decomposition test). Omit when the feature is a single narrow
capability.]

| Area | User question or job | Feature responsibility |
|------|----------------------|------------------------|
| [Area] | [What the user needs to know or do] | [What this feature must provide] |

## Requirements

### Functional Requirements by Area

[Each requirement should be testable. Group requirements by functional area
when the feature has multiple areas. Use stable prefixes that make the scope
clear, such as `HOME-01`, `TYPE-01`, `NAV-01`, or `FR-01` for narrow features.
Name high-level interface dependencies when needed, but do not define exact
API/CLI/event/schema/config/telemetry/adapter surface here; link or request a
Contract for commands, flags, endpoints, fields, payloads, status codes, error
semantics, and compatibility rules.]

#### [Area Name]

[PREFIX-01]. [Requirement]
[PREFIX-02]. [Requirement]

### Non-Functional Requirements

- **Performance**: [Specific target, e.g., "95th percentile response < 200ms"]
- **Security**: [Specific requirement, not "must be secure"]
- **Scalability**: [Specific target, e.g., "handles 10k concurrent users"]
- **Reliability**: [Specific target, e.g., "99.9% uptime"]

## User Stories

[List the user stories that implement this feature. Each story is a separate
file in `docs/helix/01-frame/user-stories/`. Reference by ID — do not
duplicate story content here.]

- [US-XXX — Story title](../user-stories/US-XXX-slug.md)
- [US-XXX — Story title](../user-stories/US-XXX-slug.md)

## Edge Cases and Error Handling

[Feature-level edge cases that span multiple stories. Story-specific edge
cases belong in the story file.]

- **[Condition]**: [Expected behavior]

## Success Metrics

[How do we know this feature is working? Metrics specific to this feature,
not the product-level metrics from the PRD.]

- [Metric with target]

## Constraints and Assumptions

- [Constraint or assumption specific to this feature]

## Dependencies

- **Other features**: [FEAT-XXX if this feature depends on another]
- **External services**: [APIs, libraries, or systems this feature requires; exact surface lives in Contract artifacts]
- **PRD requirements**: [Which P0/P1/P2 requirements this addresses]

## Out of Scope

[What this feature explicitly does not cover. Each item should prevent a
plausible scope question.]

## Review Checklist

Use this checklist when reviewing a feature specification:

- [ ] Covered PRD Subsystem(s) and Requirements (`FR-n`) are listed; a feature spanning >1 subsystem carries an explicit cross-subsystem rationale (else split per the Decomposition test)
- [ ] Functional areas (if any) are subordinate parts of this one capability, not separate capabilities (each fails the ship/cut/metric test on its own)
- [ ] Overview connects this feature to a specific PRD requirement
- [ ] Ideal future state describes the desired user-visible outcome, not only current problems
- [ ] Problem statement describes what exists now and what is broken — not just what is wanted
- [ ] Functional areas are mapped when the feature spans multiple surfaces, workflows, or domain objects
- [ ] Requirements are grouped by functional area when a flat list would mix unrelated scopes
- [ ] Domain objects that sound similar are explicitly separated (for example, artifact instances vs artifact types)
- [ ] Every functional requirement is testable — you can write an assertion for it
- [ ] Acceptance criteria are defined in the user stories that decompose this feature, not here (ADR-009)
- [ ] Non-functional requirements have specific numeric targets, not "must be fast"
- [ ] Edge cases cover realistic failure scenarios, not just happy paths
- [ ] Success metrics are specific to this feature, not product-level metrics
- [ ] Dependencies reference real artifact IDs (FEAT-XXX, external APIs)
- [ ] Out of scope excludes things someone might reasonably assume are in scope
- [ ] No implementation details ("use X library", "create Y table") — specify WHAT not HOW
- [ ] No exact API/CLI/event/schema/config/telemetry/adapter surface is defined inline; normative surface links to Contract artifacts
- [ ] Feature is consistent with governing PRD requirements
- [ ] No `[NEEDS CLARIFICATION]` markers remain unresolved for P0 features