174 lines
8.5 KiB
Markdown
174 lines
8.5 KiB
Markdown
# Feature Specification: Public Grid Viewer + Live Selection (Vertical Slice)
|
||
|
||
**Feature Branch**: `001-public-grid-viewer`
|
||
**Created**: 2026-01-03
|
||
**Status**: Draft
|
||
**Input**: User description: "Feature 1: Public Grid Viewer + Live Selection (no checkout). Vertical slice: public master image + pan/zoom + canvas-based grid, selection, server-side price prop, stub availability, upload preview modal (no payment)."
|
||
|
||
## Constitution Alignment (REQUIRED)
|
||
This spec MUST comply with `constitution.md`. If not, document deviation + mitigation here.
|
||
|
||
### Mandatory Invariants
|
||
- [ ] Server computes price; client is display-only
|
||
- [ ] DB-level prevention of double booking
|
||
- [ ] Webhooks + rendering pipeline are idempotent
|
||
- [ ] Rendering occurs in queued job(s)
|
||
|
||
## Success Criteria (MUST)
|
||
Define measurable outcomes for "done".
|
||
- Performance:
|
||
- [ ] Public page loads master image + metadata within ___ ms on ___ connection
|
||
- Correctness:
|
||
- [ ] No double booking possible under concurrency
|
||
- [ ] Paid orders render exactly once (idempotent)
|
||
- UX:
|
||
- [ ] User can select cells, preview, and pay end-to-end
|
||
- Security:
|
||
- [ ] Upload rules enforced (type/size/dimensions), safe link validation
|
||
|
||
## Acceptance Scenarios (MUST)
|
||
Write at least 3 end-to-end scenarios (Gherkin-style preferred).
|
||
|
||
### Scenario 1: Reserve → Pay → Render
|
||
Given the public page is loaded with the master image and grid
|
||
When a visitor drags a rectangular selection over the grid and opens the sidebar
|
||
Then the UI shows the selected cell count and the server-provided `price_per_cell` and computes the total price (display only)
|
||
|
||
### Scenario 2: Concurrent selection conflict
|
||
Given two visitors load the same public page
|
||
When Visitor A selects a block of cells and Visitor B selects an overlapping block
|
||
Then both visitors see availability overlays; selection is local (no booking) and the server availability API reports occupied cells when present (MVP: API returns empty set)
|
||
|
||
### Scenario 3: Webhook replay / retry
|
||
Given this vertical slice does not include payment, webhook scenarios are out of scope for this feature; the spec requires the pipeline to be prepared for idempotent webhooks in later features.
|
||
|
||
## Scope (See <attachments> above for file contents. You may not need to search or read the file again.)
|
||
|
||
This vertical slice covers the public-facing viewer and live selection experience without creating orders or processing payments. It provides the UI and server endpoints required to compute prices, return current `master_version`, and (MVP) return an availability stub. It does NOT: create reservations in the database, process payments, run rendering Jobs, or persist uploaded images permanently.
|
||
|
||
## User Scenarios & Testing *(mandatory)*
|
||
|
||
<!--
|
||
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
|
||
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
|
||
you should still have a viable MVP (Minimum Viable Product) that delivers value.
|
||
|
||
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
|
||
Think of each story as a standalone slice of functionality that can be:
|
||
- Developed independently
|
||
- Tested independently
|
||
- Deployed independently
|
||
- Demonstrated to users independently
|
||
-->
|
||
|
||
### User Story 1 - Public viewer + Live selection (Priority: P1)
|
||
|
||
Any visitor can open the public grid page, pan/zoom the master image, draw a rectangular selection (multi-cell), and see the live cell count and computed total price. The selection is client-only for now; no reservation or checkout is created.
|
||
|
||
**Why this priority**: Validates UI complexity (grid, pan/zoom, selection) early and delivers immediate visible value.
|
||
|
||
**Independent Test**: Load the public page, perform selection on desktop and mobile, verify cell count and price calculation match server-provided `price_per_cell`.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** the public master image is visible, **When** the user drags to select cells, **Then** the sidebar updates with cell count and total price.
|
||
2. **Given** mobile device, **When** user pinches/drag to select, **Then** selection precision is maintained and preview shows correctly.
|
||
|
||
---
|
||
|
||
### User Story 2 - Upload preview modal (Priority: P2)
|
||
|
||
User can open a modal from the sidebar, select an image file and optional link, and see a client-side preview composited into the selection rectangle. The modal does not persist anything to the server in this slice.
|
||
|
||
**Independent Test**: Select an image and link, verify preview scales/crops to selection proportion and displays correctly.
|
||
|
||
---
|
||
|
||
### User Story 3 - Availability overlay (Priority: P3)
|
||
|
||
Server exposes a lightweight endpoint returning currently occupied cell coordinates. For the vertical slice this may return an empty list (stub) but the client must render any occupied cells in a distinct overlay.
|
||
|
||
**Independent Test**: Call the availability endpoint and verify the overlay marks returned coordinates as unavailable.
|
||
|
||
---
|
||
|
||
[Add more user stories as needed, each with an assigned priority]
|
||
|
||
### Edge Cases
|
||
|
||
- Selection partially outside bounds: selection is clamped to image bounds and cell counts reflect clamped area.
|
||
- Very large selection on mobile: UI prevents selections beyond a maximum configured cell count and shows a warning.
|
||
|
||
## Requirements *(mandatory)*
|
||
|
||
### Functional Requirements
|
||
|
||
- **FR-001**: Public page MUST return `master_image_url` and `master_version`.
|
||
- **FR-002**: Client MUST be able to request `price_per_cell` from the server; client computes `cell_count × price_per_cell` for display only.
|
||
- **FR-003**: Client MUST render an interactive grid overlay and allow rectangle selection with pan/zoom support.
|
||
- **FR-004**: Client MUST provide an upload + link modal with client-side preview scaled to selection.
|
||
- **FR-005**: Server MUST expose an availability endpoint returning occupied cells (MVP: can return empty set).
|
||
- **FR-006**: All endpoints MUST validate inputs and rate-limit sensitive endpoints.
|
||
|
||
### Key Entities *(include if feature involves data)*
|
||
|
||
- **MasterImage**: `path`, `version` (for cache-busting)
|
||
- **Availability**: list of `{cell_x, cell_y}` entries returned by endpoint
|
||
|
||
## Success Criteria *(mandatory)*
|
||
|
||
### Measurable Outcomes
|
||
|
||
- **SC-001**: Public page loads master image and metadata within 2000ms on a 4G connection (approximate).
|
||
- **SC-002**: Selection cell coordinates reported by client match server cell unit grid (pixel-accurate within 1 cell).
|
||
- **SC-003**: Mobile pinch/drag interaction completes selection without lost events on iPhone 14 Pro viewport.
|
||
- **SC-004**: Price calculation displays correctly using server-provided `price_per_cell`.
|
||
|
||
## Assumptions
|
||
|
||
- `cell_size` (in pixels) is a server-configured value provided to the client.
|
||
- Availability API may return empty set for MVP; production will enforce DB-level locks later.
|
||
|
||
## Out of Scope
|
||
|
||
- Creating orders, reservations, payments, rendering jobs, or persisting uploaded images.
|
||
|
||
## Requirements *(mandatory)*
|
||
|
||
<!--
|
||
ACTION REQUIRED: The content in this section represents placeholders.
|
||
Fill them out with the right functional requirements.
|
||
-->
|
||
|
||
### Functional Requirements
|
||
|
||
- **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"]
|
||
- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"]
|
||
- **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"]
|
||
- **FR-004**: System MUST [data requirement, e.g., "persist user preferences"]
|
||
- **FR-005**: System MUST [behavior, e.g., "log all security events"]
|
||
|
||
*Example of marking unclear requirements:*
|
||
|
||
- **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?]
|
||
- **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified]
|
||
|
||
### Key Entities *(include if feature involves data)*
|
||
|
||
- **[Entity 1]**: [What it represents, key attributes without implementation]
|
||
- **[Entity 2]**: [What it represents, relationships to other entities]
|
||
|
||
## Success Criteria *(mandatory)*
|
||
|
||
<!--
|
||
ACTION REQUIRED: Define measurable success criteria.
|
||
These must be technology-agnostic and measurable.
|
||
-->
|
||
|
||
### Measurable Outcomes
|
||
|
||
- **SC-001**: [Measurable metric, e.g., "Users can complete account creation in under 2 minutes"]
|
||
- **SC-002**: [Measurable metric, e.g., "System handles 1000 concurrent users without degradation"]
|
||
- **SC-003**: [User satisfaction metric, e.g., "90% of users successfully complete primary task on first attempt"]
|
||
- **SC-004**: [Business metric, e.g., "Reduce support tickets related to [X] by 50%"]
|