Skip to content

Commit 9011302

Browse files
authored
Merge pull request #3 from aligneddev/001-user-signup-pin
001 user signup pin
2 parents 66ee316 + 5439412 commit 9011302

49 files changed

Lines changed: 8117 additions & 1738 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
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: 48 additions & 19 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
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 a React 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 - React + Vite frontend app
2120

2221
## Prerequisites
2322

2423
- .NET SDK 10.x
2524
- Node.js 20+ and npm
25+
- CSharpier global tool (required for formatting checks):
2626

27-
## Quick start
27+
```powershell
28+
dotnet tool install csharpier -g
29+
```
30+
31+
run it with `csharpier format .` from the repo root to format all C# code.
32+
33+
- Helpful editor integration: VS Code CSharpier extension (`csharpier.csharpier-vscode`)
34+
35+
## Quick Start
2836

2937
1. Install frontend dependencies:
3038

@@ -40,15 +48,34 @@ cd ../..
4048
dotnet run --project src/BikeTracking.AppHost
4149
```
4250

43-
3. Open Aspire dashboard and launch services:
44-
- `frontend` for the React hello screen
45-
- `api` for the Minimal API
51+
3. Open Aspire dashboard and launch:
52+
- frontend service for the signup and identify screen
53+
- api service for local identity endpoints
54+
55+
## Local Identity Endpoints
56+
57+
- GET / - API status
58+
- POST /api/users/signup - create local user record and queue UserRegistered event
59+
- POST /api/users/identify - authorize user by normalized name and PIN
60+
61+
## Local Scope Boundaries
62+
63+
- This slice is local-only and intentionally excludes OAuth and Azure hosting.
64+
- Name and PIN are validated on client and server.
65+
- PIN plaintext is never stored or emitted in events.
66+
- Future cloud and OAuth expansion will be delivered in a separate feature.
67+
68+
## Local User-Machine Install Approach
4669

47-
## API starter endpoints
70+
For local-first deployment to end-user machines, the default persistence model is a local SQLite file.
4871

49-
- `/` returns API running message
50-
- `/hello` returns hello message
72+
- No separate database installation or database service is required.
73+
- The API currently defaults to a local SQLite file named biketracking.local.db.
74+
- Startup applies EF Core migrations automatically to create or update schema.
75+
- For packaged installs, place the SQLite file in a user-writable application-data folder rather than the application install directory.
76+
- Before schema upgrades, create a safety backup copy of the SQLite file.
77+
- Use SQL Server LocalDB or SQL Server Express only when local multi-user requirements exceed the single-user SQLite profile.
5178

52-
## Next step
79+
## Next Step
5380

54-
Use SpecKit to define the first vertical slice before implementing features.
81+
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)