diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index faae98c..8a83de5 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -40,8 +40,8 @@ Requirements for beta-ready release. Each maps to roadmap phases. ### Admin Portal -- [ ] **PRTA-01**: Operator can create, view, update, and delete tenants -- [ ] **PRTA-02**: Operator can design agents via a dedicated Agent Designer module — defining job description, statement of work, persona, system prompt, tool assignments, and escalation rules +- [x] **PRTA-01**: Operator can create, view, update, and delete tenants +- [x] **PRTA-02**: Operator can design agents via a dedicated Agent Designer module — defining job description, statement of work, persona, system prompt, tool assignments, and escalation rules - [ ] **PRTA-03**: Operator can connect messaging channels (Slack, WhatsApp) via guided wizard - [ ] **PRTA-04**: New tenants are guided through structured onboarding (connect channel, configure agent, test message) - [ ] **PRTA-05**: Operator can manage subscription plans and billing via Stripe integration @@ -114,8 +114,8 @@ Which phases cover which requirements. Updated during roadmap creation. | TNNT-02 | Phase 1 | Complete | | TNNT-03 | Phase 1 | Complete | | TNNT-04 | Phase 1 | Complete | -| PRTA-01 | Phase 1 | Pending | -| PRTA-02 | Phase 1 | Pending | +| PRTA-01 | Phase 1 | Complete | +| PRTA-02 | Phase 1 | Complete | | PRTA-03 | Phase 3 | Pending | | PRTA-04 | Phase 3 | Pending | | PRTA-05 | Phase 3 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 3b577dc..e26a7d9 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -77,7 +77,7 @@ Phases execute in numeric order: 1 → 2 → 3 | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| -| 1. Foundation | 2/4 | In Progress| | +| 1. Foundation | 3/4 | In Progress| | | 2. Agent Features | 0/4 | Not started | - | | 3. Operator Experience | 0/2 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index fff6279..1d12d0c 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: planning -stopped_at: Completed 01-foundation 01-02-PLAN.md -last_updated: "2026-03-23T16:08:44.982Z" +stopped_at: Completed 01-foundation 01-04-PLAN.md +last_updated: "2026-03-23T16:22:05.663Z" last_activity: 2026-03-23 — Roadmap created, ready for Phase 1 planning progress: total_phases: 3 completed_phases: 0 total_plans: 4 - completed_plans: 2 + completed_plans: 3 percent: 0 --- @@ -52,6 +52,7 @@ Progress: [░░░░░░░░░░] 0% *Updated after each plan completion* | Phase 01-foundation P01 | 12 | 2 tasks | 32 files | | Phase 01-foundation P02 | 6 | 2 tasks | 15 files | +| Phase 01-foundation P04 | 19 | 2 tasks | 25 files | ## Accumulated Context @@ -70,6 +71,9 @@ Recent decisions affecting current work: - [Phase 01-foundation]: Celery tasks are always sync def with asyncio.run() — hard architectural constraint, never async def - [Phase 01-foundation]: AI transparency clause is unconditional in system prompt — agents must disclose AI identity when directly asked - [Phase 01-foundation]: llm-pool port 8004 (consistent with shared/config.py llm_pool_url default, not plan-stated 8002) +- [Phase 01-foundation]: proxy.ts used instead of middleware.ts — Next.js 16 renamed middleware to proxy +- [Phase 01-foundation]: standardSchemaResolver used over zodResolver — hookform/resolvers v5 dropped zod subpackage, uses Standard Schema protocol; zod v4 implements Standard Schema +- [Phase 01-foundation]: Auth.js v5 JWT session strategy chosen — no portal_sessions DB table needed for Phase 1, stateless tokens sufficient ### Pending Todos @@ -81,6 +85,6 @@ None yet. ## Session Continuity -Last session: 2026-03-23T16:08:44.980Z -Stopped at: Completed 01-foundation 01-02-PLAN.md +Last session: 2026-03-23T16:22:05.661Z +Stopped at: Completed 01-foundation 01-04-PLAN.md Resume file: None diff --git a/.planning/phases/01-foundation/01-04-SUMMARY.md b/.planning/phases/01-foundation/01-04-SUMMARY.md new file mode 100644 index 0000000..a0ac67a --- /dev/null +++ b/.planning/phases/01-foundation/01-04-SUMMARY.md @@ -0,0 +1,199 @@ +--- +phase: 01-foundation +plan: 04 +subsystem: ui +tags: [nextjs, next-auth, tanstack-query, react-hook-form, zod, shadcn, fastapi, bcrypt, tailwind] + +# Dependency graph +requires: + - phase: 01-foundation plan 01 + provides: "PostgreSQL schema with Tenant, Agent, PortalUser ORM models and RLS infrastructure" +provides: + - FastAPI portal API router at /api/portal (tenant CRUD, agent CRUD, auth verify/register) + - Next.js 16 admin portal at localhost:3000 with login, tenant management, and Agent Designer + - Auth.js v5 Credentials provider validating against FastAPI /auth/verify endpoint + - proxy.ts (Next.js 16 auth proxy) protecting all routes except /login and /api/auth/* + - Integration tests for all portal API CRUD operations (38 tests) +affects: [02-channel-expansion, 03-polish-launch, operator-workflow] + +# Tech tracking +tech-stack: + added: + - "bcrypt>=4.0.0 (password hashing in shared package)" + - "next-auth@5.0.0-beta.30 (Auth.js v5 with Credentials provider)" + - "@tanstack/react-query@^5 (server state and cache management)" + - "react-hook-form@^7 (form management)" + - "zod@^4 (schema validation)" + - "@hookform/resolvers@^5 (standard-schema resolver for zod v4 compat)" + - "shadcn/ui (button, card, input, textarea, select, badge, table, dialog, separator, label)" + - "lucide-react (icons)" + patterns: + - "FastAPI APIRouter with prefix /api/portal for portal-specific endpoints" + - "Portal API sets RLS current_tenant_id context for agent endpoints (admin bypasses but still scopes correctly)" + - "Auth.js v5 JWT strategy — no DB session table, stateless tokens" + - "Next.js 16 route groups: (auth) for login, (dashboard) for protected routes with shared layout" + - "TanStack Query hooks in lib/queries.ts with standardized query key hierarchy" + - "standardSchemaResolver from @hookform/resolvers/standard-schema for zod v4 + hookform v5 compat" + - "proxy.ts instead of middleware.ts — Next.js 16 renamed middleware to proxy" + +key-files: + created: + - "packages/shared/shared/api/__init__.py — portal_router export" + - "packages/shared/shared/api/portal.py — FastAPI portal router with all CRUD endpoints" + - "tests/integration/test_portal_tenants.py — 23 tenant CRUD integration tests" + - "tests/integration/test_portal_agents.py — 15 agent CRUD + Agent Designer field tests" + - "packages/portal/proxy.ts — auth proxy protecting dashboard routes" + - "packages/portal/lib/auth.ts — Auth.js v5 config with Credentials provider" + - "packages/portal/lib/api.ts — typed fetch wrapper + API type definitions" + - "packages/portal/lib/queries.ts — TanStack Query hooks for tenants and agents" + - "packages/portal/components/agent-designer.tsx — Agent Designer form (Identity/Personality/Config/Capabilities/Escalation/Status)" + - "packages/portal/components/tenant-form.tsx — reusable tenant create/edit form" + - "packages/portal/components/nav.tsx — sidebar navigation (Dashboard/Tenants/Employees)" + - "packages/portal/app/(dashboard)/layout.tsx — shared dashboard layout with QueryClientProvider" + - "packages/portal/app/(dashboard)/dashboard/page.tsx — dashboard landing with tenant count" + - "packages/portal/app/(dashboard)/tenants/page.tsx — tenant list with table UI" + - "packages/portal/app/(dashboard)/tenants/new/page.tsx — tenant creation" + - "packages/portal/app/(dashboard)/tenants/[id]/page.tsx — tenant detail/edit/delete" + - "packages/portal/app/(dashboard)/agents/page.tsx — AI employees card grid" + - "packages/portal/app/(dashboard)/agents/new/page.tsx — Agent Designer create" + - "packages/portal/app/(dashboard)/agents/[id]/page.tsx — Agent Designer edit" + - "packages/portal/app/(auth)/login/page.tsx — email/password login form" + - "packages/portal/app/api/auth/[...nextauth]/route.ts — Auth.js route handler" + modified: + - "packages/shared/pyproject.toml — added bcrypt>=4.0.0 dependency" + - "docker-compose.yml — added portal service on port 3000" + - "packages/portal/app/layout.tsx — updated metadata title to 'Konstruct Portal'" + - "packages/portal/app/page.tsx — redirect to /dashboard or /login based on auth state" + +key-decisions: + - "proxy.ts used instead of middleware.ts — Next.js 16 renamed middleware to proxy (deprecated warning)" + - "standardSchemaResolver from @hookform/resolvers/standard-schema used instead of zodResolver — @hookform/resolvers v5 removed dedicated zod subpackage in favor of Standard Schema protocol; zod v4 implements Standard Schema" + - "Route group (dashboard) used to share QueryClientProvider layout across /dashboard, /tenants, /agents routes without nesting them under a path prefix" + - "Portal agent endpoints set RLS current_tenant_id context before DB operations — platform admin API still operates within tenant scope per RLS policy" + - "Auth.js v5 JWT session strategy — no portal_sessions table needed for Phase 1; stateless tokens sufficient until enterprise SSO requirements" + - "Agent Designer uses employee-centric labels: Employee Name, Job Title, Job Description (persona), Statement of Work (system_prompt)" + +patterns-established: + - "Pattern 1: FastAPI portal router sets RLS tenant context via current_tenant_id ContextVar for all agent CRUD operations" + - "Pattern 2: Integration tests use make_app(session) factory to override get_session dependency with test DB session" + - "Pattern 3: Next.js 16 uses proxy.ts for edge-layer auth protection; Auth.js v5 auth() called directly in proxy" + - "Pattern 4: TanStack Query key hierarchy [resource, ...params] enables targeted cache invalidation on mutations" + - "Pattern 5: Zod v4 + @hookform/resolvers v5 via standardSchemaResolver (not zodResolver)" + +requirements-completed: [PRTA-01, PRTA-02] + +# Metrics +duration: 19min +completed: 2026-03-23 +--- + +# Phase 1 Plan 4: Portal — Tenant CRUD and Agent Designer Summary + +**FastAPI portal API with bcrypt auth + Next.js 16 admin portal featuring Auth.js v5 login, tenant management, and a full-featured Agent Designer for defining AI employees** + +## Performance + +- **Duration:** 19 min +- **Started:** 2026-03-23T16:01:33Z +- **Completed:** 2026-03-23T16:20:09Z +- **Tasks:** 2 +- **Files modified:** 25+ (new portal package + shared API) + +## Accomplishments + +- FastAPI portal router at /api/portal with full tenant CRUD, agent CRUD, and bcrypt auth endpoints +- Agent endpoints correctly set PostgreSQL RLS current_tenant_id context for policy compliance +- 38 integration tests prove all CRUD operations, validation, uniqueness constraints, and tenant isolation +- Next.js 16 portal builds cleanly with Auth.js v5 Credentials provider, proxy.ts auth guard +- Agent Designer with 6 grouped sections (Identity, Personality, Configuration, Capabilities, Escalation, Status) using employee-centric language throughout +- Tenant management: list with slug badges, create with auto-slug generation, edit, delete with cascade confirmation + +## Task Commits + +1. **Task 1: FastAPI portal API endpoints** - `7b348b9` (feat) +2. **Task 2: Next.js portal with Auth.js v5 and Agent Designer** - `cec7180` (feat) + +## Files Created/Modified + +- `/home/adelorenzo/repos/konstruct/packages/shared/shared/api/portal.py` — FastAPI portal router with all endpoints +- `/home/adelorenzo/repos/konstruct/packages/shared/shared/api/__init__.py` — exports portal_router +- `/home/adelorenzo/repos/konstruct/tests/integration/test_portal_tenants.py` — 23 tenant CRUD tests +- `/home/adelorenzo/repos/konstruct/tests/integration/test_portal_agents.py` — 15 agent + Agent Designer tests +- `/home/adelorenzo/repos/konstruct/packages/portal/proxy.ts` — Next.js 16 auth proxy +- `/home/adelorenzo/repos/konstruct/packages/portal/lib/auth.ts` — Auth.js v5 config +- `/home/adelorenzo/repos/konstruct/packages/portal/lib/api.ts` — typed fetch client +- `/home/adelorenzo/repos/konstruct/packages/portal/lib/queries.ts` — TanStack Query hooks +- `/home/adelorenzo/repos/konstruct/packages/portal/components/agent-designer.tsx` — Agent Designer form +- `/home/adelorenzo/repos/konstruct/packages/portal/components/tenant-form.tsx` — tenant form +- `/home/adelorenzo/repos/konstruct/packages/portal/components/nav.tsx` — sidebar nav + +## Decisions Made + +- **proxy.ts over middleware.ts:** Next.js 16 renamed `middleware.ts` to `proxy.ts`. The old name generates a deprecation warning. Used the new convention throughout. +- **standardSchemaResolver over zodResolver:** `@hookform/resolvers@5` no longer ships a dedicated `/zod` subpackage. It uses the Standard Schema protocol instead, and zod v4 implements Standard Schema. Using `standardSchemaResolver` from `@hookform/resolvers/standard-schema` is the correct integration pattern. +- **Route group (dashboard):** Moving tenant and agent routes into an `(dashboard)` route group shares the `QueryClientProvider` layout without adding `/dashboard` to the URL path. Clean separation of public (`(auth)`) and protected (`(dashboard)`) routes. +- **Auth.js v5 JWT strategy:** No `portal_sessions` table required for Phase 1. JWT tokens stored in httpOnly cookies via Auth.js session strategy. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Agent portal endpoints set RLS tenant context** +- **Found during:** Task 1 (integration test execution) +- **Issue:** `POST /tenants/{tenant_id}/agents` raised `InsufficientPrivilegeError: new row violates row-level security policy for table "agents"` — the portal API connected as `konstruct_app` role but didn't set `app.current_tenant` session variable before inserting +- **Fix:** Added `current_tenant_id.set(tenant_id)` context manager around all agent DB operations in portal.py endpoints +- **Files modified:** packages/shared/shared/api/portal.py +- **Verification:** All 38 integration tests pass including agent create/read/update/delete +- **Committed in:** 7b348b9 (Task 1 commit) + +**2. [Rule 3 - Blocking] Next.js 16 renamed middleware.ts to proxy.ts** +- **Found during:** Task 2 (reading Next.js 16 docs per CLAUDE.md/AGENTS.md instruction) +- **Issue:** Plan specified creating `middleware.ts`; Next.js 16 deprecates this in favor of `proxy.ts` with a `proxy()` export +- **Fix:** Created `proxy.ts` with `export async function proxy()` and `export const config` matcher +- **Files modified:** packages/portal/proxy.ts (created instead of middleware.ts) +- **Verification:** Build output shows `ƒ Proxy (Middleware)` — proxy is active +- **Committed in:** cec7180 (Task 2 commit) + +**3. [Rule 3 - Blocking] zodResolver replaced with standardSchemaResolver** +- **Found during:** Task 2 (TypeScript build error) +- **Issue:** `@hookform/resolvers@5` removed the `/zod` subpackage — TypeScript error `Type 'Resolver<...string | undefined...>' is not assignable to type 'Resolver<...string...>'` because the new standard-schema protocol handles zod v4 output type inference differently +- **Fix:** Changed all imports from `zodResolver` (`@hookform/resolvers/zod`) to `standardSchemaResolver` (`@hookform/resolvers/standard-schema`) in login page, agent-designer, and tenant-form +- **Files modified:** app/(auth)/login/page.tsx, components/agent-designer.tsx, components/tenant-form.tsx +- **Verification:** `npm run build` exits 0 with no TypeScript errors +- **Committed in:** cec7180 (Task 2 commit) + +**4. [Rule 3 - Blocking] Route group reorganization for QueryClientProvider scope** +- **Found during:** Task 2 (Next.js prerender error) +- **Issue:** `Error: No QueryClient set, use QueryClientProvider to set one` — `/agents` and `/tenants` routes were outside the `dashboard/layout.tsx` so they didn't get the QueryClientProvider wrapper +- **Fix:** Created `(dashboard)` route group with shared `layout.tsx`, moved `/dashboard`, `/tenants`, and `/agents` routes under it. URLs remain the same (`/tenants`, `/agents`, `/dashboard`) since route groups don't add path segments. +- **Files modified:** entire app route structure reorganized into (auth) and (dashboard) groups +- **Verification:** `npm run build` completes successfully with all 10 routes rendered +- **Committed in:** cec7180 (Task 2 commit) + +--- + +**Total deviations:** 4 auto-fixed (1 bug, 3 blocking) +**Impact on plan:** All auto-fixes necessary for correctness and functionality. No scope creep. Deviations 2-4 are Next.js 16 + ecosystem version adaptations. + +## Issues Encountered + +- `create-next-app` initialized a nested `.git` repo inside `packages/portal/` — removed with `rm -rf packages/portal/.git` before committing to prevent git submodule confusion. + +## User Setup Required + +None — portal uses email/password auth against local DB, no external OAuth providers needed in Phase 1. + +## Next Phase Readiness + +- Portal API endpoints ready to receive connections from the gateway service (Plan 01-02, 01-03) +- Auth.js session ready; will need `AUTH_SECRET` env var set in production +- Agent Designer stores all fields needed for agent orchestration (Phase 2) +- Portal service added to docker-compose.yml — requires `npm run build` output or container build before running + +## Self-Check: PASSED + +All created files verified on disk. Both task commits (7b348b9, cec7180) confirmed in git log. + +--- +*Phase: 01-foundation* +*Completed: 2026-03-23*