Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,6 @@ The event schema is the most important artifact in the repo. Rules:

## Current Working Context

See `docs/CURRENT_SLICE.md` for what we're actively building right now.
The Week 1–2 Foundation slice is **complete** (all 8 deliverables on `main`, 2026-05-18). Active work is now **Vertical Slice 0 — Auth + Task Capture Spine**.

See `docs/CURRENT_SLICE.md` for what we're actively building right now, and `docs/handoffs/week-1-2.md` for the foundation outcome + remaining operational steps.
6 changes: 3 additions & 3 deletions docs/CURRENT_SLICE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Current Slice — Vertical Slice 0: Auth + Task Capture Spine

> **⚠️ Foundation status (2026-05-11):** The Week 1–2 Foundation slice is **partially shipped**. Monorepo wiring, event schema v1 (9 types, TS↔Python round-trip green), `@lockin/ui` base components, GitHub Actions PR pipeline, and GCP Terraform modules are done. Auth (NextAuth + Google OAuth + passkeys), full observability (Sentry + OTel + Grafana), Storybook deploy, secrets-pull CLI, and the TimescaleDB hypertable migration are **not yet shipped**. Read [`docs/handoffs/week-1-2.md`](handoffs/week-1-2.md) before starting this slice — Slice 0 depends on auth being in place, so Tasks 9 + 10 of the foundation plan should land first.
> ** Foundation status (2026-05-18):** The Week 1–2 Foundation slice is **complete** — all 8 deliverables merged to `main` across PRs #1–#5. Monorepo + Turborepo, event schema v1 (9 types, TS↔Python round-trip), `@lockin/ui` + Storybook, GitHub Actions (PR + staging + prod pipelines), GCP Terraform modules, observability (OTel + Sentry + Grafana), secret management, and the auth foundation (NextAuth v5 + Google OAuth + WebAuthn passkeys) are all on `main`. Remaining items are **operational, not code** — see [`docs/handoffs/week-1-2.md`](handoffs/week-1-2.md) for the ops checklist before this slice ships to a real environment.

**Status:** Blocked on Foundation Tasks 9 + 10 (auth + passkeys)
**Status:** Ready to start — foundation unblocked
**Owner:** [assigned engineer]
**Est. duration:** 3–5 days (after auth lands)
**Est. duration:** 3–5 days

## The Goal

Expand Down
92 changes: 47 additions & 45 deletions docs/handoffs/week-1-2.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,65 @@
# Week 1–2 Foundation — Handoff to Week 3

**Date:** 2026-05-11
**Branch:** `feat/week-1-2-foundation`
**Slice status:** ✅ **COMPLETE** — all 8 deliverables merged to `main` (2026-05-18)
**Plan:** [`docs/superpowers/plans/2026-05-11-week-1-2-foundation.md`](../superpowers/plans/2026-05-11-week-1-2-foundation.md)
**Shipped via:** PRs #1–#5

This slice is partially landed. The foundation-unblocking subset that Week 3 depends on is shipped; auth, observability, and Storybook are sequenced for follow-up sessions.
## Delivery map

## Shipped this session
| PR | Branch | Deliverables |
| --- | --- | --- |
| #1 | `feat/week-1-2-foundation` | 1 Monorepo · 2 CI (PR pipeline) · 3 Terraform · 7 design system · 8 event schema |
| #2 | `feat/auth-google-oauth` | 6 Auth foundation · TimescaleDB hypertable migration |
| #3 | `feat/observability-baseline` | 4 Observability (OTel + Sentry + Grafana) |
| #4 | `feat/deploy-and-secrets` | 2 CI (staging/prod CD) · 5 Secret management |
| #5 | `feat/storybook-preview` | 7 Storybook deploy |

- [x] **Deliverable 1 — Monorepo.** Turborepo + pnpm workspace at root. `pnpm install && pnpm typecheck` green on a clean clone. 4 workspaces: `@lockin/web`, `@lockin/events`, `@lockin/ui`, `@lockin/shared-types`. uv workspace covers `apps/api`, `apps/mcp`, `packages/events/python`.
- [x] **Deliverable 2 — CI/CD (PR pipeline).** `.github/workflows/pr.yml` with `dorny/paths-filter` for changed-package detection. Separate jobs: js (lint/typecheck/test/build), python-api (ruff/mypy/pytest), python-mcp, events-roundtrip (TS + Python parity), terraform-plan (fmt-check + validate staging + prod). One `gate` job aggregates results so branch protection has a single required check.
- [x] **Deliverable 3 — Terraform (modules + envs).** Six GCP modules (`vpc`, `postgres`, `redis`, `kubernetes`, `secrets`, `dns`) wired into `envs/staging` and `envs/prod`. GCS remote state, env-prefixed paths. README documents state-bucket bootstrap, TimescaleDB `CREATE EXTENSION` step, and the Workload Identity Federation chicken-and-egg.
- [x] **Deliverable 7 — Design system (`@lockin/ui`).** Six base components (`Button`, `Input`, `Card`, `Stack`, `Text`, `Icon`) + Tailwind v4 `@theme` token block with brand, semantic surfaces, type scale, spacing, motion, radius, dark-mode variants. 18 component tests via Vitest + Testing Library. `apps/web` consumes `@lockin/ui` and the page renders `Button/Stack/Text` — design-system smoke test green.
- [x] **Deliverable 8 — Event schema v1.** Zod source-of-truth at `packages/events/src/schema.ts`. 9 event types (`task.created`, `task.scheduled`, `task.accepted`, `task.rejected`, `task.modified`, `task.completed`, `mood.logged`, `energy.logged`, `schedule.explained`). Versioned envelope (`event_version: 1`) with `source` enum, `tenant_id`, `client_idempotency_key`. JSON Schema emitted; pydantic models generated via `datamodel-code-generator`. 19 TS round-trip tests + 10 Python round-trip tests — both green. `apps/api/app/events/schemas.py` rewritten to thin re-export from the `lockin_events` package.
## Acceptance vs current state

## Punted to follow-up sessions
| # | Deliverable | Acceptance check | State |
| --- | --- | --- | --- |
| 1 | Monorepo | `pnpm install` + `pnpm dev` boots web; `make api`/`make mcp` boot the Python apps | ✅ shipped |
| 2 | CI/CD | PR pipeline (paths-filtered) + `staging.yml` + `prod.yml` | ✅ shipped — live deploys gated on repo secrets |
| 3 | Terraform | GCP modules (vpc/postgres/redis/gke/secrets/dns) + staging/prod envs | ✅ shipped — `apply` pending one-time GCP bootstrap |
| 4 | Observability | OTel + Sentry on api/mcp/web; Grafana dashboards; forced-500 route | ✅ shipped — Grafana UI authoring + Slack contact point pending |
| 5 | Secrets | Zero secrets in repo; `pnpm secrets:pull` helper | ✅ shipped |
| 6 | Auth foundation | NextAuth v5 + Google OAuth + JWT middleware + `/api/me`; WebAuthn passkey endpoints | ✅ shipped |
| 7 | Design system | `@lockin/ui` 6 base components + tokens; `apps/web` consumes them; Storybook | ✅ shipped — Lighthouse ≥95 verify pending live deploy |
| 8 | Event schema v1 | 9 event types, TS↔Python round-trip; TimescaleDB migration ready (unapplied) | ✅ shipped |

- [ ] **Deliverable 2 — staging + prod pipelines.** `.github/workflows/staging.yml` and `prod.yml` are speced in the plan (Task 6) but not committed. Manual reviewer approval on the `prod` GitHub Environment is a repo-setting and is **not** enforced by the workflow file alone.
- [ ] **Deliverable 4 — Observability.** OpenTelemetry SDK wiring (Task 11), Sentry SDK on web/api/mcp (Task 12), Grafana Cloud dashboards + Slack alert + forced-500 verification (Task 13). Today's `apps/api/app/core/logging.py` is OTel-compatible structured logging only — no exporter yet.
- [ ] **Deliverable 5 — Secret management.** `scripts/secrets-pull.mjs` and `.env.example` expansion (Task 8). Today there are no real secrets in the repo (✓) but no automated rotation pull either.
- [ ] **Deliverable 6 — Auth foundation.** NextAuth v5 + Google OAuth + JWT middleware + `/api/me` (Task 9), WebAuthn passkey endpoints (Task 10).
- [ ] **Deliverable 7 — Storybook deploy** (Task 4). Components exist; Storybook config + Vercel preview workflow do not.
- [ ] **Deliverable 8 — TimescaleDB hypertable migration** (Task 14). Alembic migration not yet committed; the plan has the code.
## Test posture on `main`

## Open infra debt (must do once, manually, before staging is real)
- `pnpm typecheck` — 5/5 turbo tasks · `pnpm lint` — 3/3 · `pnpm test` — 18 ui + 19 events
- `pytest apps/api` — 15 · `pytest apps/mcp` — 2 · `pytest packages/events` — 10
- `mypy apps/api` clean (40 files) · `mypy apps/mcp` clean (12 files)

- Create GCS state bucket: `gcloud storage buckets create gs://lockin-tfstate-$LOCKIN_GCP_PROJECT ...` (see [`infra/terraform/README.md`](../../infra/terraform/README.md)).
- Configure GitHub Actions OIDC → GCP Workload Identity Pool. The pool/provider isn't in Terraform — it would have to authenticate as itself to create itself.
- After Terraform applies Cloud SQL: connect once and run `CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;`.
- Configure repo Settings → Environments → `prod` with required-reviewers; the workflow file does not enforce this on its own.
## Open operational debt — must be done before staging is real

## What Week 3 (Auth + Task Capture Spine) starts with
These are **not code** — they are one-time provisioning steps, owned by DevOps:

- `pnpm install && pnpm dev` boots `@lockin/web` on `http://localhost:3000`.
- `@lockin/web` already imports `Button`, `Stack`, `Text` from `@lockin/ui`. Adding `Input` for the task-input field is one import.
- `@lockin/events` exports `TaskCreatedEvent`, `LockInEvent`, and 7 more event types. `apps/api` imports the same types via `from lockin_events import TaskCreated`.
- The `events:tasks` Redis stream constant is canonical in both languages. `EVENT_TYPE_TO_STREAM["task.created"] === "events:tasks"`.
- `apps/api` test suite still passes after the `schemas.py` rewrite — 1 health test green.
- `docker compose -f infra/docker/docker-compose.dev.yml up -d` brings up local Postgres + Redis (this slice did not touch local-dev infra).
- **GCS state bucket** — `gcloud storage buckets create gs://lockin-tfstate-$LOCKIN_GCP_PROJECT …` (see [`infra/terraform/README.md`](../../infra/terraform/README.md)).
- **GitHub Actions OIDC → GCP** — create the Workload Identity Federation pool/provider; bind the `lockin-deploy` service account. Cannot be Terraformed (chicken-and-egg).
- **Repo secrets** — provision `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_WEB_PROJECT_ID`, `VERCEL_STORYBOOK_PROJECT_ID`, `GCP_WORKLOAD_IDENTITY_PROVIDER`, `GCP_DEPLOY_SA`, `GCP_PROJECT_ID`, `SENTRY_DSN_*`, `SENTRY_ORG/PROJECT/AUTH_TOKEN`, `GRAFANA_CLOUD_OTLP_*`.
- **`prod` GitHub Environment** — configure Required reviewers in repo Settings → Environments. The `prod.yml` workflow references the environment but does not enforce the gate by itself.
- **TimescaleDB** — after the first `terraform apply` provisions Cloud SQL, run `CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;` once, then apply Alembic migration `0001`.
- **K8s manifests** — `staging.yml`/`prod.yml` assume `Deployment/api` and `Deployment/mcp` already exist in the `lockin` namespace. Authoring those manifests is the first infra task of whichever slice ships the backend to GKE.
- **Grafana** — import the three dashboards from [`infra/grafana/dashboards/`](../../infra/grafana/dashboards), create the `#lockin-test-alerts` Slack contact point + the `api 5xx > 0` rule, then run the forced-500 acceptance test (`curl …/v1/__debug__/force_500`).

## What Week 3 should **not** do
## Known code follow-up

- Touch root Turborepo wiring, event schema TS/Python codegen pipeline, or `@lockin/ui` base components. Add new components/events only if needed.
- Add another OAuth provider — that's the Week 5 polish window per the cloud + OAuth decision record ([`docs/decisions/2026-05-11-cloud-and-oauth.md`](../decisions/2026-05-11-cloud-and-oauth.md)).
- Start native mobile, gamification, or analytics dashboard work — those are P3 / out-of-scope per `CLAUDE.md`.
- **`app` package-name collision** — both `apps/api` and `apps/mcp` install themselves as the top-level `app` Python module. The `apps/mcp` smoke test works around it with `importlib` path-loading. Proper fix: rename one package (`refactor/mcp-namespace`). Not foundation scope.

## Acceptance vs current state
## What Week 3 (Auth + Task Capture Spine) starts with

| # | Deliverable | Acceptance check | State |
| --- | ---------------------------------------- | ----------------------------------------------------------- | ----------------------------------------- |
| 1 | Monorepo | `pnpm install && pnpm dev` boots all 3 apps from clean clone | ✓ shipped |
| 2 | CI/CD | PR pipeline runs only changed-package tests; main→staging <8m; tag→prod with approval | PR pipeline ✓ shipped; staging/prod ↺ punted |
| 3 | Terraform | `apply` from zero produces working staging; `destroy` clean | ✓ shipped (validation pending real `apply`) |
| 4 | Observability | Forced 500 → Sentry + Grafana + Slack alert within 60s | ↺ punted |
| 5 | Secrets | No secrets in repo; rotation without redeploy | Half: repo is clean (✓), no rotation tool yet |
| 6 | Auth foundation | OAuth signin → `/api/me` returns user; passkey verify works | ↺ punted |
| 7 | Design system | `@lockin/web` uses `@lockin/ui`; Lighthouse ≥95 | Components ✓ shipped; Storybook deploy ↺ punted |
| 8 | Event schema v1 | TS↔Python round-trip green; hypertable migration ready | Round-trip ✓ shipped; migration ↺ punted |
- A user can sign in with Google; `/api/me` returns `{ user_id, email, providers }`.
- The api validates a shared-secret HS256 bearer (`get_current_user` dependency) and can write to Postgres.
- The event schema imports cleanly from `apps/web` (`@lockin/events`) and `apps/api` (`lockin_events`).
- `@lockin/ui` exports `Input`, `Button`, `Stack`, `Text` — everything the task-input UI needs.
- Sentry catches errors; OTel traces flow once `GRAFANA_CLOUD_OTLP_*` is set; the forced-500 route proves the chain.
- `docker compose -f infra/docker/docker-compose.dev.yml up -d` brings up local Postgres + Redis.

## Pointer for the next session
## What Week 3 should NOT do

Read [`docs/superpowers/plans/2026-05-11-week-1-2-foundation.md`](../superpowers/plans/2026-05-11-week-1-2-foundation.md) — Tasks **4, 6, 8, 9, 10, 11, 12, 13, 14** are concretely spec'd and unexecuted. Each has full code/config; no placeholders.
- Re-touch monorepo wiring, the event-schema codegen pipeline, or `@lockin/ui` base components — extend only.
- Add another OAuth provider — Apple + Microsoft are the Week 5 polish window ([`docs/decisions/2026-05-11-cloud-and-oauth.md`](../decisions/2026-05-11-cloud-and-oauth.md)).
- Start gamification, native mobile, or an analytics dashboard — out of P1 scope per `CLAUDE.md`.
7 changes: 7 additions & 0 deletions docs/superpowers/plans/2026-05-11-week-1-2-foundation.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Week 1–2 Foundation Slice — Implementation Plan

> **✅ STATUS: COMPLETE (2026-05-18).** All 15 tasks shipped to `main` via PRs #1–#5.
> The unchecked `- [ ]` boxes below are left as the historical plan record — do not
> re-execute. Current state and remaining operational steps live in
> [`docs/handoffs/week-1-2.md`](../../handoffs/week-1-2.md).
> Mapping: Tasks 1,2,3,7(components),8 → PR #1 · Tasks 9,10,14 → PR #2 ·
> Tasks 11,12,13 → PR #3 · Tasks 6,8(secrets CLI) → PR #4 · Task 4 → PR #5.

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Ship the eight Week 1–2 Foundation Handoff deliverables — monorepo wiring, CI/CD, GCP Terraform, observability, secret management, auth foundation, design system, and event schema v1 — so the Week 3 Auth+Task-Capture vertical slice can start clean on Day 1.
Expand Down
Loading