Skip to content

Commit 1601dd6

Browse files
committed
Phase 1 comlpletes
1 parent 738cbcb commit 1601dd6

49 files changed

Lines changed: 4757 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Environment
2+
.env
3+
vault/.env
4+
vault/.venv/
5+
vault/venv/
6+
7+
# Python
8+
__pycache__/
9+
*.pyc
10+
*.pyo
11+
*.pyd
12+
13+
# Database (local dev only)
14+
vault/vault.db
15+
16+
# IDE
17+
.vscode/
18+
.idea/
19+
*.swp
20+
21+
# OS
22+
.DS_Store
23+
Thumbs.db
24+
25+
# Testing
26+
.pytest_cache/
27+
.coverage
28+
htmlcov/

claude-instructions/README.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Claude Master Instructions — Personal Vault Project
2+
3+
This file is Claude's primary reference document. Read this at the start of every session before doing anything.
4+
5+
---
6+
7+
## Application: Personal Vault
8+
9+
A multi-user, private data storage application. Users register, log in, and store their own private data that no other user can see.
10+
11+
### What a user can do
12+
- Register with a username and password
13+
- Log in and receive a session token
14+
- Store **text notes** (title + body)
15+
- Store **passwords** (label + username + password value)
16+
- Store **important notes** (tagged, searchable)
17+
- View, edit, and delete only their own data
18+
19+
### Real-world analogy
20+
Think of it as a personal, self-hosted combination of Bitwarden (password manager) and a private notebook. Bob logs in and sees only Bob's data. Alice logs in and sees only Alice's data.
21+
22+
---
23+
24+
## Version Strategy
25+
26+
| Version | Scope | Phases |
27+
|---|---|---|
28+
| v1 | API only, SQLite, no authentication | Phase 1–2 |
29+
| v2 | Authentication added, multi-user, PostgreSQL | Phase 3–4 |
30+
| v3 | Minimal frontend, DevTools learning | Phase 3 |
31+
| v4 | Architecture refactor (service + repo layers) | Phase 5 |
32+
| v5 | Containerized, Dockerized | Phase 6 |
33+
| v6 | Nginx reverse proxy | Phase 7 |
34+
| v7 | Kong API gateway | Phase 8 |
35+
| v8 | Keycloak SSO replaces custom JWT | Phase 9 |
36+
| v9 | Kubernetes deployment | Phase 10 |
37+
| v10 | Helm charts | Phase 11 |
38+
| v11 | CI/CD pipeline | Phase 12 |
39+
| v12 | Monitoring and logging | Phase 13 |
40+
41+
---
42+
43+
## Tech Stack
44+
45+
| Layer | Choice | Reason |
46+
|---|---|---|
47+
| Language | Python 3.11+ | User has prior Python knowledge |
48+
| API Framework | FastAPI | User knows basics; auto-docs at /docs; async |
49+
| Database (v1) | SQLite | Zero setup; perfect for learning |
50+
| Database (v2+) | PostgreSQL | Production-grade; migrate before Docker |
51+
| ORM | SQLAlchemy 2.x | Industry standard; works with both DBs |
52+
| Migrations | Alembic | Tracks schema changes like git does for code |
53+
| Auth | Custom JWT first, then Keycloak | Learn JWT internals before enterprise SSO |
54+
| Frontend | Plain HTML + vanilla JS (no framework) | Learn fundamentals before React |
55+
| Container | Docker + docker-compose | Learn containers before Kubernetes |
56+
| Reverse Proxy | Nginx | Industry standard reverse proxy |
57+
| API Gateway | Kong | Real-world API management layer |
58+
| Orchestration | Kubernetes | After Docker fundamentals are solid |
59+
| Package manager | pip + requirements.txt → Poetry | Start simple, evolve tooling |
60+
61+
---
62+
63+
## Phase Roadmap
64+
65+
```
66+
Phase 1 → Project setup + first API endpoint + database connection
67+
Phase 2 → Full CRUD: notes, passwords, user model (no auth yet)
68+
Phase 3 → Minimal HTML frontend + Chrome DevTools introduction
69+
Phase 4 → CORS + JWT authentication + auth middleware
70+
Phase 5 → Service layer + Repository pattern (architecture refactor)
71+
Phase 6 → Docker + docker-compose
72+
Phase 7 → Nginx reverse proxy
73+
Phase 8 → Kong API gateway
74+
Phase 9 → Keycloak (replace custom JWT)
75+
Phase 10 → Kubernetes (pods, deployments, services)
76+
Phase 11 → Helm charts
77+
Phase 12 → GitHub Actions CI/CD
78+
Phase 13 → Prometheus + Grafana + structured logging
79+
```
80+
81+
---
82+
83+
## Non-Negotiable Process Rules
84+
85+
Claude MUST follow these rules in every session without exception.
86+
87+
### Rule 1 — Docs structure
88+
Every `docs/NNN-*.md` file must have exactly two parts:
89+
90+
**Part 1: What we are doing** — files being created/modified, implementation steps, what is NOT in scope for this step.
91+
92+
**Part 2: Concepts / KT** — short explanation of every tool, pattern, or technology used in this step. Not a textbook. Just enough to understand why it exists and what role it plays. Written in plain language with short examples.
93+
94+
### Rule 2 — Explain WHY first
95+
Before implementing, explain the business reason and technical reason. Not just "we are adding X" but "we are adding X because Y problem exists."
96+
97+
### Rule 3 — One small step at a time
98+
Never implement an entire feature in one shot. Break it into the smallest logical steps. Example: adding auth = 6 separate steps, not 1.
99+
100+
### Rule 4 — Teach during implementation
101+
When a concept appears in code, explain it inline. Do not dump theory upfront. JWT appears in code → explain JWT then.
102+
103+
### Rule 5 — Never skip a phase
104+
Do not jump from Phase 1 to Phase 4. Every phase has a learning purpose. Respect the sequence.
105+
106+
### Rule 6 — Real engineering practices always
107+
Even in v1 (SQLite, no auth), always use:
108+
- Proper folder structure
109+
- Environment variables (never hardcode secrets)
110+
- Consistent naming conventions
111+
- Meaningful error responses
112+
- Git commits after every logical step
113+
114+
### Rule 7 — Frontend is last in each phase
115+
Only build frontend after the backend step in that phase is stable and manually tested via `/docs` (FastAPI's swagger UI).
116+
117+
### Rule 8 — KT docs on demand
118+
If the user says "I don't understand" or "create KT document" — immediately create `docs/KT-topic-name.md` using the structure defined in goal.md.
119+
120+
---
121+
122+
## Folder Structure (target for v1)
123+
124+
```
125+
development/ ← git repo root
126+
├── claude-instructions/ ← Claude's playbooks (this directory)
127+
├── docs/ ← all planning + KT documents
128+
├── goal.md ← learning goals and mentorship rules
129+
├── README.md
130+
├── .gitignore
131+
└── vault/ ← the actual application lives here
132+
├── app/
133+
│ ├── main.py ← FastAPI app entry point
134+
│ ├── config.py ← environment + settings
135+
│ ├── database.py ← DB engine + session setup
136+
│ ├── models/ ← SQLAlchemy ORM models
137+
│ ├── schemas/ ← Pydantic request/response schemas
138+
│ ├── routers/ ← FastAPI route handlers
139+
│ ├── services/ ← business logic (added in Phase 5)
140+
│ └── repositories/ ← DB access layer (added in Phase 5)
141+
├── tests/ ← pytest tests
142+
├── .env ← local environment variables (gitignored)
143+
├── .env.example ← committed template of env vars
144+
└── requirements.txt
145+
```
146+
147+
**Rule:** All application code lives inside `vault/`. All docs, plans, and Claude instructions live at the repo root level. Never mix them.
148+
149+
---
150+
151+
## Application Data Models (target)
152+
153+
### User
154+
- id, username (unique), hashed_password, created_at
155+
156+
### Note
157+
- id, user_id (FK), title, body, created_at, updated_at
158+
159+
### Password Entry
160+
- id, user_id (FK), label, username, encrypted_value, created_at
161+
162+
### Tag (future, Phase 2+)
163+
- id, name, user_id
164+
165+
---
166+
167+
## DevTools Learning Goals
168+
169+
The user has never used browser developer tools. These concepts should be taught progressively during Phase 3:
170+
- Network tab: observe HTTP requests, status codes, headers, request/response bodies
171+
- Console tab: JavaScript errors, console.log debugging
172+
- Elements tab: inspect HTML structure
173+
- Application tab: view localStorage, cookies, tokens stored in browser
174+
175+
Tie every DevTools lesson to something that just happened in the app (e.g., "open Network tab and watch what happens when you click Save").
176+
177+
---
178+
179+
## Cloud + Domain Goal
180+
181+
After Phase 6 (Docker), the project will be deployed to a cloud provider (to be decided) with a free domain. This simulates a real production deployment. Claude should keep this in mind when making infrastructure decisions — avoid anything that only works locally.
182+
183+
---
184+
185+
## Reference Files
186+
187+
- `goal.md` — user's full learning goal and mentorship instructions
188+
- `claude-instructions/debugging-philosophy.md`**READ THIS** for how to handle all errors and deliberate mistakes
189+
- `claude-instructions/phase-*/` — per-phase implementation playbooks
190+
- `docs/` — all feature planning docs and KT documents created during development
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Debugging Philosophy
2+
3+
This file defines how Claude handles errors and debugging throughout all phases.
4+
5+
---
6+
7+
## Rule: Teach debugging methodology BEFORE fixing anything
8+
9+
When an error occurs — whether real or deliberately introduced — never silently fix it.
10+
11+
Always follow this sequence:
12+
13+
### 1. Read the error out loud
14+
Walk through the error message word by word. Most engineers (especially beginners) panic when they see a red error and immediately Google it without actually reading what it says.
15+
16+
Example:
17+
```
18+
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: notes
19+
```
20+
Before fixing: "Let's read this carefully. `OperationalError` — something went wrong at the database operation level. `no such table: notes` — the database doesn't have a table called `notes`. Why? Let's find out."
21+
22+
### 2. Identify the layer
23+
Which layer is failing?
24+
- Is the error in the terminal (server-side)?
25+
- Is the error in the browser Console (client-side JavaScript)?
26+
- Is the error in the browser Network tab (HTTP response)?
27+
- Is the error in the database (SQL)?
28+
29+
Knowing WHERE the error is tells you WHERE to look next.
30+
31+
### 3. Form a hypothesis
32+
Before touching anything: "I think this is happening because X."
33+
Then check if that hypothesis is correct.
34+
35+
### 4. Test the hypothesis (not fix it)
36+
One change at a time. If you change three things at once and it works, you don't know what fixed it — and you don't learn.
37+
38+
### 5. Fix, then explain WHY the fix works
39+
Not just what the fix is, but why the original code was wrong and what the fix does differently.
40+
41+
---
42+
43+
## Deliberate Mistakes Policy
44+
45+
At appropriate moments in each phase, Claude will intentionally introduce a common real-world mistake, let the error surface, and then run through the debugging process above.
46+
47+
This is NOT random sabotage. Each mistake is:
48+
- Common in real engineering (you WILL encounter this in a real job)
49+
- Fixable with the debugging skills relevant to that phase
50+
- Followed by a full debugging walkthrough
51+
52+
The user will be told: **"This is a deliberate mistake — let's debug it."**
53+
54+
---
55+
56+
## Planned deliberate mistakes by phase
57+
58+
### Phase 1 — Project Setup
59+
**Mistake**: Missing `__init__.py` in a package folder.
60+
**Error**: `ModuleNotFoundError: No module named 'app.routers'`
61+
**Lesson**: Python package system, what `__init__.py` does
62+
63+
### Phase 1 — First API
64+
**Mistake**: Forget to include the router in `main.py`.
65+
**Error**: `GET /health` returns 404 in Swagger even though the route file exists
66+
**Lesson**: FastAPI router registration, difference between "file exists" and "route is registered"
67+
68+
### Phase 1 — Database
69+
**Mistake**: Wrong `DATABASE_URL` format (e.g., `sqlite://vault.db` instead of `sqlite:///./vault.db`).
70+
**Error**: `sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string 'sqlite://vault.db'`
71+
**Lesson**: Connection strings, how to read SQLAlchemy errors, URL format rules
72+
73+
### Phase 2 — Models
74+
**Mistake**: Forget to import the model in `models/__init__.py` before calling `create_all()`.
75+
**Error**: Table doesn't get created, then `OperationalError: no such table: notes` when inserting
76+
**Lesson**: How SQLAlchemy discovers models, why `create_all` needs to see the model class
77+
78+
### Phase 2 — CRUD
79+
**Mistake**: Return the SQLAlchemy model object directly from a route (instead of using Pydantic response schema).
80+
**Error**: `ValueError: sqlalchemy.orm.DeclarativeBase is not a valid pydantic field type`
81+
**Lesson**: The model/schema separation, why response schemas exist, what Pydantic serialization does
82+
83+
### Phase 3 — Frontend
84+
**Mistake**: Wrong API URL in `fetch()` (e.g., `/notes` instead of `/api/notes` after the prefix change).
85+
**Error**: Browser Console shows `404 Not Found` on the fetch call, but the API endpoint exists
86+
**Lesson**: DevTools Network tab, how to trace a 404 from frontend to backend
87+
88+
### Phase 4 — CORS
89+
**Mistake**: Add CORS middleware AFTER mounting static files in `main.py`.
90+
**Error**: CORS headers missing on API responses, error appears in browser Console
91+
**Lesson**: FastAPI middleware order matters, middleware executes in reverse registration order
92+
93+
### Phase 4 — JWT
94+
**Mistake**: Forget to set `SECRET_KEY` in `.env` (use empty string).
95+
**Error**: All tokens validate as valid (empty key = no security) OR all tokens fail depending on the library
96+
**Lesson**: Why secret key management matters, how to verify a config value is actually loaded
97+
98+
### Phase 6 — Docker
99+
**Mistake**: Forget `.dockerignore` — copy `.env` into the image.
100+
**Error**: Not an immediate crash, but show using `docker inspect` that secrets are baked into the image
101+
**Lesson**: Security-in-containers, why `.dockerignore` is as important as `.gitignore`
102+
103+
### Phase 6 — Docker
104+
**Mistake**: Use `localhost` in `DATABASE_URL` inside Docker instead of the service name `db`.
105+
**Error**: `Connection refused` — the app tries to connect to its own container's localhost, not the db container
106+
**Lesson**: Docker networking, container DNS, why service names are used in connection strings
107+
108+
---
109+
110+
## How to use DevTools for debugging (reference)
111+
112+
When the error is frontend-side, always open DevTools FIRST:
113+
114+
| Symptom | Where to look |
115+
|---|---|
116+
| Page loads but data doesn't appear | Network tab → find the failed request |
117+
| JavaScript error on page | Console tab → read the error message |
118+
| API call goes out but returns wrong data | Network tab → Response tab of the request |
119+
| Token not being sent | Network tab → Headers tab → look for Authorization |
120+
| CORS error | Console tab → red CORS message |
121+
| App works in Swagger but not in browser | Usually CORS or wrong URL in fetch() |
122+
123+
---
124+
125+
## Debugging commands reference (backend)
126+
127+
```bash
128+
# See what's running
129+
ps aux | grep uvicorn
130+
131+
# Check if port is in use
132+
lsof -i :8000
133+
134+
# Inspect SQLite database directly
135+
sqlite3 vault.db ".tables"
136+
sqlite3 vault.db "SELECT * FROM users;"
137+
138+
# Check if env var is loaded
139+
python -c "from app.config import settings; print(settings.database_url)"
140+
141+
# See Docker container logs
142+
docker logs <container_name>
143+
docker logs <container_name> --follow # live tail
144+
145+
# Check container networking
146+
docker exec -it <container_name> curl http://db:5432 # test internal DNS
147+
docker network inspect vault_default # see all containers on the network
148+
```
149+
150+
---
151+
152+
## The mindset
153+
154+
A senior engineer does not panic at errors. They:
155+
1. Read the error
156+
2. Identify the layer
157+
3. Form a hypothesis
158+
4. Test it
159+
5. Fix and explain
160+
161+
Developing this mental habit is more valuable than knowing any specific technology. Every technology breaks differently, but the debugging process is always the same.

0 commit comments

Comments
 (0)