-
Notifications
You must be signed in to change notification settings - Fork 1
docs(009): update tasks.md with completion status and what-to-do-next roadmap #505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
8
commits into
main
Choose a base branch
from
copilot/vscode-mmz66374-oe5b
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
aa1e636
Initial plan
Copilot a777a22
chore: initial plan for spec 009 user directory
Copilot 0fd4353
feat(009): implement user directory - migration, service, API routes,…
Copilot afe55bf
fix(ci): replace next lint with ESLint flat config, fix all lint errors
Copilot 2370c32
Checkpoint from VS Code for cloud agent session
MikeWedderburn-Clarke 13fe52f
merge: integrate origin/main (spec 010 events explorer) + fix lint er…
Copilot 36b70d7
Merge remote-tracking branch 'origin/copilot/009-user-directory-imple…
Copilot 35dd124
docs(009): update tasks.md with completion status after branch review
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,76 +1,76 @@ | ||
| # Copilot Coding Agent Instructions | ||
|
|
||
| This project uses the **Spec-Kit** agentic development process. Every change | ||
| MUST follow these rules. Violations will be caught by CI and rejected. | ||
|
|
||
| ## Before Writing Any Code | ||
|
|
||
| 1. **Find the relevant spec** — Check `specs/` for the feature spec matching | ||
| your issue. Read spec.md, plan.md, tasks.md, and data-model.md before coding. | ||
| 2. **Read the constitution** — `specs/constitution.md` (v1.4.0) defines 13 | ||
| mandatory architectural principles. Key constraints: | ||
| - **I. API-First**: All mutations go through API routes, never direct DB from components. | ||
| Response shapes live in `packages/shared/src/types/`. Error responses use `@/lib/errors`. | ||
| - **II. Test-First**: Every service function needs an integration test. Use `createTestDb()` for PGlite isolation. | ||
| - **III. Privacy**: PII encrypted at rest, EXIF stripped from uploads, GDPR deletion covers all tables. | ||
| - **IV. Server-Side Authority**: Zod schemas validate all request bodies. No trusting client input. | ||
| - **IX. Scoped Permissions**: Use `withPermission()` middleware on all admin/mutation endpoints. | ||
| - **XI. Resource Ownership**: Every mutation verifies caller owns the resource or holds scoped admin. | ||
| - **XII. Financial Integrity**: Server-side pricing only. Stripe Connect with signed OAuth state. | ||
| 3. **Check tasks.md** — If your issue maps to a task, mark it `[X]` when done. | ||
|
|
||
| ## Monorepo Structure | ||
|
|
||
| npm workspaces monorepo — always run commands from the repo root: | ||
|
|
||
| | Workspace | Package | Purpose | | ||
| |-----------|---------|---------| | ||
| | `apps/web/` | `@acroyoga/web` | Next.js 16 web app (App Router, React 19) | | ||
| | `packages/shared/` | `@acroyoga/shared` | Shared TypeScript types and contracts | | ||
| | `packages/shared-ui/` | `@acroyoga/shared-ui` | 15 cross-platform UI components (design tokens) | | ||
| | `packages/tokens/` | `@acroyoga/tokens` | Design token pipeline — **must build before other packages** | | ||
|
|
||
| ## Validation Checklist — REQUIRED Before Completing Any Task | ||
|
|
||
| Run these in order. All must pass: | ||
|
|
||
| npm run tokens:build -w @acroyoga/tokens # 1. Build tokens (prerequisite) | ||
| npm run typecheck # 2. Zero type errors | ||
| npm run lint -w @acroyoga/web # 3. Zero lint warnings | ||
| npm run test # 4. All tests pass (tokens > shared-ui > web) | ||
| npm run build -w @acroyoga/web # 5. Production build succeeds | ||
|
|
||
| If you add a new API route, you MUST also: | ||
| - Add integration tests in `apps/web/tests/integration/` | ||
| - Test 403 for unauthorized callers (Constitution QG-10) | ||
| - Use `createTestDb()` for PGlite test isolation | ||
|
|
||
| ## Auth Pattern | ||
|
|
||
| - Web: `getServerSession()` / `requireAuth()` — session-based only | ||
| - Never trust client-injectable headers (`x-user-id`, `x-api-key` etc.) | ||
| - Admin routes: `withPermission()` middleware, not bare `requireAuth()` | ||
|
|
||
| ## Code Conventions | ||
|
|
||
| - TypeScript strict mode — no `any`, no `@ts-ignore` | ||
| - Zod schemas at all API boundaries (no manual `typeof` checks) | ||
| - SQL migrations: `apps/web/src/db/migrations/` (raw SQL, no ORM) | ||
| - Response types: `packages/shared/src/types/` | ||
| - Error responses: `{ error: string, code: string, details?: unknown }` via `@/lib/errors` | ||
| - No hardcoded user-facing strings (i18n extractable, Constitution VIII) | ||
| - No N+1 queries — use JOINs or `WHERE IN` for lists (Constitution VI) | ||
|
|
||
| ## Quality Gates (enforced by CI) | ||
|
|
||
| The CI pipeline (`.github/workflows/ci.yml`) runs on every PR: | ||
|
|
||
| 1. Typecheck (`tsc -b`) | ||
| 2. Lint (ESLint + jsx-a11y) | ||
| 3. Build (Next.js production) | ||
| 4. Bundle size <=200KB compressed | ||
| 5. All tests: tokens (20), shared-ui (85), web (339+) | ||
| 6. i18n string lint | ||
| 7. Storybook build + a11y audit (axe-core) | ||
|
|
||
| Your PR will be blocked if any gate fails. Fix before requesting review. | ||
| # Copilot Coding Agent Instructions | ||
| This project uses the **Spec-Kit** agentic development process. Every change | ||
| MUST follow these rules. Violations will be caught by CI and rejected. | ||
| ## Before Writing Any Code | ||
| 1. **Find the relevant spec** — Check `specs/` for the feature spec matching | ||
| your issue. Read spec.md, plan.md, tasks.md, and data-model.md before coding. | ||
| 2. **Read the constitution** — `specs/constitution.md` (v1.4.0) defines 13 | ||
| mandatory architectural principles. Key constraints: | ||
| - **I. API-First**: All mutations go through API routes, never direct DB from components. | ||
| Response shapes live in `packages/shared/src/types/`. Error responses use `@/lib/errors`. | ||
| - **II. Test-First**: Every service function needs an integration test. Use `createTestDb()` for PGlite isolation. | ||
| - **III. Privacy**: PII encrypted at rest, EXIF stripped from uploads, GDPR deletion covers all tables. | ||
| - **IV. Server-Side Authority**: Zod schemas validate all request bodies. No trusting client input. | ||
| - **IX. Scoped Permissions**: Use `withPermission()` middleware on all admin/mutation endpoints. | ||
| - **XI. Resource Ownership**: Every mutation verifies caller owns the resource or holds scoped admin. | ||
| - **XII. Financial Integrity**: Server-side pricing only. Stripe Connect with signed OAuth state. | ||
| 3. **Check tasks.md** — If your issue maps to a task, mark it `[X]` when done. | ||
| ## Monorepo Structure | ||
| npm workspaces monorepo — always run commands from the repo root: | ||
| | Workspace | Package | Purpose | | ||
| |-----------|---------|---------| | ||
| | `apps/web/` | `@acroyoga/web` | Next.js 16 web app (App Router, React 19) | | ||
| | `packages/shared/` | `@acroyoga/shared` | Shared TypeScript types and contracts | | ||
| | `packages/shared-ui/` | `@acroyoga/shared-ui` | 15 cross-platform UI components (design tokens) | | ||
| | `packages/tokens/` | `@acroyoga/tokens` | Design token pipeline — **must build before other packages** | | ||
| ## Validation Checklist — REQUIRED Before Completing Any Task | ||
| Run these in order. All must pass: | ||
| npm run tokens:build -w @acroyoga/tokens # 1. Build tokens (prerequisite) | ||
| npm run typecheck # 2. Zero type errors | ||
| npm run lint -w @acroyoga/web # 3. Zero lint warnings | ||
| npm run test # 4. All tests pass (tokens > shared-ui > web) | ||
| npm run build -w @acroyoga/web # 5. Production build succeeds | ||
| If you add a new API route, you MUST also: | ||
| - Add integration tests in `apps/web/tests/integration/` | ||
| - Test 403 for unauthorized callers (Constitution QG-10) | ||
| - Use `createTestDb()` for PGlite test isolation | ||
| ## Auth Pattern | ||
| - Web: `getServerSession()` / `requireAuth()` — session-based only | ||
| - Never trust client-injectable headers (`x-user-id`, `x-api-key` etc.) | ||
| - Admin routes: `withPermission()` middleware, not bare `requireAuth()` | ||
| ## Code Conventions | ||
| - TypeScript strict mode — no `any`, no `@ts-ignore` | ||
| - Zod schemas at all API boundaries (no manual `typeof` checks) | ||
| - SQL migrations: `apps/web/src/db/migrations/` (raw SQL, no ORM) | ||
| - Response types: `packages/shared/src/types/` | ||
| - Error responses: `{ error: string, code: string, details?: unknown }` via `@/lib/errors` | ||
| - No hardcoded user-facing strings (i18n extractable, Constitution VIII) | ||
| - No N+1 queries — use JOINs or `WHERE IN` for lists (Constitution VI) | ||
| ## Quality Gates (enforced by CI) | ||
| The CI pipeline (`.github/workflows/ci.yml`) runs on every PR: | ||
| 1. Typecheck (`tsc -b`) | ||
| 2. Lint (ESLint + jsx-a11y) | ||
| 3. Build (Next.js production) | ||
| 4. Bundle size <=200KB compressed | ||
| 5. All tests: tokens (20), shared-ui (85), web (339+) | ||
| 6. i18n string lint | ||
| 7. Storybook build + a11y audit (axe-core) | ||
| Your PR will be blocked if any gate fails. Fix before requesting review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| name: "Copilot Setup Steps" | ||
|
|
||
| on: workflow_dispatch | ||
|
|
||
| jobs: | ||
| setup: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "24" | ||
| cache: "npm" | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Build design tokens | ||
| run: npm run tokens:build -w @acroyoga/tokens | ||
|
|
||
| - name: Typecheck | ||
| run: npm run typecheck | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| const endpoints = ["/api/events", "/api/teachers", "/api/venues", "/", "/events", "/teachers", "/profile"]; | ||
| for (const ep of endpoints) { | ||
| const r = await fetch("http://localhost:3000" + ep); | ||
| const t = await r.text(); | ||
| const preview = ep.startsWith("/api") ? t.substring(0, 200) : t.length + " bytes"; | ||
| console.log(ep, "STATUS:", r.status, preview); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| const endpoints = ["/api/events", "/api/teachers", "/api/dev/mock-user"]; | ||
| for (const ep of endpoints) { | ||
| const r = await fetch("http://localhost:3000" + ep); | ||
| const data = await r.json(); | ||
| if (ep === "/api/events") { | ||
| console.log("EVENTS:", data.total, "items. Titles:", data.events.map(function(e){ return e.title }).join(", ")); | ||
| } else if (ep === "/api/teachers") { | ||
| console.log("TEACHERS:", data.total, "items. IDs:", data.teachers.map(function(t){ return t.user_id.slice(-2) }).join(", ")); | ||
| } else { | ||
| console.log("MOCK USERS:", data.availableUsers ? data.availableUsers.length : "N/A", "available"); | ||
| if (data.availableUsers) data.availableUsers.forEach(function(u){ console.log(" -", u.name, "(" + u.displayRole + ")") }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 17 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Copilot Autofix
AI 17 days ago
In general, the fix is to define an explicit
permissions:block in the workflow, granting only the minimal rights needed. For a build/test workflow like this that only checks out code and runs local Node commands,contents: readis typically sufficient, and optionallypackages: readif private packages are involved.For this specific file, the safest and simplest change is to add a top-level
permissions:block (applies to all jobs) right after theon:section, settingcontents: read. This documents the intended least privilege and ensures that even if repository defaults are broad or change later, thesetupjob will only have read access to repository contents. No existing functionality needs write access, so this change will not affect behavior. No additional imports or methods are required; this is purely a YAML workflow configuration change within.github/workflows/copilot-setup-steps.yml.