Skip to content

Commit cd77a1a

Browse files
author
aligneddev
committed
implement, needs review
1 parent 66ee316 commit cd77a1a

39 files changed

Lines changed: 2544 additions & 31 deletions
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# neCodeBikeTracking Development Guidelines
2+
3+
Auto-generated from all feature plans. Last updated: 2026-03-13
4+
5+
## Active Technologies
6+
7+
- .NET 10 (C#), F# (domain project), TypeScript 5.x (Aurelia 2 frontend) + ASP.NET Core Minimal API, Microsoft Aspire AppHost, Entity Framework Core + SQLite provider, Aurelia 2 + `@aurelia/router`, .NET `System.Security.Cryptography` (PBKDF2), background worker for outbox retry (001-user-signup-pin)
8+
9+
## Project Structure
10+
11+
```text
12+
backend/
13+
frontend/
14+
tests/
15+
```
16+
17+
## Commands
18+
19+
npm test; npm run lint
20+
21+
## Code Style
22+
23+
.NET 10 (C#), F# (domain project), TypeScript 5.x (Aurelia 2 frontend): Follow standard conventions
24+
25+
## Recent Changes
26+
27+
- 001-user-signup-pin: Added .NET 10 (C#), F# (domain project), TypeScript 5.x (Aurelia 2 frontend) + ASP.NET Core Minimal API, Microsoft Aspire AppHost, Entity Framework Core + SQLite provider, Aurelia 2 + `@aurelia/router`, .NET `System.Security.Cryptography` (PBKDF2), background worker for outbox retry
28+
29+
<!-- MANUAL ADDITIONS START -->
30+
<!-- MANUAL ADDITIONS END -->

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,20 @@ appsettings.Development.json
4040

4141
# Others
4242
*.db
43+
*.db-shm
44+
*.db-wal
4345
*.sqlite
46+
*.sqlite-shm
47+
*.sqlite-wal
4448
*.bak
4549
*.cache
50+
node_modules/
51+
dist/
52+
build/
53+
coverage/
54+
.env*
55+
*.tmp
56+
*.swp
4657

4758
#Paket dependency manager
4859
paket-files/

.specify/memory/constitution.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ Example: "User records a bike ride" slice includes:
155155
- Background function listening to CES to update RideProjection
156156
- Aspire AppHost configuration for frontend + API + database orchestration; Azure CLI deployment scripts for Static Web Apps (frontend) and Container Apps (API)
157157

158+
run `dotnet format .` to enforce code style; `dotnet test` to run tests; `dotnet run --project src/BikeTracking.AppHost` to start local stack; GitHub Actions for CI/CD to Azure.
159+
160+
run Typescript linting and formatting via `npm run lint` and `npm run format` in the frontend directory.
161+
158162
### Vertical Slice Implementation Strategy: Minimal-First Approach
159163

160164
After the application structure is built, implementation proceeds in **vertical slices with minimal functionality first**:
@@ -166,7 +170,7 @@ After the application structure is built, implementation proceeds in **vertical
166170
- Event and projection for persistence
167171
- Database schema (migrations)
168172
- No bells, whistles, or optional features
169-
3. **Test & Verify**: Run full test suite (unit, integration, E2E); deploy locally via `dotnet run` and manually verify the slice works as specified.
173+
3. **Test & Verify**: Run full test suite (unit, integration, E2E); deploy locally via `dotnet run` and manually verify the slice works as specified. Each slice must be fully tested (unit, integration, E2E) and user-approved before proceeding to the next slice.
170174
4. **User Decision Point**: Once minimal slice is verified and working, present the user with options:
171175
- **Approve Minimal & Iterate**: User approves the working slice, then we build next priority feature (additional fields, refinements, enhancement)
172176
- **Expand Current Slice**: User requests additional functionality for the current slice before finalizing (e.g., "add weather capture" to the ride recording feature)

README.md

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
11
# Commute Bike Tracker
22

3-
Scaffolded starter structure for a local-first Bike Tracking application.
3+
Local-first Bike Tracking application built with .NET Aspire orchestration, .NET 10 Minimal API, F# domain modules, and an Aurelia 2 frontend.
44

5-
## What exists now
5+
## Current Feature Slice
66

7-
- .NET 10 Aspire AppHost orchestration
8-
- .NET 10 Minimal API backend with hello endpoints
9-
- F# domain project placeholder
10-
- React frontend (Vite) with a simple hello screen
11-
- No business logic implemented yet
12-
- No database schema created yet
7+
- Local user signup with name and PIN
8+
- PIN protection through salted, non-reversible hashing (PBKDF2)
9+
- Duplicate-name rejection using trimmed, case-insensitive normalization
10+
- User identification with progressive retry delay (up to 30 seconds)
11+
- User registration outbox with background retry until successful publication
1312

14-
## Project structure
13+
## Project Structure
1514

1615
- src/BikeTracking.AppHost - Aspire orchestration host
1716
- src/BikeTracking.Api - Minimal API service
18-
- src/BikeTracking.ServiceDefaults - Shared Aspire defaults/telemetry wiring
19-
- src/BikeTracking.Domain.FSharp - Domain layer starter project (F#)
20-
- src/BikeTracking.Frontend - React frontend app
17+
- src/BikeTracking.ServiceDefaults - Shared Aspire defaults and telemetry wiring
18+
- src/BikeTracking.Domain.FSharp - Domain event and type modules (F#)
19+
- src/BikeTracking.Frontend - Aurelia 2 frontend app
2120

2221
## Prerequisites
2322

2423
- .NET SDK 10.x
2524
- Node.js 20+ and npm
2625

27-
## Quick start
26+
## Quick Start
2827

2928
1. Install frontend dependencies:
3029

@@ -40,15 +39,23 @@ cd ../..
4039
dotnet run --project src/BikeTracking.AppHost
4140
```
4241

43-
3. Open Aspire dashboard and launch services:
44-
- `frontend` for the React hello screen
45-
- `api` for the Minimal API
42+
3. Open Aspire dashboard and launch:
43+
- frontend service for the signup and identify screen
44+
- api service for local identity endpoints
4645

47-
## API starter endpoints
46+
## Local Identity Endpoints
4847

49-
- `/` returns API running message
50-
- `/hello` returns hello message
48+
- GET / - API status
49+
- POST /api/users/signup - create local user record and queue UserRegistered event
50+
- POST /api/users/identify - authorize user by normalized name and PIN
5151

52-
## Next step
52+
## Local Scope Boundaries
5353

54-
Use SpecKit to define the first vertical slice before implementing features.
54+
- This slice is local-only and intentionally excludes OAuth and Azure hosting.
55+
- Name and PIN are validated on client and server.
56+
- PIN plaintext is never stored or emitted in events.
57+
- Future cloud and OAuth expansion will be delivered in a separate feature.
58+
59+
## Next Step
60+
61+
Continue with task execution and verification using specs/001-user-signup-pin/tasks.md.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Specification Quality Checklist: Local User Signup and PIN Identity
2+
3+
**Purpose**: Validate specification completeness and quality before proceeding to planning
4+
**Created**: 2026-03-13
5+
**Feature**: [spec.md](../spec.md)
6+
7+
## Content Quality
8+
9+
- [x] No implementation details (languages, frameworks, APIs)
10+
- [x] Focused on user value and business needs
11+
- [x] Written for non-technical stakeholders
12+
- [x] All mandatory sections completed
13+
14+
## Requirement Completeness
15+
16+
- [x] No [NEEDS CLARIFICATION] markers remain
17+
- [x] Requirements are testable and unambiguous
18+
- [x] Success criteria are measurable
19+
- [x] Success criteria are technology-agnostic (no implementation details)
20+
- [x] All acceptance scenarios are defined
21+
- [x] Edge cases are identified
22+
- [x] Scope is clearly bounded
23+
- [x] Dependencies and assumptions identified
24+
25+
## Feature Readiness
26+
27+
- [x] All functional requirements have clear acceptance criteria
28+
- [x] User scenarios cover primary flows
29+
- [x] Feature meets measurable outcomes defined in Success Criteria
30+
- [x] No implementation details leak into specification
31+
32+
## Notes
33+
34+
- All checklist items passed in validation iteration 1.
35+
- No clarification questions are required for this feature.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
openapi: 3.0.3
2+
info:
3+
title: BikeTracking Local User Identity API
4+
version: 1.0.0
5+
description: Local-first signup and identification endpoints for name and PIN authorization.
6+
7+
paths:
8+
/api/users/signup:
9+
post:
10+
summary: Create a local user with name and PIN
11+
operationId: signupUser
12+
requestBody:
13+
required: true
14+
content:
15+
application/json:
16+
schema:
17+
$ref: '#/components/schemas/SignupRequest'
18+
responses:
19+
'201':
20+
description: User created
21+
content:
22+
application/json:
23+
schema:
24+
$ref: '#/components/schemas/SignupSuccessResponse'
25+
'400':
26+
description: Validation failed
27+
content:
28+
application/json:
29+
schema:
30+
$ref: '#/components/schemas/ErrorResponse'
31+
'409':
32+
description: Duplicate normalized name
33+
content:
34+
application/json:
35+
schema:
36+
$ref: '#/components/schemas/ErrorResponse'
37+
38+
/api/users/identify:
39+
post:
40+
summary: Identify and authorize local user by normalized name and PIN
41+
operationId: identifyUser
42+
requestBody:
43+
required: true
44+
content:
45+
application/json:
46+
schema:
47+
$ref: '#/components/schemas/IdentifyRequest'
48+
responses:
49+
'200':
50+
description: Authorized
51+
content:
52+
application/json:
53+
schema:
54+
$ref: '#/components/schemas/IdentifySuccessResponse'
55+
'400':
56+
description: Validation failed
57+
content:
58+
application/json:
59+
schema:
60+
$ref: '#/components/schemas/ErrorResponse'
61+
'401':
62+
description: Invalid credentials
63+
content:
64+
application/json:
65+
schema:
66+
$ref: '#/components/schemas/ErrorResponse'
67+
'429':
68+
description: Request throttled due to repeated failures
69+
headers:
70+
Retry-After:
71+
schema:
72+
type: integer
73+
minimum: 1
74+
description: Seconds before next attempt is processed.
75+
content:
76+
application/json:
77+
schema:
78+
$ref: '#/components/schemas/ThrottleResponse'
79+
80+
components:
81+
schemas:
82+
SignupRequest:
83+
type: object
84+
required:
85+
- name
86+
- pin
87+
properties:
88+
name:
89+
type: string
90+
description: Display name; server trims and normalizes for duplicate detection.
91+
pin:
92+
type: string
93+
description: Numeric PIN input, validated by policy.
94+
95+
SignupSuccessResponse:
96+
type: object
97+
required:
98+
- userId
99+
- userName
100+
- createdAtUtc
101+
properties:
102+
userId:
103+
type: integer
104+
format: int64
105+
userName:
106+
type: string
107+
createdAtUtc:
108+
type: string
109+
format: date-time
110+
eventStatus:
111+
type: string
112+
enum:
113+
- queued
114+
- published
115+
116+
IdentifyRequest:
117+
type: object
118+
required:
119+
- name
120+
- pin
121+
properties:
122+
name:
123+
type: string
124+
description: Name compared using trimmed, case-insensitive normalization.
125+
pin:
126+
type: string
127+
128+
IdentifySuccessResponse:
129+
type: object
130+
required:
131+
- userId
132+
- userName
133+
- authorized
134+
properties:
135+
userId:
136+
type: integer
137+
format: int64
138+
userName:
139+
type: string
140+
authorized:
141+
type: boolean
142+
enum: [true]
143+
144+
ThrottleResponse:
145+
type: object
146+
required:
147+
- code
148+
- message
149+
- retryAfterSeconds
150+
properties:
151+
code:
152+
type: string
153+
enum:
154+
- throttled
155+
message:
156+
type: string
157+
retryAfterSeconds:
158+
type: integer
159+
minimum: 1
160+
161+
ErrorResponse:
162+
type: object
163+
required:
164+
- code
165+
- message
166+
properties:
167+
code:
168+
type: string
169+
message:
170+
type: string
171+
details:
172+
type: array
173+
items:
174+
type: string

0 commit comments

Comments
 (0)