feat(billing): plan taxonomy reconciliation + Stripe sync + internal-tester allowlist #164
@@ -13,6 +13,54 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-07 — Per-email allowlist (`INTERNAL_TESTER_EMAILS`) for self-serve soft cutover
|
||||
|
||||
**Context:** Phase O Task 46 ("internal validation pass") needed a way to exercise the full self-serve flow against the prod backend before flipping `SELF_SERVE_ENABLED=true` for everyone. The plan doc described the mechanism but the backend support was never built — flagged in `SESSION_LOG.md` as a code blocker. Stripe live-mode setup is also gated on having a working internal-tester path in prod test mode.
|
||||
|
||||
**Decision:** Comma-separated allowlist `INTERNAL_TESTER_EMAILS` parsed by a Pydantic field_validator into a normalized lowercase list. Two helpers on `Settings`: `is_internal_tester(email)` (case-insensitive membership check) and `is_self_serve_active_for(email)` (returns `SELF_SERVE_ENABLED OR is_internal_tester(email)`). Both endpoints that gate on the global flag now call the helper:
|
||||
- `/config/public` accepts optional auth via new `get_current_user_optional` dep; returns `self_serve_enabled=true` for allowlisted authenticated callers; anonymous calls always see the global flag.
|
||||
- `/auth/register` allows allowlisted emails to register without an invite code.
|
||||
|
||||
**Rejected:**
|
||||
- **Custom header `X-Internal-Tester-Email` for anonymous flows.** Spoofable. The auth/register-payload checks are sufficient because the user has to OWN the email to register or log in.
|
||||
- **Separate allowlists per surface (`INTERNAL_PRICING_TESTERS`, `INTERNAL_OAUTH_TESTERS`).** Premature splitting. The Phase O use case is "this small set of people can see the new flow"; one variable handles it. If finer granularity emerges, split then.
|
||||
- **Database table for the allowlist.** Env var matches the spec from the plan doc and fits the soft-cutover lifecycle — list is small, changes infrequently, lives alongside other deployment-time config.
|
||||
|
||||
**Consequences:**
|
||||
- Stripe internal validation can run end-to-end in prod test mode without flipping the global flag.
|
||||
- Anonymous callers always see the global flag — the allowlist never leaks via unauthenticated request content. Three regression tests in `test_config_public.py` enforce this.
|
||||
- `INTERNAL_TESTER_EMAILS` plumbed through `docker-compose.dev.yml` and documented in `backend/.env.example`. Railway prod env will need the same var set during Phase O cutover.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-07 — Reconcile plan tier taxonomy (rename `team` → `enterprise`, add `starter`)
|
||||
|
||||
**Context:** PR #162 left a real architectural gap. Marketing surface (PricingPage, Stripe products) was wired for `Starter / Pro / Enterprise` while backend was on `free / pro / team`. `plan_billing.plan` FK referenced `plan_limits.plan` so the `BillingPlan` schema's `Literal["pro", "starter", "team", "enterprise"]` could accept values that violated the FK. `plan_billing` was unseeded in dev, so no checkout could complete. `Subscription.plan.in_(["pro", "team"])` paid-plan checks wouldn't recognize `enterprise`. Self-serve cutover was blocked at the data layer.
|
||||
|
||||
**Decision:** Reconcile to a single taxonomy — backend slugs become `free / pro / starter / enterprise`, matching the marketing surface and Stripe products. Migration `4ce3e594cb87`:
|
||||
1. Defensive `UPDATE subscriptions SET plan='enterprise' WHERE plan='team'` (dev had zero such rows; safety for any prod stragglers).
|
||||
2. Rename the `plan_limits.plan='team'` row to `'enterprise'`.
|
||||
3. Insert a `starter` row with caps interpolated between free and pro: `max_trees=10`, `max_sessions=75`, `max_users=1`, `max_ai_builds_per_month=15`, no KB Accelerator, no custom branding, no priority support.
|
||||
|
||||
Code rename across schemas, `Subscription` paid-plan/`has_pro_entitlement` checks, admin endpoints, frontend `useSubscription.isPaidPlan`. Resource visibility (`Tree.visibility='team'`, `StepLibrary.visibility='team'`) is a separate domain and intentionally untouched — that string means "shared with my account" and has nothing to do with the subscription tier.
|
||||
|
||||
New `backend/scripts/sync_stripe_plan_ids.py` — idempotent upsert of `plan_billing` rows from Stripe products by exact name match (`ResolutionFlow Starter / Pro / Enterprise`). Picks the active monthly recurring price for tiers that have one. Annual fields stay NULL by design — annual pricing is intentionally out of scope for the soft cutover ("want to be able to exit if necessary without breaching any terms").
|
||||
|
||||
**Rejected:**
|
||||
- **Map marketing names to existing slugs (Option A from the discussion).** Smallest diff but means PricingPage cards have to translate `enterprise` → `team` at render time, and "Starter" can't exist as a real backend tier — it'd have to be hidden or dropped. Kicks the can.
|
||||
- **Add `starter` only, keep `team` slug as cosmetic enterprise (Option C).** Mixed taxonomy across layers — slug-vs-display-name divergence guarantees confusion in 6 months. Compromise that's worse than either pure choice.
|
||||
- **Annual pricing in this iteration.** User's explicit constraint: skip annual to keep exit-flexibility. Schema columns (`annual_price_cents`, `stripe_annual_price_id`) preserved as nullable for future re-enable.
|
||||
- **Auto-archive the existing Enterprise `$500/mo` test-mode price.** Done manually via Stripe MCP after un-setting the product's `default_price` first. Spec says Enterprise is sales-led with no catalog price.
|
||||
|
||||
**Consequences:**
|
||||
- `plan_billing` table is now seedable and seeded. Test-mode `plan_billing` populated for all 3 tiers via `sync_stripe_plan_ids.py`. Live mode runs the same script after manual Dashboard setup of products + prices.
|
||||
- New consumers of `Subscription.plan` literal must use `("free", "pro", "starter", "enterprise")`. Three call sites already updated. Backend-wide grep is the safety net for new ones.
|
||||
- `Subscription.is_paid` and `has_pro_entitlement` now include `starter` — Starter is a paid tier with a real $19.99/mo price.
|
||||
- 86/86 passing across the subscription/billing/plan/invite/admin sweep after the rename.
|
||||
- Test fixtures: `conftest.py` plan_limits seed updated to the new taxonomy. `_seed_plan_limits` helper in `test_plans_public.py` is now a true upsert so tests can override `max_users` even when conftest seeded the canonical value.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-07 — Standardize backend Python on 3.12
|
||||
|
||||
**Context:** Runtime facts had drifted from docs. The backend Dockerfiles and running dev container were already on Python 3.12, GitHub CI had just been updated to 3.12, but project docs still said Python 3.11 and Gitea CI relied on the runner's ambient Python.
|
||||
|
||||
@@ -7,4 +7,6 @@ GOOGLE_AI_API_KEY=
|
||||
STRIPE_SECRET_KEY=sk_test_
|
||||
STRIPE_PUBLISHABLE_KEY=pk_test_
|
||||
STRIPE_WEBHOOK_SECRET=whsec_
|
||||
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_
|
||||
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_
|
||||
|
||||
INTERNAL_TESTER_EMAILS=internaltest@resolutionflow.com
|
||||
@@ -1,11 +1,25 @@
|
||||
# Development Roadmap
|
||||
|
||||
> **Last Updated:** March 18, 2026
|
||||
> **Product:** ResolutionFlow (repo: patherly)
|
||||
> **Last Updated:** May 7, 2026
|
||||
> **Product:** ResolutionFlow (repo path: `resolutionflow/`; `patherly` is the legacy internal name)
|
||||
> **Target Market:** MSP companies — IT service providers managing infrastructure and support for multiple clients
|
||||
|
||||
---
|
||||
|
||||
## Status as of 2026-05-07
|
||||
|
||||
The historical phase content below (Phase 1 through Phase 5) is preserved as a factual record. **This section is the live status overlay — read it first.**
|
||||
|
||||
**Where we are:** Pre-PMF, Go-to-Market Validation. Backend feature-complete (50+ endpoints, 100+ tests). FlowPilot session UX is the daily-driver surface and recently went through PR #155 (escalation wedge), #156 (`applied_pending` non-terminal status), #158 (impeccable pass + tasklane keyboard flow), #159 (Diátaxis User Guides), #160 (sidebar IA + account redesign).
|
||||
|
||||
**Currently in flight:** Self-serve signup cutover. Phase 1 backend (#161) and Phase 2 frontend (#162) merged. PR #164 (open) closes the last code blockers — plan taxonomy reconciliation (`team` → `enterprise`, add `starter`) and `INTERNAL_TESTER_EMAILS` allowlist for the soft cutover. After merge, remaining work is **manual operations only**: Stripe Dashboard live-mode setup, Railway prod env vars, internal validation pass, public flag flip. See `docs/superpowers/plans/2026-05-06-self-serve-signup-phase-2-frontend-cutover.md` Phase O for the checklist.
|
||||
|
||||
**Product thesis being tested:** "We're not a documentation app. We are the documentation builders." Captured in `~/.gstack/projects/chihlasm-resolutionflow/abc-feat-self-serve-signup-phase-2-design-20260507-112020.md` (office-hours design doc). Pre-build assignment: 3 calls with external Directors of Onboarding (cold, no friendly contacts) to validate the framing before adopting it as the public positioning.
|
||||
|
||||
**What's not yet decided:** Whether to formally cut branching Flows from the pilot UI surface in favor of a Project (linear procedure) + FlowPilot + Documentation-Builder positioning. Discussed in /office-hours but no implementation work scheduled — gated on the 3 external validation calls.
|
||||
|
||||
---
|
||||
|
||||
## Completed Work
|
||||
|
||||
### Phase 1: MVP
|
||||
@@ -72,13 +86,26 @@
|
||||
|
||||
| Task | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| ConnectWise PSA Integration (Advanced) | In Progress | Core done — ticket linking, note posting, member mapping. Remaining: callback webhooks, deeper ticket context in sessions |
|
||||
| PR #114 Merge | In Progress | Empty states, onboarding, PDF exports, branding, supporting data — ready for review |
|
||||
| Self-serve signup cutover (Phase O) | In Progress | PR #164 merge → Stripe live-mode Dashboard setup → Railway prod env vars → internal validation → public flag flip. Code blockers cleared by #164 (taxonomy + `INTERNAL_TESTER_EMAILS` allowlist). |
|
||||
| External validation of documentation-builder thesis | Not started | 3 calls with external Directors of Onboarding (cold). Decision gate before scoping a "Day 1 onboarding checklist" build. |
|
||||
| ConnectWise PSA Integration (Advanced) | Deferred | Core complete — ticket linking, note posting, member mapping, ticket context retrieval. Callback webhooks deferred until pilot signal demands them. |
|
||||
|
||||
---
|
||||
|
||||
## What's Next
|
||||
|
||||
### Phase O Cutover (Weeks 0-1)
|
||||
|
||||
| Step | Status |
|
||||
|---|---|
|
||||
| Merge PR #164 (taxonomy reconciliation + allowlist) | Open, CI green |
|
||||
| Stripe Dashboard live-mode setup (Products + Prices for Starter/Pro, no Prices on Enterprise, Customer Portal config, webhook endpoint with 5 events) | Manual op |
|
||||
| Railway prod env vars (`sk_live_*`, `whsec_*`, `INTERNAL_TESTER_EMAILS`, prod Google + Microsoft OAuth credentials, `OAUTH_REDIRECT_BASE`, `STRIPE_PUBLISHABLE_KEY`, `VITE_STRIPE_PUBLISHABLE_KEY` for frontend redeploy) | Manual op |
|
||||
| Run `python -m scripts.sync_stripe_plan_ids` against prod backend; verify `plan_billing` has `sk_live_*` price IDs | Manual op |
|
||||
| Internal validation pass (9 scenarios from Phase O Task 46) | Manual op |
|
||||
| Email pilots about complimentary status, flip `SELF_SERVE_ENABLED=true` (frontend redeploy required for `VITE_SELF_SERVE_ENABLED`) | Manual op |
|
||||
| PostHog signup-funnel dashboard + Sentry alert at >1/hour Stripe webhook errors | Manual op |
|
||||
|
||||
### Near-Term Priorities (from Stack Priorities Plan)
|
||||
|
||||
| Feature | Status | Description |
|
||||
@@ -86,7 +113,7 @@
|
||||
| Coverage gates in CI | ✅ Complete | Backend enforced at 80%, frontend coverage reporting enabled |
|
||||
| Security headers | ✅ Complete | HSTS, CSP (report-only), X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy |
|
||||
| Web Vitals / performance budgets | ✅ Complete | LCP, INP, CLS, FCP, TTFB reported to PostHog via web-vitals |
|
||||
| Search and recall improvements | ⬜ Not started | Search sessions by flow, tag, client, ticket context |
|
||||
| Search and recall improvements | ✅ Complete | Structured filters + FTS + Voyage AI semantic search shipped (see CURRENT-STATE.md "Search & Recall" section) |
|
||||
|
||||
### 3A: Quick Wins & UX (Priority: Medium)
|
||||
|
||||
|
||||
@@ -2,16 +2,30 @@
|
||||
|
||||
> **Purpose:** Quick-reference file showing exactly where the project stands.
|
||||
> **For Claude Code:** Read this first to understand what's done and what's next.
|
||||
> **Last Updated:** May 1, 2026
|
||||
> **Last Updated:** May 7, 2026
|
||||
|
||||
---
|
||||
|
||||
## Active Phase: Go-to-Market Validation (Pre-PMF)
|
||||
## Active Phase: Go-to-Market Validation (Pre-PMF) — Self-serve cutover (Phase O) in flight
|
||||
|
||||
Self-serve signup backend (Phase 1) and frontend (Phase 2) are merged. Cutover (Phase O) is gated on manual ops: live-mode Stripe Dashboard config, Railway prod env vars, internal validation pass against prod test mode, then the public flag flip. Plan: `docs/superpowers/plans/2026-05-06-self-serve-signup-phase-2-frontend-cutover.md`.
|
||||
|
||||
---
|
||||
|
||||
## Recently shipped (post-0.1.0.0)
|
||||
|
||||
- **2026-05-07 — PR #164 (open)** Plan taxonomy reconciliation + `INTERNAL_TESTER_EMAILS` allowlist. Marketing surface (PricingPage, Stripe products) used `Starter / Pro / Enterprise` while backend was on `free / pro / team`, leaving `plan_billing` unseeded and `BillingPlan` schema accepting a literal that violated the FK. Migration `4ce3e594cb87`: rename `team` → `enterprise` in `plan_limits`, add `starter` row (caps interpolated between free and pro: `max_trees=10`, `sessions=75`, `ai=15/mo`), defensive update of any subscriptions on the `team` slug. Code rename across schemas, `Subscription` paid-plan checks, admin endpoints, and frontend `useSubscription`. Resource visibility (`Tree.visibility='team'`, `StepLibrary.visibility='team'`) is a separate domain and intentionally untouched. New `backend/scripts/sync_stripe_plan_ids.py` — idempotent upsert of `plan_billing` rows from Stripe products by exact name match, picks active monthly recurring price, leaves annual fields NULL by design. Test-mode `plan_billing` populated for all 3 tiers in dev. Phase O Task 46 allowlist: `INTERNAL_TESTER_EMAILS` env var (comma-separated) bypasses `SELF_SERVE_ENABLED=false` for specific authenticated users — `Settings.is_self_serve_active_for(email)` centralizes the check; `/config/public` returns `self_serve_enabled=true` for allowlisted authenticated callers; `/auth/register` allows allowlisted emails to register without invite code. New `get_current_user_optional` dep for endpoints that work both anonymous and authed.
|
||||
|
||||
- **2026-05-06 — PR #163** Seed test users marked email-verified. Fixed seeded users showing the email verification banner in dev/test, blocking flows that gate on `email_verified=True`. Squash-merged into main as `dad5e1f`.
|
||||
|
||||
- **2026-05-06 — PR #162** Self-serve signup Phase 2 (frontend cutover). 18 commits across Tasks 27–44 of the Phase 2 plan: backend remainders + frontend billing foundation + auth surfaces (OAuth + accept-invite + verify-email) + welcome wizard + dashboard redesign (TrialPill, NextStepCard, unified checklist) + public surfaces (`/pricing`, `/contact-sales`) + beta-signup deprecation. Single alembic head `c6cbfc534fad` (no new migrations in Phase 2). Squash-merged as `f1be3ab`.
|
||||
|
||||
- **2026-05-?? — PR #161** Self-serve signup backend (Phase 1). `plan_billing` sibling table for Stripe + catalog metadata, `sales_leads` and `stripe_events` tables, `complimentary` status with `has_pro_entitlement`, `BillingService.start_trial` wired into `/auth/register`, `/billing/checkout-session`, Stripe webhook handler with idempotency via `stripe_events`, Google + Microsoft OAuth callbacks with `oauth_identities` linking, `require_verified_email_after_grace` + `require_active_subscription` guards, bulk-create + soft-revoke invite endpoints, account-invite email-match enforcement, pilot complimentary backfill, `accounts.team_size_bucket` + `primary_psa` for wizard. Squash-merged as `f918b76`.
|
||||
|
||||
- **2026-05-02 — PR #159** In-product User Guides rewrite to Diátaxis how-tos. Replaced 15 feature-dump guides with 43 problem-oriented how-tos grouped under 10 categories. Dropped Maintenance Flows / AI Assistant / Flow Assist Sparkles guides (UI no longer exists). Renamed Step Library → Solutions Library. Authored 14 net-new how-tos for FlowPilot-era surfaces (tasklane keyboard flow, what-we-know, resolve, escalate, record-fix-outcome, post-docs-to-ticket, share-update, pause-and-leave, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate, etc.). Schema additions: `category`, optional `relatedSlugs`. Browser-verified against engineer + owner login.
|
||||
|
||||
- **2026-05-?? — PR #160** Post-PR-159 UI cleanup — sidebar IA + account redesign. Squash-merged as `a8b22cf`.
|
||||
|
||||
- **2026-05-01 — PR #158** Session-screen UX impeccable pass + tasklane keyboard flow. Heuristic score 24/40 → 33/40 across five sub-passes (distill, quieter, layout, typeset, polish). Removed duplicate "Suggested checks" chip strip → TaskLane is the single source of truth; added inline `Next steps · N pending` cue on the latest action-bearing AI bubble; consolidated session header to Resolve + Escalate + ⋯ kebab; centered messages column to match composer; dropped all banned decorations (side stripes, gradient surfaces, backdrop blur, accent borderTop) for a single decoration channel per surface; unified 14 text sizes into a 5-step scale. TaskLane keyboard flow: Enter submits + auto-advances, Shift+Enter newline, Esc cancel, focus jumps to Send after the last task. Banner ↔ script-panel are now linked (collapse hides both, any outcome closes both). WhatWeKnow section is collapsible with `sessionStorage` memory + auto-collapse-at-5-facts. Side fix: ParameterizationPreview no longer over-highlights short parameter values (word-boundary check). Two backlog entries logged in `.ai/TODO.md`: ConcludeSessionModal multi-select and `bg-card-hover` Tailwind drift in CommandPalette.
|
||||
- **2026-05-01 — PR #156** Suggested-fix "Awaiting verification" outcome. Engineers can now park a fix in `applied_pending` (waiting on client power-cycle, AD replication, license sync, etc.) instead of forcing a synchronous worked/didn't/partial verdict. PendingBanner with worked / didn't / update reason / dismiss; nudge "Still checking" records pending with a reason; page-level Resolve auto-patches pending → success before the resolution flow opens; page-level Escalate intercepts pending. Migration `c0f3a4b7e91d` (`pending_reason` column + status CHECK constraint).
|
||||
- **2026-04-30 — PR #155** Escalation Mode wedge. Magic-moment handoff-context screen for senior pickup, live SSE escalation arrivals, post-claim time-to-first-action metric (`GET /analytics/flowpilot/escalations`), atomic role-gated claim with conflict resolution, queue self-exclusion, chat ownership extended to claimed sessions. The wedge for the first paying-customer push.
|
||||
@@ -215,17 +229,30 @@
|
||||
|
||||
## What's In Progress
|
||||
|
||||
- **GTM Validation:** Shadow & Ship — founder uses product for 2 weeks, then hands logins to 5 colleagues
|
||||
- **Solutions Library spec:** Written at `docs/plans/2026-03-23-solutions-library-design.md`, implementation deferred to post-pilot
|
||||
- **Self-serve cutover (Phase O):** PR #164 (open) closes the last code blockers — taxonomy reconciliation + `INTERNAL_TESTER_EMAILS` allowlist. After merge, remaining work is purely manual ops: live-mode Stripe Dashboard config, Railway prod env vars, internal validation pass with Andrea Henry + 2-3 external Directors of Onboarding, then `SELF_SERVE_ENABLED=true` flip with frontend redeploy.
|
||||
- **Stripe live-mode setup:** Test-mode is fully wired (3 products, monthly prices for Starter/Pro, Enterprise sales-led, `plan_billing` seeded via `sync_stripe_plan_ids.py`). Live mode requires manual Dashboard config — same script handles seeding live IDs.
|
||||
- **GTM Validation:** Shadow & Ship — founder uses product for real MSP tickets daily, then hands logins to 5 colleagues.
|
||||
- **Solutions Library spec:** Written at `docs/plans/2026-03-23-solutions-library-design.md`, implementation deferred to post-pilot.
|
||||
|
||||
---
|
||||
|
||||
## What's Next (Priority Order)
|
||||
|
||||
### Phase O Cutover (Weeks 0-1)
|
||||
|
||||
- Merge PR #164
|
||||
- Stripe Dashboard live-mode setup (Products + Prices for Starter/Pro, no Prices on Enterprise, Customer Portal config, webhook endpoint with 5 events)
|
||||
- Railway prod env vars (`sk_live_*`, `whsec_*`, `INTERNAL_TESTER_EMAILS`, prod Google + Microsoft OAuth credentials, `OAUTH_REDIRECT_BASE`)
|
||||
- Run `sync_stripe_plan_ids.py` against prod backend; verify `plan_billing` has `sk_live_*` price IDs
|
||||
- Internal validation pass (9 scenarios from Phase O Task 46 plan)
|
||||
- Email pilots about complimentary status, flip `SELF_SERVE_ENABLED=true` (frontend redeploy required for `VITE_SELF_SERVE_ENABLED`)
|
||||
- PostHog dashboards + Sentry alert at >1/hour Stripe webhook errors
|
||||
|
||||
### Pilot Phase (Weeks 1-2)
|
||||
|
||||
- Founder dogfooding: use ResolutionFlow for real MSP tickets daily
|
||||
- Collect feedback on copilot-first experience
|
||||
- 3 calls with external Directors of Onboarding to validate the documentation-builder thesis (cold pitch, no friendly contacts)
|
||||
- Collect feedback on copilot-first experience and self-serve onboarding flow
|
||||
- Fix issues discovered during real usage
|
||||
|
||||
### Post-Pilot (Weeks 3-4)
|
||||
|
||||
24
README.md
24
README.md
@@ -13,8 +13,8 @@
|
||||
```bash
|
||||
# Prerequisites: Docker, Python 3.12, Node.js 20+
|
||||
|
||||
# Start PostgreSQL
|
||||
docker start patherly_postgres
|
||||
# Start PostgreSQL (and the rest of the dev stack)
|
||||
docker compose -f docker-compose.dev.yml up -d
|
||||
|
||||
# Backend
|
||||
cd backend
|
||||
@@ -105,16 +105,17 @@ Every session generates timestamped, detailed notes formatted for your PSA. Engi
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
patherly/
|
||||
resolutionflow/
|
||||
├── backend/
|
||||
│ ├── app/
|
||||
│ │ ├── main.py # FastAPI entry point
|
||||
│ │ ├── api/endpoints/ # Route handlers (35+ endpoints)
|
||||
│ │ ├── api/endpoints/ # Route handlers (50+ endpoints)
|
||||
│ │ ├── core/ # Config, database, permissions, security
|
||||
│ │ ├── models/ # SQLAlchemy models
|
||||
│ │ ├── schemas/ # Pydantic schemas
|
||||
│ │ └── services/psa/ # PSA provider abstraction layer
|
||||
│ ├── alembic/ # Database migrations
|
||||
│ ├── scripts/ # Seed + sync scripts (incl. sync_stripe_plan_ids.py)
|
||||
│ └── tests/ # Integration tests (100+)
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
@@ -122,13 +123,19 @@ patherly/
|
||||
│ │ ├── pages/ # Page components
|
||||
│ │ ├── store/ # Zustand stores
|
||||
│ │ └── types/ # TypeScript interfaces
|
||||
├── .ai/ # Dual-agent handoff system (PROJECT_CONTEXT, HANDOFF, etc.)
|
||||
├── docs/ # Design docs, plans, ConnectWise reference
|
||||
├── brand-assets/ # SVGs, brand guide
|
||||
├── CLAUDE.md # AI assistant project context
|
||||
├── CLAUDE.md # AI assistant project context (Claude Code)
|
||||
├── AGENTS.md # AI assistant project context (Codex; shared protocol with CLAUDE.md)
|
||||
├── CURRENT-STATE.md # Detailed feature status
|
||||
├── DESIGN-SYSTEM.md # Visual + interaction design system
|
||||
├── PRODUCT.md # Design intent and brand personality
|
||||
└── CHANGELOG.md # Release history
|
||||
```
|
||||
|
||||
> The on-disk repo path is `resolutionflow/`. `patherly` is the legacy internal name — still appears in some Railway service names and the prod DB name. Treat as an alias, not canonical.
|
||||
|
||||
---
|
||||
|
||||
## Running Tests
|
||||
@@ -149,10 +156,13 @@ npm run build
|
||||
|
||||
| Document | Purpose |
|
||||
|----------|---------|
|
||||
| [CLAUDE.md](CLAUDE.md) | Full project context for AI-assisted development |
|
||||
| [CLAUDE.md](CLAUDE.md) | Project context for Claude Code |
|
||||
| [AGENTS.md](AGENTS.md) | Project context for Codex (shared protocol with CLAUDE.md) |
|
||||
| [.ai/PROJECT_CONTEXT.md](.ai/PROJECT_CONTEXT.md) | Stable architectural truth |
|
||||
| [CURRENT-STATE.md](CURRENT-STATE.md) | Detailed feature status |
|
||||
| [03-DEVELOPMENT-ROADMAP.md](03-DEVELOPMENT-ROADMAP.md) | Development roadmap |
|
||||
| [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) | Design system (Slate & Ice) |
|
||||
| [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) | Visual + interaction design system (charcoal palette + electric blue accent) |
|
||||
| [PRODUCT.md](PRODUCT.md) | Design intent, users, brand personality |
|
||||
| [DEV-ENV.md](DEV-ENV.md) | Development environment setup |
|
||||
| [CHANGELOG.md](CHANGELOG.md) | Release history |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user