feat: establish auth listing and image vertical slices

Includes MFA-capable authentication, session and CSRF security, password recovery, listing lifecycle and ownership rules, inventory image metadata, local ImageStorage, migrations, tests, and implementation status documentation. Verification: npm test (62 passing) and integration suite (14 passing).
This commit is contained in:
2026-09-08 17:32:03 -04:00
commit c728016dec
128 changed files with 9788 additions and 0 deletions
+176
View File
@@ -0,0 +1,176 @@
# Functional Requirements
## Public
### Homepage
- Minimal, search-first landing page.
- Search updates as the visitor types.
- Recently added available items appear below search.
- No-match state: `No relevant matches found.`
### Search
Search may include product name, Pokémon name, set, card number, category, description, event, year, brand, and tags.
Public search must use the same underlying search abstraction as admin search while respecting public visibility.
### Inventory
Filters include status, newly added, category, set, condition, price range, and event. Available filter values are derived from current data where appropriate.
Sorting includes:
- Recently Added
- Recently Updated
- Name A–Z
- Name Z–A
- Price Low→High
- Price High→Low
- Market Value Low→High
- Market Value High→Low
Sold is hidden by default but can be included through an explicit public filter/search.
Pending listings are public and clearly marked.
### Item details
Show images, title, product details, condition, asking price, market value where available, market update time, seller description, and configured seller contact methods.
Public pages have stable, shareable URLs.
## Inventory creation
Guided flow:
`Find/Create Product → Link Market Sources → Inventory Details → Images → Pricing → Review → List`
Required for an item to become Available:
- Product name
- Category
- Asking price
- Images
- Physical inventory record
- Condition
Provider matching is not mandatory.
### Existing Product
Admin can add another physical copy, reuse prior item data as a starting point, or create a new physical record after a previous copy sold.
### Provider matching
When creating a new Product, the system searches applicable configured providers and presents candidate matches. Admin can refine/search manually and confirm a mapping.
Mappings belong to Products and are reused by physical copies.
A provider may be marked Not Applicable. A Product may exist without any provider mapping.
## Inventory lifecycle
Inventory status:
- `ACTIVE`
- `SOLD`
- `ARCHIVED`
Listing status:
- `DRAFT`
- `AVAILABLE`
- `PENDING`
- `CLOSED`
- `ARCHIVED`
Owned items may have no active listing and may be designated for sale, personal collection, display, or other purposes.
Pending and sold items are locked against ordinary edits. Controlled corrections remain possible with audit history.
Relisting creates a new physical Inventory Item rather than reopening the sold physical record.
## Conditions
Card profile:
- NM
- LP
- MP
- HP
- Damaged
Merchandise profile:
- New
- Like New
- Used
- Damaged
Profiles and labels are configurable.
## Pricing
- Multiple providers supported.
- Median is the default valuation strategy.
- Outliers are retained and flagged.
- One valid source may produce a low-confidence value.
- Manual market-value overrides require a private reason.
- Provider errors are retained for admin visibility.
- Public sees only calculated/overridden market value, not source-level observations.
- Canonical currency is USD.
- Condition-specific values are used only when reliable data exists.
- No fabricated values.
- Pricing can refresh by item, Product, or bulk.
- Bulk refresh is asynchronous.
## Images
- Multiple images per physical item.
- Multiple-file upload and drag/drop.
- Reorder, primary selection, deletion, and later additions.
- Configurable image count limit.
- Automatic validation and optimization.
- Original retained where practical.
- Responsive derivatives generated.
- Seller can edit generated alt-text suggestions.
## Acquisition
Private acquisition information includes cost, date, source, location, shipping, tax, fees, trade value, and notes.
Total cost basis is calculated from component costs.
## Sales
Record Sale requires sold price and supports date, location/platform, fees, shipping, taxes, buyer information, and notes.
Multiple inventory items may belong to one sale.
Sale correction/undo is controlled and audited.
## Bulk operations
Supported:
- status change
- archive
- pricing refresh
- tags
Mark Sold uses the dedicated sale workflow and cannot bypass sold-price validation.
## Dashboard
Dashboard should meaningfully present:
- inventory count
- available listings
- sold count
- total acquisition cost
- total asking value
- total market value
- potential profit
- recently added items
- stale pricing
- missing images
- missing pricing
- provider errors
- recent activity
Actionable alerts link to filtered management views.
## Exports
Admin-only CSV, Excel, and JSON exports. Large exports may run asynchronously.
## Settings
General, inventory, pricing, and security settings are configurable as described in the supporting documentation.