@etus/bhono-app 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +46 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +26 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/generator.d.ts +14 -0
- package/dist/generator.js +142 -0
- package/dist/generator.js.map +1 -0
- package/dist/generator.test.d.ts +1 -0
- package/dist/generator.test.js +127 -0
- package/dist/generator.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +25 -0
- package/dist/prompts.js +83 -0
- package/dist/prompts.js.map +1 -0
- package/dist/prompts.test.d.ts +1 -0
- package/dist/prompts.test.js +24 -0
- package/dist/prompts.test.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +37 -0
- package/dist/providers/cloudflare.js +61 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/cloudflare.test.d.ts +1 -0
- package/dist/providers/cloudflare.test.js +29 -0
- package/dist/providers/cloudflare.test.js.map +1 -0
- package/dist/providers/github.d.ts +16 -0
- package/dist/providers/github.js +57 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/github.test.d.ts +1 -0
- package/dist/providers/github.test.js +16 -0
- package/dist/providers/github.test.js.map +1 -0
- package/dist/templates.d.ts +8 -0
- package/dist/templates.js +88 -0
- package/dist/templates.js.map +1 -0
- package/dist/templates.test.d.ts +1 -0
- package/dist/templates.test.js +26 -0
- package/dist/templates.test.js.map +1 -0
- package/package.json +36 -0
- package/templates/base/.claude/agents/architect-review.md +160 -0
- package/templates/base/.claude/agents/backend-architect.md +308 -0
- package/templates/base/.claude/agents/code-reviewer.md +170 -0
- package/templates/base/.claude/agents/performance-engineer.md +166 -0
- package/templates/base/.claude/agents/test-automator.md +219 -0
- package/templates/base/.claude/commands/check-skill-rules.md +53 -0
- package/templates/base/.claude/commands/claude-md.md +250 -0
- package/templates/base/.claude/commands/code-prompt.md +212 -0
- package/templates/base/.claude/commands/explain-code.md +194 -0
- package/templates/base/.claude/commands/init-projec.md +89 -0
- package/templates/base/.claude/commands/linear/README.md +297 -0
- package/templates/base/.claude/commands/linear/create-issue.md +190 -0
- package/templates/base/.claude/commands/linear/implement-issue.md +248 -0
- package/templates/base/.claude/commands/linear/process-triage.md +399 -0
- package/templates/base/.claude/commands/linear/setup.md +180 -0
- package/templates/base/.claude/commands/prime.md +9 -0
- package/templates/base/.claude/commands/review-gap.md +10 -0
- package/templates/base/.claude/commands/setup-aa.md +311 -0
- package/templates/base/.claude/commands/ship.md +262 -0
- package/templates/base/.claude/commands/tools.md +3 -0
- package/templates/base/.claude/docs/claude-progress.txt +107 -0
- package/templates/base/.claude/hooks/package-lock.json +556 -0
- package/templates/base/.claude/hooks/package.json +16 -0
- package/templates/base/.claude/hooks/skill-activation-prompt.sh +7 -0
- package/templates/base/.claude/hooks/skill-activation-prompt.ts +142 -0
- package/templates/base/.claude/hooks/tsconfig.json +19 -0
- package/templates/base/.claude/scripts/check-updates.sh +85 -0
- package/templates/base/.claude/scripts/install_pkgs.sh +66 -0
- package/templates/base/.claude/scripts/setup-project.sh +177 -0
- package/templates/base/.claude/scripts/validate-skill-rules.sh +94 -0
- package/templates/base/.claude/settings.json +113 -0
- package/templates/base/.claude/settings.local.json +11 -0
- package/templates/base/.claude/skills/architecture-analyzer/SKILL.md +531 -0
- package/templates/base/.claude/skills/architecture-analyzer/assets/report-template.md +215 -0
- package/templates/base/.claude/skills/architecture-analyzer/references/c4-templates.md +234 -0
- package/templates/base/.claude/skills/architecture-analyzer/references/confidence-levels.md +203 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/analyze_structure.py +266 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/analyze_tech_debt.py +776 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/extract_apis.py +338 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/generate_c4.py +283 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/generate_erd.py +935 -0
- package/templates/base/.claude/skills/architecture-analyzer/scripts/map_dependencies.py +555 -0
- package/templates/base/.claude/skills/dev-browser/SKILL.md +318 -0
- package/templates/base/.claude/skills/dev-browser/bun.lock +443 -0
- package/templates/base/.claude/skills/dev-browser/package-lock.json +2927 -0
- package/templates/base/.claude/skills/dev-browser/package.json +27 -0
- package/templates/base/.claude/skills/dev-browser/scripts/start-server.ts +117 -0
- package/templates/base/.claude/skills/dev-browser/server.sh +24 -0
- package/templates/base/.claude/skills/dev-browser/src/client.ts +403 -0
- package/templates/base/.claude/skills/dev-browser/src/index.ts +281 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/__tests__/snapshot.test.ts +223 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/browser-script.ts +877 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/index.ts +14 -0
- package/templates/base/.claude/skills/dev-browser/src/snapshot/inject.ts +13 -0
- package/templates/base/.claude/skills/dev-browser/src/types.ts +27 -0
- package/templates/base/.claude/skills/dev-browser/tsconfig.json +36 -0
- package/templates/base/.claude/skills/dev-browser/vitest.config.ts +12 -0
- package/templates/base/.claude/skills/linear/SKILL.md +440 -0
- package/templates/base/.claude/skills/linear/examples.md +262 -0
- package/templates/base/.claude/skills/linear/lib/client.ts +51 -0
- package/templates/base/.claude/skills/linear/lib/config.ts +106 -0
- package/templates/base/.claude/skills/linear/lib/output.ts +34 -0
- package/templates/base/.claude/skills/linear/package-lock.json +698 -0
- package/templates/base/.claude/skills/linear/package.json +27 -0
- package/templates/base/.claude/skills/linear/reference.md +263 -0
- package/templates/base/.claude/skills/linear/scripts/comments/create.ts +47 -0
- package/templates/base/.claude/skills/linear/scripts/comments/list.ts +47 -0
- package/templates/base/.claude/skills/linear/scripts/issues/archive.ts +30 -0
- package/templates/base/.claude/skills/linear/scripts/issues/create.ts +279 -0
- package/templates/base/.claude/skills/linear/scripts/issues/get.ts +68 -0
- package/templates/base/.claude/skills/linear/scripts/issues/list.ts +67 -0
- package/templates/base/.claude/skills/linear/scripts/issues/update.ts +281 -0
- package/templates/base/.claude/skills/linear/scripts/labels/add-to-issue.ts +63 -0
- package/templates/base/.claude/skills/linear/scripts/labels/create.ts +45 -0
- package/templates/base/.claude/skills/linear/scripts/labels/list.ts +30 -0
- package/templates/base/.claude/skills/linear/scripts/list-teams.ts +52 -0
- package/templates/base/.claude/skills/linear/scripts/setup/setup-credentials.ts +96 -0
- package/templates/base/.claude/skills/linear/scripts/status/list.ts +31 -0
- package/templates/base/.claude/skills/linear/scripts/status/set-by-name.ts +78 -0
- package/templates/base/.claude/skills/linear/scripts/status/update.ts +44 -0
- package/templates/base/.claude/skills/linear/scripts/users/list.ts +59 -0
- package/templates/base/.claude/skills/linear/scripts/users/me.ts +20 -0
- package/templates/base/.claude/skills/linear/templates/README.md +203 -0
- package/templates/base/.claude/skills/linear/templates/api-reference.md +258 -0
- package/templates/base/.claude/skills/linear/templates/bug-report.md +99 -0
- package/templates/base/.claude/skills/linear/templates/feature-request.md +118 -0
- package/templates/base/.claude/skills/linear/templates/security-issue.md +162 -0
- package/templates/base/.claude/skills/linear/templates/sprint-task.md +175 -0
- package/templates/base/.claude/skills/linear/templates/tech-debt.md +137 -0
- package/templates/base/.claude/skills/linear/tsconfig.json +17 -0
- package/templates/base/.claude/skills/linear/workflows/issue-lifecycle.md +317 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/SKILL.md +113 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/global-setup.template.js +97 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/playwright.config.template.js +171 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/assets/test-template.spec.js +163 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/README.md +26 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/ads.email-deeplink.spec.ts +12 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/mobile.realism.spec.ts +16 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/examples/smoke.home.spec.ts +6 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/architecture.md +578 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/best-practices.md +260 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/ci-reporting.md +86 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/debugging.md +629 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/mobile-realism.md +50 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/optimization.md +488 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/patterns.md +513 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/resources.md +44 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/references/visual-a11y.md +66 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/auth-setup.js +202 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/performance-analyzer.js +240 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/scripts/trace-url.js +132 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/ci/github-actions.playwright.yml +78 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/fixtures.ts +44 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/global-setup.template.js +97 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/global.setup.ts +35 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/helpers/ad-gpt-observer.ts +80 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/helpers/chromium-mobile-profile.ts +93 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/playwright.config.template.js +171 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/playwright.config.ts +126 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/test-template.spec.js +163 -0
- package/templates/base/.claude/skills/playwright-e2e-testing/templates/tests/email-deeplink.ads.spec.ts +44 -0
- package/templates/base/.claude/skills/skill-rules.json +184 -0
- package/templates/base/.claude/skills/wrangler/SKILL.md +209 -0
- package/templates/base/.claude/skills/wrangler/resources/api.md +494 -0
- package/templates/base/.claude/skills/wrangler/resources/bundling.md +83 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/cert.md +64 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/check.md +66 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/containers.md +157 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/d1.md +843 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/delete.md +27 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/deploy.md +139 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/deployments.md +56 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/dev.md +157 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/dispatch-namespace.md +69 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/docs.md +61 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/how-to-run.md +62 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/hyperdrive.md +425 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/init.md +31 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-bulk.md +265 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-key.md +353 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/kv-namespace.md +265 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/login.md +23 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/logout.md +19 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/mtls-certificate.md +69 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/pages.md +175 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/pipelines.md +76 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/queues.md +132 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-bucket.md +342 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-object.md +267 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/r2-sql.md +65 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/rollback.md +40 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secret.md +308 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secrets-store-secret.md +100 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/secrets-store-store.md +60 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/setup.md +67 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/tail.md +37 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/telemetry.md +64 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/triggers.md +39 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/types.md +73 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/vectorize.md +941 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/versions.md +95 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/whoami.md +49 -0
- package/templates/base/.claude/skills/wrangler/resources/commands/workflows.md +117 -0
- package/templates/base/.claude/skills/wrangler/resources/commands.md +138 -0
- package/templates/base/.claude/skills/wrangler/resources/configuration.md +2176 -0
- package/templates/base/.claude/skills/wrangler/resources/custom-builds.md +55 -0
- package/templates/base/.claude/skills/wrangler/resources/deprecations.md +279 -0
- package/templates/base/.claude/skills/wrangler/resources/enviroments.md +416 -0
- package/templates/base/.claude/skills/wrangler/resources/extract_sections.py +119 -0
- package/templates/base/.claude/skills/wrangler/resources/process_content.py +94 -0
- package/templates/base/.claude/skills/wrangler/resources/system-enviroments-variables.md +120 -0
- package/templates/base/.dev.vars.example +15 -0
- package/templates/base/.env.example +29 -0
- package/templates/base/.github/workflows/test.yml +127 -0
- package/templates/base/.nycrc.json +16 -0
- package/templates/base/CLAUDE.md +218 -0
- package/templates/base/README.md +670 -0
- package/templates/base/auth-setup-error.png +0 -0
- package/templates/base/config/drizzle.config.ts +10 -0
- package/templates/base/config/eslint.config.js +364 -0
- package/templates/base/config/wrangler.json +76 -0
- package/templates/base/docs/app_spec.txt +879 -0
- package/templates/base/docs/app_spec_template.md +681 -0
- package/templates/base/docs/architecture/README.md +8 -0
- package/templates/base/docs/architecture/data-requirements.md +109 -0
- package/templates/base/docs/architecture/erd.md +91 -0
- package/templates/base/docs/features/feature_list.json +3128 -0
- package/templates/base/docs/hono-boilerplate-plan.md +1774 -0
- package/templates/base/docs/test-coverage-gap-analysis.md +242 -0
- package/templates/base/docs/testing.md +188 -0
- package/templates/base/index.html +16 -0
- package/templates/base/package.json +115 -0
- package/templates/base/playwright.config.ts +158 -0
- package/templates/base/pnpm-lock.yaml +8175 -0
- package/templates/base/scripts/capture-prod-session.ts +250 -0
- package/templates/base/scripts/generate-openapi.ts +23 -0
- package/templates/base/scripts/init.sh +121 -0
- package/templates/base/src/client/__tests__/button.test.tsx +30 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-dashboard-stats-cards-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-quick-action-cards-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-recent-activity-section-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-first-name-in-welcome-message-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-display-user-information-in-sidebar-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-render-dashboard-when-authenticated-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-authenticated-should-show-navigation-sidebar-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/dashboard.test.tsx/Dashboard-Page-when-unauthenticated-should-redirect-to-login-when-not-authenticated-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-display-Google-OAuth-login-button-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-have-a-link-back-to-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-content-without-waiting-for-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-render-login-page-at--login-route-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-show-Terms-of-Service-and-Privacy-Policy-links-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/login.test.tsx/Login-Page-should-trigger-OAuth-flow-when-clicking-login-button-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-display-404-text-on-not-found-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-have-navigation-options-on-404-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-404-handling-should-render-404-page-for-unknown-routes-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-account-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-integrations-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-settings-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-authenticated-navigation-should-navigate-from-dashboard-to-team-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-display-navigation-links-on-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-home-page-navigation-should-have-correct-link-destinations-on-home-page-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-home-page-without-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-allow-access-to-login-page-without-authentication-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-dashboard-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-settings-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/__screenshots__/navigation.test.tsx/Navigation-unauthenticated-navigation-should-redirect-unauthenticated-users-from-team-to-login-1.png +0 -0
- package/templates/base/src/client/__tests__/routes/authenticated-layout.test.tsx +252 -0
- package/templates/base/src/client/__tests__/routes/dashboard.test.tsx +136 -0
- package/templates/base/src/client/__tests__/routes/error-components.test.tsx +186 -0
- package/templates/base/src/client/__tests__/routes/login.test.tsx +112 -0
- package/templates/base/src/client/__tests__/routes/navigation.test.tsx +272 -0
- package/templates/base/src/client/__tests__/routes/root-layout.test.tsx +65 -0
- package/templates/base/src/client/__tests__/setup-browser.ts +15 -0
- package/templates/base/src/client/__tests__/setup.ts +32 -0
- package/templates/base/src/client/__tests__/test-utils.tsx +135 -0
- package/templates/base/src/client/api/.gitkeep +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-can-be-collapsed-by-default-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-expands-when-collapsed-and-expand-button-is-clicked-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-handles-logout-button-click-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-handles-navigation-clicks-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-hides-navigation-labels-when-collapsed-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-highlights-active-route-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-renders-sidebar-navigation-items-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-keyboard-shortcut-hint-when-expanded-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-info-when-authenticated-1.png +0 -0
- package/templates/base/src/client/components/__tests__/__screenshots__/sidebar.test.tsx/Sidebar-shows-user-initials-in-avatar-fallback-1.png +0 -0
- package/templates/base/src/client/components/__tests__/error-boundary.test.tsx +97 -0
- package/templates/base/src/client/components/__tests__/sidebar.test.tsx +281 -0
- package/templates/base/src/client/components/error-boundary.tsx +68 -0
- package/templates/base/src/client/components/icons.tsx +106 -0
- package/templates/base/src/client/components/layout/.gitkeep +0 -0
- package/templates/base/src/client/components/sidebar.tsx +267 -0
- package/templates/base/src/client/components/ui/.gitkeep +0 -0
- package/templates/base/src/client/components/ui/__tests__/avatar.test.tsx +308 -0
- package/templates/base/src/client/components/ui/__tests__/card.test.tsx +214 -0
- package/templates/base/src/client/components/ui/__tests__/dialog.test.tsx +297 -0
- package/templates/base/src/client/components/ui/__tests__/error-fallback.test.tsx +145 -0
- package/templates/base/src/client/components/ui/__tests__/input.test.tsx +98 -0
- package/templates/base/src/client/components/ui/__tests__/loading-skeleton.test.tsx +139 -0
- package/templates/base/src/client/components/ui/__tests__/skeleton.test.tsx +44 -0
- package/templates/base/src/client/components/ui/__tests__/sonner.test.tsx +28 -0
- package/templates/base/src/client/components/ui/__tests__/tabs.test.tsx +233 -0
- package/templates/base/src/client/components/ui/avatar.tsx +101 -0
- package/templates/base/src/client/components/ui/badge.tsx +46 -0
- package/templates/base/src/client/components/ui/button.tsx +72 -0
- package/templates/base/src/client/components/ui/card.tsx +86 -0
- package/templates/base/src/client/components/ui/dialog.tsx +140 -0
- package/templates/base/src/client/components/ui/error-fallback.tsx +179 -0
- package/templates/base/src/client/components/ui/form.tsx +172 -0
- package/templates/base/src/client/components/ui/input.tsx +24 -0
- package/templates/base/src/client/components/ui/label.tsx +22 -0
- package/templates/base/src/client/components/ui/loading-skeleton.tsx +154 -0
- package/templates/base/src/client/components/ui/separator.tsx +33 -0
- package/templates/base/src/client/components/ui/skeleton.tsx +16 -0
- package/templates/base/src/client/components/ui/sonner.tsx +29 -0
- package/templates/base/src/client/components/ui/tabs.tsx +121 -0
- package/templates/base/src/client/hooks/.gitkeep +0 -0
- package/templates/base/src/client/hooks/__tests__/use-auth.test.tsx +306 -0
- package/templates/base/src/client/hooks/__tests__/use-theme.test.tsx +172 -0
- package/templates/base/src/client/hooks/use-auth.ts +53 -0
- package/templates/base/src/client/hooks/use-theme.tsx +78 -0
- package/templates/base/src/client/index.css +881 -0
- package/templates/base/src/client/lib/query-client.ts +11 -0
- package/templates/base/src/client/lib/utils.ts +7 -0
- package/templates/base/src/client/main.tsx +26 -0
- package/templates/base/src/client/routeTree.gen.ts +258 -0
- package/templates/base/src/client/router.ts +15 -0
- package/templates/base/src/client/routes/$.tsx +77 -0
- package/templates/base/src/client/routes/.gitkeep +0 -0
- package/templates/base/src/client/routes/__root.tsx +34 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-accept-invitation-button-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-decline-button-linking-to-homepage-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-display-invitation-details--email--workspace--role--1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-have-a-logo-link-to-homepage-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-render-invitation-page-with-inviter-name-and-workspace-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/__screenshots__/invite.test.tsx/Invite-Token-Page-pending-invitation-state-should-show-terms-of-service-and-privacy-policy-links-1.png +0 -0
- package/templates/base/src/client/routes/__tests__/invite.test.tsx +138 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-render-Active-Sessions-section-with-session-cards-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-render-page-with-correct-title--Account--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-API-Access-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Connected-Accounts-section-with-Google-connected-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Danger-Zone-section-with-delete-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/account.test.tsx/Account-Page-should-show-Security-section-with-Two-Factor-Authentication-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-API-documentation-section-should-display-API-documentation-link-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-Create-Webhook-Dialog-should-have-Add-Webhook-trigger-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-category-filters-should-display-all-category-buttons-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-all-integration-cards-with-names-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-display-category-badges-on-cards-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Configure-button-for-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connect-button-for-not-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-integration-cards-should-show-Connected-badge-for-connected-integrations-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Available-Integrations-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-Webhooks-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-connected-count-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-page-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-display-search-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-page-rendering-should-render-with-correct-title--Integrations--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-filter-integrations-based-on-search-query-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-search-by-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-search-functionality-should-show-no-results-message-when-search-has-no-matches-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-existing-webhook-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-events-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-last-delivery-info-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-display-webhook-success-status-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/integrations.test.tsx/Integrations-Page-webhooks-section-should-have-Add-Webhook-button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-connected-accounts-section-with-Google-provider-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Account-tab-should-display-sessions-and-danger-zone-sections-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-all-notification-toggle-options-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-email-notifications-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-display-toggle-switches-for-notification-options-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Notifications-tab-should-have-toggles-checked-by-default-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display--Save-Changes--button-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-personal-information-form-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-profile-picture-section-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-email-in-disabled-email-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-initials-in-avatar-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-Profile-tab-should-display-user-name-in-the-name-input-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-all-three-tabs-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-display-page-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-page-rendering-should-render-with-correct-title--Settings--1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-show-Profile-tab-as-default-active-tab-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Account-tab-when-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/settings.test.tsx/Settings-Page-tab-navigation-should-switch-to-Notifications-tab-when-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-display-Active-Members-section-with-member-count-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-display-Pending-Invitations-section-with-invitation-details-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-have-invite-member-button-that-can-be-clicked-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-render-page-with-correct-title-and-description-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-render-search-input-that-filters-team-members-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/__screenshots__/team.test.tsx/Team-Page-should-show-current-user-with---you---indicator-and-role-badge-1.png +0 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/account.test.tsx +324 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/integrations.test.tsx +520 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/settings.test.tsx +414 -0
- package/templates/base/src/client/routes/_authenticated/__tests__/team.test.tsx +374 -0
- package/templates/base/src/client/routes/_authenticated/account.tsx +416 -0
- package/templates/base/src/client/routes/_authenticated/dashboard.tsx +151 -0
- package/templates/base/src/client/routes/_authenticated/integrations.tsx +553 -0
- package/templates/base/src/client/routes/_authenticated/settings.tsx +310 -0
- package/templates/base/src/client/routes/_authenticated/team.tsx +395 -0
- package/templates/base/src/client/routes/_authenticated.tsx +69 -0
- package/templates/base/src/client/routes/index.tsx +155 -0
- package/templates/base/src/client/routes/invite.$token.tsx +191 -0
- package/templates/base/src/client/routes/login.tsx +92 -0
- package/templates/base/src/server/__tests__/fixtures.ts +461 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/db.test.ts +239 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/kv.test.ts +293 -0
- package/templates/base/src/server/__tests__/mocks/__tests__/r2.test.ts +363 -0
- package/templates/base/src/server/__tests__/mocks/db.ts +186 -0
- package/templates/base/src/server/__tests__/mocks/index.ts +33 -0
- package/templates/base/src/server/__tests__/mocks/kv.ts +286 -0
- package/templates/base/src/server/__tests__/mocks/r2.ts +397 -0
- package/templates/base/src/server/__tests__/setup.ts +281 -0
- package/templates/base/src/server/auth/__tests__/guards.test.ts +162 -0
- package/templates/base/src/server/auth/guards.ts +92 -0
- package/templates/base/src/server/auth/permissions.test.ts +45 -0
- package/templates/base/src/server/auth/permissions.ts +139 -0
- package/templates/base/src/server/auth/roles.test.ts +169 -0
- package/templates/base/src/server/auth/roles.ts +141 -0
- package/templates/base/src/server/db/client.ts +12 -0
- package/templates/base/src/server/db/schema/accounts.ts +20 -0
- package/templates/base/src/server/db/schema/audit-logs.ts +26 -0
- package/templates/base/src/server/db/schema/index.ts +7 -0
- package/templates/base/src/server/db/schema/invitations.ts +30 -0
- package/templates/base/src/server/db/schema/refresh-tokens.ts +22 -0
- package/templates/base/src/server/db/schema/user-accounts.ts +25 -0
- package/templates/base/src/server/db/schema/users.ts +33 -0
- package/templates/base/src/server/db/seed.ts +267 -0
- package/templates/base/src/server/env.test.ts +84 -0
- package/templates/base/src/server/env.ts +78 -0
- package/templates/base/src/server/index.ts +82 -0
- package/templates/base/src/server/lib/audit.ts +73 -0
- package/templates/base/src/server/lib/audited-db.test.ts +107 -0
- package/templates/base/src/server/lib/audited-db.ts +154 -0
- package/templates/base/src/server/lib/email.test.ts +116 -0
- package/templates/base/src/server/lib/email.ts +82 -0
- package/templates/base/src/server/lib/errors.test.ts +49 -0
- package/templates/base/src/server/lib/errors.ts +64 -0
- package/templates/base/src/server/lib/oauth.test.ts +238 -0
- package/templates/base/src/server/lib/oauth.ts +113 -0
- package/templates/base/src/server/lib/pagination.test.ts +52 -0
- package/templates/base/src/server/lib/pagination.ts +32 -0
- package/templates/base/src/server/lib/password.test.ts +151 -0
- package/templates/base/src/server/lib/password.ts +151 -0
- package/templates/base/src/server/lib/providers.test.ts +105 -0
- package/templates/base/src/server/lib/providers.ts +62 -0
- package/templates/base/src/server/lib/r2-storage.test.ts +202 -0
- package/templates/base/src/server/lib/r2-storage.ts +107 -0
- package/templates/base/src/server/lib/schema-helpers.ts +16 -0
- package/templates/base/src/server/lib/session.test.ts +758 -0
- package/templates/base/src/server/lib/session.ts +267 -0
- package/templates/base/src/server/lib/tokens.test.ts +208 -0
- package/templates/base/src/server/lib/tokens.ts +65 -0
- package/templates/base/src/server/lib/transaction.test.ts +45 -0
- package/templates/base/src/server/lib/transaction.ts +24 -0
- package/templates/base/src/server/middleware/account.test.ts +201 -0
- package/templates/base/src/server/middleware/account.ts +66 -0
- package/templates/base/src/server/middleware/auth.test.ts +345 -0
- package/templates/base/src/server/middleware/auth.ts +146 -0
- package/templates/base/src/server/middleware/cors.test.ts +88 -0
- package/templates/base/src/server/middleware/cors.ts +26 -0
- package/templates/base/src/server/middleware/error-handler.test.ts +69 -0
- package/templates/base/src/server/middleware/error-handler.ts +43 -0
- package/templates/base/src/server/middleware/index.ts +8 -0
- package/templates/base/src/server/middleware/rate-limit.test.ts +472 -0
- package/templates/base/src/server/middleware/rate-limit.ts +294 -0
- package/templates/base/src/server/middleware/request-context.test.ts +175 -0
- package/templates/base/src/server/middleware/request-context.ts +28 -0
- package/templates/base/src/server/middleware/request-logger.test.ts +92 -0
- package/templates/base/src/server/middleware/request-logger.ts +50 -0
- package/templates/base/src/server/routes/accounts/__tests__/handlers.test.ts +460 -0
- package/templates/base/src/server/routes/accounts/handlers.ts +179 -0
- package/templates/base/src/server/routes/accounts/index.ts +55 -0
- package/templates/base/src/server/routes/accounts/routes.ts +205 -0
- package/templates/base/src/server/routes/accounts/schemas.ts +31 -0
- package/templates/base/src/server/routes/api.ts +37 -0
- package/templates/base/src/server/routes/audits/__tests__/handlers.test.ts +349 -0
- package/templates/base/src/server/routes/audits/handlers.ts +37 -0
- package/templates/base/src/server/routes/audits/index.ts +14 -0
- package/templates/base/src/server/routes/audits/routes.ts +29 -0
- package/templates/base/src/server/routes/audits/schemas.ts +43 -0
- package/templates/base/src/server/routes/auth/__tests__/handlers.test.ts +381 -0
- package/templates/base/src/server/routes/auth/handlers.ts +222 -0
- package/templates/base/src/server/routes/auth/index.ts +37 -0
- package/templates/base/src/server/routes/auth/routes.ts +136 -0
- package/templates/base/src/server/routes/auth/schemas.ts +48 -0
- package/templates/base/src/server/routes/auth/test-login.ts +156 -0
- package/templates/base/src/server/routes/health/__tests__/handlers.test.ts +237 -0
- package/templates/base/src/server/routes/health/handlers.ts +83 -0
- package/templates/base/src/server/routes/health/index.ts +13 -0
- package/templates/base/src/server/routes/health/routes.ts +90 -0
- package/templates/base/src/server/routes/index.ts +53 -0
- package/templates/base/src/server/routes/invitations/__tests__/handlers.test.ts +473 -0
- package/templates/base/src/server/routes/invitations/handlers.ts +71 -0
- package/templates/base/src/server/routes/invitations/index.ts +25 -0
- package/templates/base/src/server/routes/invitations/routes.ts +69 -0
- package/templates/base/src/server/routes/invitations/schemas.ts +39 -0
- package/templates/base/src/server/routes/openapi.ts +14 -0
- package/templates/base/src/server/routes/schemas.ts +53 -0
- package/templates/base/src/server/routes/storage/__tests__/handlers.test.ts +408 -0
- package/templates/base/src/server/routes/storage/handlers.ts +100 -0
- package/templates/base/src/server/routes/storage/index.ts +42 -0
- package/templates/base/src/server/routes/storage/routes.ts +91 -0
- package/templates/base/src/server/routes/storage/schemas.ts +56 -0
- package/templates/base/src/server/routes/users/__tests__/handlers.test.ts +526 -0
- package/templates/base/src/server/routes/users/handlers.ts +228 -0
- package/templates/base/src/server/routes/users/index.ts +67 -0
- package/templates/base/src/server/routes/users/routes.ts +265 -0
- package/templates/base/src/server/routes/users/schemas.ts +67 -0
- package/templates/base/src/server/services/__tests__/accounts.test.ts +764 -0
- package/templates/base/src/server/services/__tests__/audits.test.ts +235 -0
- package/templates/base/src/server/services/__tests__/auth.test.ts +765 -0
- package/templates/base/src/server/services/__tests__/invitations.test.ts +704 -0
- package/templates/base/src/server/services/__tests__/users.test.ts +755 -0
- package/templates/base/src/server/services/accounts.ts +269 -0
- package/templates/base/src/server/services/audits.ts +82 -0
- package/templates/base/src/server/services/auth.ts +225 -0
- package/templates/base/src/server/services/index.ts +6 -0
- package/templates/base/src/server/services/invitations.ts +306 -0
- package/templates/base/src/server/services/users.ts +350 -0
- package/templates/base/src/server/types/auth.ts +36 -0
- package/templates/base/src/server/types/index.ts +117 -0
- package/templates/base/src/shared/schemas/.gitkeep +0 -0
- package/templates/base/src/shared/schemas/__tests__/schemas.test.ts +547 -0
- package/templates/base/src/shared/schemas/account.ts +15 -0
- package/templates/base/src/shared/schemas/index.ts +6 -0
- package/templates/base/src/shared/schemas/invitation.ts +9 -0
- package/templates/base/src/shared/schemas/profile.ts +10 -0
- package/templates/base/src/shared/schemas/user.ts +16 -0
- package/templates/base/src/shared/schemas/webhook.ts +12 -0
- package/templates/base/src/shared/types/.gitkeep +0 -0
- package/templates/base/src/shared/types/account.ts +12 -0
- package/templates/base/src/shared/types/api.ts +1399 -0
- package/templates/base/src/shared/types/auth.ts +24 -0
- package/templates/base/src/shared/types/index.ts +5 -0
- package/templates/base/src/shared/types/user.ts +31 -0
- package/templates/base/src/test/vitest-zod-matcher.ts +37 -0
- package/templates/base/src/test/vitest.d.ts +19 -0
- package/templates/base/tests/e2e/README.md +141 -0
- package/templates/base/tests/e2e/a11y/accessibility.spec.ts +925 -0
- package/templates/base/tests/e2e/a11y/keyboard-navigation.spec.ts +610 -0
- package/templates/base/tests/e2e/api/accounts.spec.ts +148 -0
- package/templates/base/tests/e2e/api/audit-logs.spec.ts +130 -0
- package/templates/base/tests/e2e/api/authenticated-api.spec.ts +311 -0
- package/templates/base/tests/e2e/api/storage.spec.ts +109 -0
- package/templates/base/tests/e2e/auth-flows.unauth.spec.ts +117 -0
- package/templates/base/tests/e2e/auth-logout.unauth.spec.ts +103 -0
- package/templates/base/tests/e2e/auth.setup.ts +115 -0
- package/templates/base/tests/e2e/auth.spec.ts +146 -0
- package/templates/base/tests/e2e/compatibility/cross-browser.spec.ts +152 -0
- package/templates/base/tests/e2e/compatibility/cross-browser.spec.ts-snapshots/login-chromium-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/crud/account.spec.ts +356 -0
- package/templates/base/tests/e2e/crud/integrations.spec.ts +419 -0
- package/templates/base/tests/e2e/crud/team.spec.ts +287 -0
- package/templates/base/tests/e2e/crud/users.spec.ts +239 -0
- package/templates/base/tests/e2e/errors/error-boundary.spec.ts +428 -0
- package/templates/base/tests/e2e/errors/error-handling.spec.ts +47 -0
- package/templates/base/tests/e2e/errors/error-handling.unauth.spec.ts +205 -0
- package/templates/base/tests/e2e/fixtures.ts +266 -0
- package/templates/base/tests/e2e/forms/validation.spec.ts +569 -0
- package/templates/base/tests/e2e/invitations/invite-flow.unauth.spec.ts +204 -0
- package/templates/base/tests/e2e/journeys/account-lifecycle.spec.ts +314 -0
- package/templates/base/tests/e2e/journeys/audit-investigation.spec.ts +299 -0
- package/templates/base/tests/e2e/journeys/auth-onboarding.spec.ts +232 -0
- package/templates/base/tests/e2e/journeys/critical-flows.spec.ts +281 -0
- package/templates/base/tests/e2e/journeys/error-recovery.spec.ts +354 -0
- package/templates/base/tests/e2e/journeys/file-management.spec.ts +307 -0
- package/templates/base/tests/e2e/journeys/integrations.spec.ts +372 -0
- package/templates/base/tests/e2e/journeys/multi-account.spec.ts +317 -0
- package/templates/base/tests/e2e/journeys/rbac-enforcement.spec.ts +389 -0
- package/templates/base/tests/e2e/journeys/settings-profile.spec.ts +400 -0
- package/templates/base/tests/e2e/journeys/team-collaboration.spec.ts +410 -0
- package/templates/base/tests/e2e/mobile/responsive.spec.ts +178 -0
- package/templates/base/tests/e2e/navigation/routing.spec.ts +371 -0
- package/templates/base/tests/e2e/navigation/sidebar.spec.ts +425 -0
- package/templates/base/tests/e2e/pages/ui-features.spec.ts +393 -0
- package/templates/base/tests/e2e/performance/baselines.spec.ts +162 -0
- package/templates/base/tests/e2e/performance/benchmarks.spec.ts +371 -0
- package/templates/base/tests/e2e/smoke.unauth.spec.ts +196 -0
- package/templates/base/tests/e2e/visual/components.spec.ts +650 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/confirmation-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-background-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-card-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dark-mode-sidebar-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dashboard-card-single-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dialog-content-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/dialog-with-backdrop-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/empty-search-results-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/input-default-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/input-focus-ring-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-focus-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-hover-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/primary-button-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-active-nav-item-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-collapsed-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/components.spec.ts-snapshots/sidebar-navigation-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts +192 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/account-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/create-webhook-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/dashboard-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/delete-account-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/integrations-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/invite-member-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/login-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/settings-account-tab-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/settings-profile-tab-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/sidebar-navigation-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/core-components.spec.ts-snapshots/team-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts +230 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/404-page-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/404-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/account-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/login-page-chromium-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/login-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/settings-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/team-invite-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/team-page-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/screenshots.spec.ts-snapshots/webhook-create-dialog-visual-darwin.png +0 -0
- package/templates/base/tests/e2e/visual/theme-colors.spec.ts +293 -0
- package/templates/base/tests/e2e/visual/ui-components.spec.ts +502 -0
- package/templates/base/tests/integration/accounts/crud.test.ts +1402 -0
- package/templates/base/tests/integration/audits/list.test.ts +1133 -0
- package/templates/base/tests/integration/auth/auth-service.test.ts +415 -0
- package/templates/base/tests/integration/auth/invitation-token.test.ts +529 -0
- package/templates/base/tests/integration/auth/logout.test.ts +524 -0
- package/templates/base/tests/integration/auth/oauth.test.ts +768 -0
- package/templates/base/tests/integration/auth/refresh-token.test.ts +364 -0
- package/templates/base/tests/integration/auth/session-expiry.test.ts +569 -0
- package/templates/base/tests/integration/auth/session.test.ts +520 -0
- package/templates/base/tests/integration/auth/super-admin.test.ts +451 -0
- package/templates/base/tests/integration/authorization/analytics-role.test.ts +1026 -0
- package/templates/base/tests/integration/authorization/billing-role.test.ts +776 -0
- package/templates/base/tests/integration/authorization/guards-roles.test.ts +539 -0
- package/templates/base/tests/integration/authorization/multi-tenancy.test.ts +1112 -0
- package/templates/base/tests/integration/authorization/role-hierarchy.test.ts +931 -0
- package/templates/base/tests/integration/authorization/roles.test.ts +1347 -0
- package/templates/base/tests/integration/config/production-behavior.test.ts +536 -0
- package/templates/base/tests/integration/db/constraints.test.ts +695 -0
- package/templates/base/tests/integration/fixtures/accounts.ts +136 -0
- package/templates/base/tests/integration/fixtures/index.ts +232 -0
- package/templates/base/tests/integration/fixtures/invitations.ts +195 -0
- package/templates/base/tests/integration/fixtures/users.ts +144 -0
- package/templates/base/tests/integration/health/health.test.ts +351 -0
- package/templates/base/tests/integration/invitations/crud.test.ts +1457 -0
- package/templates/base/tests/integration/invitations/email.test.ts +506 -0
- package/templates/base/tests/integration/lib/email.test.ts +174 -0
- package/templates/base/tests/integration/lib/oauth.test.ts +368 -0
- package/templates/base/tests/integration/lib/password.test.ts +192 -0
- package/templates/base/tests/integration/lib/schema-helpers.test.ts +129 -0
- package/templates/base/tests/integration/lib/tokens.test.ts +304 -0
- package/templates/base/tests/integration/middleware/auth.test.ts +499 -0
- package/templates/base/tests/integration/middleware/cors.test.ts +334 -0
- package/templates/base/tests/integration/middleware/request-context.test.ts +156 -0
- package/templates/base/tests/integration/middleware/request-logger.test.ts +313 -0
- package/templates/base/tests/integration/performance/response-times.test.ts +509 -0
- package/templates/base/tests/integration/security/cookie-security.test.ts +567 -0
- package/templates/base/tests/integration/security/csrf-protection.test.ts +542 -0
- package/templates/base/tests/integration/security/jwt-validation.test.ts +209 -0
- package/templates/base/tests/integration/security/log-sanitization.test.ts +658 -0
- package/templates/base/tests/integration/security/rate-limiting.test.ts +1251 -0
- package/templates/base/tests/integration/security/sql-injection.test.ts +663 -0
- package/templates/base/tests/integration/security/token-hashing.test.ts +371 -0
- package/templates/base/tests/integration/security/xss-prevention.test.ts +541 -0
- package/templates/base/tests/integration/setup.ts +834 -0
- package/templates/base/tests/integration/smoke.test.ts +288 -0
- package/templates/base/tests/integration/storage/upload.test.ts +1162 -0
- package/templates/base/tests/integration/storage/validation.test.ts +746 -0
- package/templates/base/tests/integration/users/crud.test.ts +1297 -0
- package/templates/base/tests/integration/users/list.test.ts +698 -0
- package/templates/base/tests/integration/vitest.config.ts +80 -0
- package/templates/base/tsconfig.app.json +18 -0
- package/templates/base/tsconfig.json +39 -0
- package/templates/base/tsconfig.node.json +16 -0
- package/templates/base/tsconfig.server.json +26 -0
- package/templates/base/tsconfig.tsbuildinfo +1 -0
- package/templates/base/vite.config.ts +46 -0
- package/templates/base/vitest.config.browser.ts +47 -0
- package/templates/base/vitest.config.frontend.ts +47 -0
- package/templates/base/vitest.config.ts +82 -0
- package/templates/base/vitest.workspace.ts +22 -0
- package/templates/modules/audit-logs/.gitkeep +0 -0
- package/templates/modules/billing/.gitkeep +0 -0
- package/templates/modules/invitations/.gitkeep +0 -0
- package/templates/modules/storage/.gitkeep +0 -0
- package/templates/modules/webhooks/.gitkeep +0 -0
- package/templates/providers/auth-email/.gitkeep +0 -0
- package/templates/providers/auth-github/.gitkeep +0 -0
- package/templates/providers/auth-google/.gitkeep +0 -0
- package/templates/providers/email-resend/.gitkeep +0 -0
- package/templates/providers/email-sendgrid/.gitkeep +0 -0
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
<project_specification>
|
|
2
|
+
<project_name>Hono Multi-Tenant SaaS Boilerplate</project_name>
|
|
3
|
+
<version>1.0.0</version>
|
|
4
|
+
<last_updated>2026-01-03</last_updated>
|
|
5
|
+
|
|
6
|
+
<overview>
|
|
7
|
+
Canonical high-level overview for the architecture docs in docs/architecture/.
|
|
8
|
+
Production-ready multi-tenant SaaS boilerplate built with Hono.js on Cloudflare Workers and React.
|
|
9
|
+
Provides a complete foundation for B2B SaaS with team workspaces, RBAC, invitations,
|
|
10
|
+
audit logging, and Google OAuth authentication.
|
|
11
|
+
|
|
12
|
+
The system uses D1 (SQLite) for relational data, KV for sessions, and R2 for object storage.
|
|
13
|
+
Users can belong to multiple accounts (workspaces) with distinct roles and permissions.
|
|
14
|
+
All state changes are logged for compliance and debugging.
|
|
15
|
+
</overview>
|
|
16
|
+
|
|
17
|
+
<goals>
|
|
18
|
+
<primary>
|
|
19
|
+
- Provide a production-ready starting point for SaaS applications
|
|
20
|
+
- Enable rapid development with pre-built auth, multi-tenancy, and RBAC
|
|
21
|
+
- Leverage edge computing for global low-latency performance
|
|
22
|
+
- Maintain strong security practices and audit compliance
|
|
23
|
+
</primary>
|
|
24
|
+
<secondary>
|
|
25
|
+
- Demonstrate best practices for Hono.js + Cloudflare Workers
|
|
26
|
+
- Provide comprehensive testing patterns (unit, integration, E2E)
|
|
27
|
+
- Enable easy customization and extension
|
|
28
|
+
</secondary>
|
|
29
|
+
</goals>
|
|
30
|
+
|
|
31
|
+
<technology_stack>
|
|
32
|
+
<runtime>
|
|
33
|
+
<platform>Cloudflare Workers</platform>
|
|
34
|
+
<database>D1 (SQLite on edge)</database>
|
|
35
|
+
<sessions>KV Namespace</sessions>
|
|
36
|
+
<storage>R2 Object Storage</storage>
|
|
37
|
+
<description>
|
|
38
|
+
Serverless edge runtime with ~50ms cold start, global distribution,
|
|
39
|
+
and integrated storage services. All infrastructure managed via Wrangler CLI.
|
|
40
|
+
</description>
|
|
41
|
+
</runtime>
|
|
42
|
+
|
|
43
|
+
<backend>
|
|
44
|
+
<framework>Hono.js 4.6</framework>
|
|
45
|
+
<orm>Drizzle ORM</orm>
|
|
46
|
+
<validation>Zod</validation>
|
|
47
|
+
<documentation>OpenAPI 3.0 / Swagger UI</documentation>
|
|
48
|
+
<description>
|
|
49
|
+
Type-safe API development with automatic schema generation.
|
|
50
|
+
Drizzle provides compile-time SQL safety with SQLite dialect.
|
|
51
|
+
OpenAPI spec and TypeScript types can be generated locally (api:spec, api:types).
|
|
52
|
+
</description>
|
|
53
|
+
</backend>
|
|
54
|
+
|
|
55
|
+
<frontend>
|
|
56
|
+
<framework>React 19</framework>
|
|
57
|
+
<routing>TanStack Router (file-based)</routing>
|
|
58
|
+
<state>TanStack Query</state>
|
|
59
|
+
<styling>Tailwind CSS 4.0</styling>
|
|
60
|
+
<components>shadcn/ui pattern</components>
|
|
61
|
+
<forms>React Hook Form + Zod</forms>
|
|
62
|
+
<notifications>Sonner (toast)</notifications>
|
|
63
|
+
<description>
|
|
64
|
+
Modern React with file-based routing, optimistic updates,
|
|
65
|
+
and a consistent design system following shadcn/ui patterns.
|
|
66
|
+
</description>
|
|
67
|
+
</frontend>
|
|
68
|
+
|
|
69
|
+
<testing>
|
|
70
|
+
<unit>Vitest</unit>
|
|
71
|
+
<integration>Vitest + Miniflare</integration>
|
|
72
|
+
<e2e>Playwright</e2e>
|
|
73
|
+
<coverage>95% server, 90% client</coverage>
|
|
74
|
+
<description>
|
|
75
|
+
Comprehensive testing strategy with isolated integration tests
|
|
76
|
+
using Miniflare for Cloudflare Workers simulation.
|
|
77
|
+
</description>
|
|
78
|
+
</testing>
|
|
79
|
+
|
|
80
|
+
<authentication>
|
|
81
|
+
<primary>Google OAuth 2.0 with PKCE</primary>
|
|
82
|
+
<sessions>Cloudflare KV (session-based cookies)</sessions>
|
|
83
|
+
<tokens>JWT access tokens (legacy support; sessions preferred)</tokens>
|
|
84
|
+
<description>
|
|
85
|
+
Session-based authentication stored in KV for persistence.
|
|
86
|
+
PKCE flow provides security for browser-based OAuth.
|
|
87
|
+
</description>
|
|
88
|
+
</authentication>
|
|
89
|
+
</technology_stack>
|
|
90
|
+
|
|
91
|
+
<architecture>
|
|
92
|
+
<multi_tenancy>
|
|
93
|
+
<model>Users belong to multiple Accounts (workspaces)</model>
|
|
94
|
+
<relationship>Many-to-many via user_accounts junction table</relationship>
|
|
95
|
+
<isolation>All queries scoped by accountId in context</isolation>
|
|
96
|
+
<roles>
|
|
97
|
+
- ADMIN: Full account management, user administration
|
|
98
|
+
- MANAGER: Team management, invitations
|
|
99
|
+
- EDITOR: Content creation and modification
|
|
100
|
+
- AUTHOR: Limited content creation
|
|
101
|
+
- VIEWER: Read-only access
|
|
102
|
+
- BILLING: Financial operations (non-hierarchical)
|
|
103
|
+
- ANALYTICS: Reporting access (non-hierarchical)
|
|
104
|
+
</roles>
|
|
105
|
+
</multi_tenancy>
|
|
106
|
+
|
|
107
|
+
<request_flow>
|
|
108
|
+
1. Request arrives at Cloudflare Workers edge
|
|
109
|
+
2. requestContext middleware attaches transactionId, IP, userAgent
|
|
110
|
+
3. sessionAuth middleware validates session cookie from KV
|
|
111
|
+
4. accountMiddleware extracts accountId from query/header
|
|
112
|
+
5. Route handler executes business logic via services
|
|
113
|
+
6. auditedDb functions log state changes automatically
|
|
114
|
+
7. Response returned with proper error handling
|
|
115
|
+
</request_flow>
|
|
116
|
+
|
|
117
|
+
<data_flow>
|
|
118
|
+
Frontend (React)
|
|
119
|
+
→ TanStack Query
|
|
120
|
+
→ Fetch API
|
|
121
|
+
→ Hono Routes
|
|
122
|
+
→ Services
|
|
123
|
+
→ Drizzle ORM
|
|
124
|
+
→ D1 Database
|
|
125
|
+
</data_flow>
|
|
126
|
+
</architecture>
|
|
127
|
+
|
|
128
|
+
<database_schema>
|
|
129
|
+
<tables>
|
|
130
|
+
<users>
|
|
131
|
+
<description>Core user entity, one per person</description>
|
|
132
|
+
<columns>
|
|
133
|
+
- id: UUID (PK)
|
|
134
|
+
- googleId: string (unique, OAuth identifier)
|
|
135
|
+
- email: string (from OAuth provider)
|
|
136
|
+
- name: string (display name)
|
|
137
|
+
- avatarUrl: string | null (profile picture URL)
|
|
138
|
+
- status: enum ['active', 'inactive']
|
|
139
|
+
- providerIds: JSON string[] (future multi-provider support)
|
|
140
|
+
- isSuperAdmin: boolean (system-wide admin flag)
|
|
141
|
+
- createdAt, updatedAt, deletedAt: timestamps
|
|
142
|
+
- createdById, updatedById, deletedById: FK to users
|
|
143
|
+
</columns>
|
|
144
|
+
<indexes>
|
|
145
|
+
- UNIQUE on googleId
|
|
146
|
+
</indexes>
|
|
147
|
+
</users>
|
|
148
|
+
|
|
149
|
+
<accounts>
|
|
150
|
+
<description>Tenant/workspace entity</description>
|
|
151
|
+
<columns>
|
|
152
|
+
- id: UUID (PK)
|
|
153
|
+
- name: string (workspace name)
|
|
154
|
+
- description: string | null
|
|
155
|
+
- domain: string | null (unique, custom domain)
|
|
156
|
+
- createdAt, updatedAt, deletedAt: timestamps
|
|
157
|
+
</columns>
|
|
158
|
+
<indexes>
|
|
159
|
+
- UNIQUE on domain (where not null)
|
|
160
|
+
</indexes>
|
|
161
|
+
</accounts>
|
|
162
|
+
|
|
163
|
+
<user_accounts>
|
|
164
|
+
<description>Junction table for user-account membership</description>
|
|
165
|
+
<columns>
|
|
166
|
+
- userId: UUID (PK, FK to users, CASCADE)
|
|
167
|
+
- accountId: UUID (PK, FK to accounts, CASCADE)
|
|
168
|
+
- role: enum ['ADMIN', 'MANAGER', 'EDITOR', 'AUTHOR', 'VIEWER', 'BILLING', 'ANALYTICS']
|
|
169
|
+
</columns>
|
|
170
|
+
<constraints>
|
|
171
|
+
- PRIMARY KEY (userId, accountId)
|
|
172
|
+
- ON DELETE CASCADE for both FKs
|
|
173
|
+
</constraints>
|
|
174
|
+
</user_accounts>
|
|
175
|
+
|
|
176
|
+
<invitations>
|
|
177
|
+
<description>Pending team invitations</description>
|
|
178
|
+
<columns>
|
|
179
|
+
- id: UUID (PK)
|
|
180
|
+
- accountId: UUID (FK to accounts)
|
|
181
|
+
- email: string (invitee email)
|
|
182
|
+
- role: enum (same as user_accounts)
|
|
183
|
+
- token: string (unique, 64 chars, valid 7 days)
|
|
184
|
+
- invitedById: UUID (FK to users)
|
|
185
|
+
- expiresAt: timestamp
|
|
186
|
+
- acceptedAt: timestamp | null
|
|
187
|
+
- createdAt: timestamp
|
|
188
|
+
</columns>
|
|
189
|
+
<indexes>
|
|
190
|
+
- UNIQUE on token
|
|
191
|
+
- UNIQUE on (accountId, email)
|
|
192
|
+
</indexes>
|
|
193
|
+
</invitations>
|
|
194
|
+
|
|
195
|
+
<audit_logs>
|
|
196
|
+
<description>Complete audit trail for compliance</description>
|
|
197
|
+
<columns>
|
|
198
|
+
- id: UUID (PK)
|
|
199
|
+
- transactionId: string (groups related operations)
|
|
200
|
+
- accountId: UUID | null (FK to accounts)
|
|
201
|
+
- userId: UUID | null (FK to users, who performed)
|
|
202
|
+
- entity: string (e.g., 'User', 'Account', 'Auth')
|
|
203
|
+
- entityId: string (ID of affected entity)
|
|
204
|
+
- action: enum ['INSERT', 'UPDATE', 'DELETE', 'LOGIN', 'LOGOUT', 'SIGNUP', 'TOKEN_REFRESH', 'LOGIN_FAILED']
|
|
205
|
+
- changes: JSON | null (before/after state)
|
|
206
|
+
- ipAddress: string | null
|
|
207
|
+
- userAgent: string | null
|
|
208
|
+
- timestamp: timestamp
|
|
209
|
+
</columns>
|
|
210
|
+
<indexes>
|
|
211
|
+
- INDEX on (accountId, timestamp)
|
|
212
|
+
- INDEX on (entity, entityId)
|
|
213
|
+
- INDEX on action
|
|
214
|
+
</indexes>
|
|
215
|
+
</audit_logs>
|
|
216
|
+
|
|
217
|
+
<refresh_tokens>
|
|
218
|
+
<description>Token storage for session refresh (legacy)</description>
|
|
219
|
+
<columns>
|
|
220
|
+
- id: UUID (PK)
|
|
221
|
+
- userId: UUID (FK to users, CASCADE)
|
|
222
|
+
- tokenHash: string (SHA-256 hash, never plaintext)
|
|
223
|
+
- expiresAt: unix epoch (integer)
|
|
224
|
+
- createdAt: unix epoch (integer)
|
|
225
|
+
- revokedAt: unix epoch (integer) | null
|
|
226
|
+
</columns>
|
|
227
|
+
</refresh_tokens>
|
|
228
|
+
</tables>
|
|
229
|
+
|
|
230
|
+
<relationships>
|
|
231
|
+
users ─────┬───→ user_accounts ←───┬───── accounts
|
|
232
|
+
│ │
|
|
233
|
+
├───→ refresh_tokens ├───→ invitations
|
|
234
|
+
│ │
|
|
235
|
+
├───→ invitations (inviter)
|
|
236
|
+
│ │
|
|
237
|
+
└───→ audit_logs ←───────┘
|
|
238
|
+
</relationships>
|
|
239
|
+
</database_schema>
|
|
240
|
+
|
|
241
|
+
<api_endpoints>
|
|
242
|
+
<authentication prefix="/auth">
|
|
243
|
+
<endpoint method="GET" path="/login">
|
|
244
|
+
<description>Initiate Google OAuth flow with PKCE</description>
|
|
245
|
+
<query>redirect: string (optional, post-login redirect)</query>
|
|
246
|
+
<response>302 Redirect to Google</response>
|
|
247
|
+
<auth>None</auth>
|
|
248
|
+
</endpoint>
|
|
249
|
+
|
|
250
|
+
<endpoint method="GET" path="/callback">
|
|
251
|
+
<description>Handle Google OAuth callback</description>
|
|
252
|
+
<query>code: string, state: string</query>
|
|
253
|
+
<response>302 Redirect to app with session cookie</response>
|
|
254
|
+
<auth>None (creates session)</auth>
|
|
255
|
+
</endpoint>
|
|
256
|
+
|
|
257
|
+
<endpoint method="POST" path="/logout">
|
|
258
|
+
<description>Destroy session, clear cookies</description>
|
|
259
|
+
<response>200 { message: "Logged out successfully" }</response>
|
|
260
|
+
<auth>Session required</auth>
|
|
261
|
+
<audit>LOGOUT event logged</audit>
|
|
262
|
+
</endpoint>
|
|
263
|
+
|
|
264
|
+
<endpoint method="GET" path="/me">
|
|
265
|
+
<description>Get current authenticated user</description>
|
|
266
|
+
<response>200 { user: { id, email, name, avatarUrl, isSuperAdmin } }</response>
|
|
267
|
+
<auth>Session required</auth>
|
|
268
|
+
</endpoint>
|
|
269
|
+
|
|
270
|
+
<endpoint method="GET" path="/invite/:token">
|
|
271
|
+
<description>Accept invitation, store token, redirect to login</description>
|
|
272
|
+
<params>token: string (invitation token)</params>
|
|
273
|
+
<response>302 Redirect to /auth/login</response>
|
|
274
|
+
<auth>None</auth>
|
|
275
|
+
</endpoint>
|
|
276
|
+
</authentication>
|
|
277
|
+
|
|
278
|
+
<users prefix="/api/users">
|
|
279
|
+
<endpoint method="GET" path="/">
|
|
280
|
+
<description>List users (paginated, searchable)</description>
|
|
281
|
+
<query>page, limit, query (search email/name)</query>
|
|
282
|
+
<response>200 { data: User[], meta: { total, page, pages, hasMore } }</response>
|
|
283
|
+
<auth>Session + Account member</auth>
|
|
284
|
+
</endpoint>
|
|
285
|
+
|
|
286
|
+
<endpoint method="GET" path="/:id">
|
|
287
|
+
<description>Get user by ID</description>
|
|
288
|
+
<response>200 { user: User }</response>
|
|
289
|
+
<auth>Session + Account member</auth>
|
|
290
|
+
</endpoint>
|
|
291
|
+
|
|
292
|
+
<endpoint method="PATCH" path="/:id">
|
|
293
|
+
<description>Update user (name, status)</description>
|
|
294
|
+
<body>{ name?: string, status?: 'active' | 'inactive' }</body>
|
|
295
|
+
<response>200 { user: User }</response>
|
|
296
|
+
<auth>Session + ADMIN role</auth>
|
|
297
|
+
<audit>UPDATE event logged</audit>
|
|
298
|
+
</endpoint>
|
|
299
|
+
|
|
300
|
+
<endpoint method="DELETE" path="/:id">
|
|
301
|
+
<description>Soft delete user</description>
|
|
302
|
+
<response>204 No Content</response>
|
|
303
|
+
<auth>Session + ADMIN role</auth>
|
|
304
|
+
<audit>DELETE event logged</audit>
|
|
305
|
+
</endpoint>
|
|
306
|
+
|
|
307
|
+
<endpoint method="POST" path="/:id/restore">
|
|
308
|
+
<description>Restore soft-deleted user</description>
|
|
309
|
+
<response>200 { user: User }</response>
|
|
310
|
+
<auth>Session + Super Admin</auth>
|
|
311
|
+
<audit>UPDATE event logged</audit>
|
|
312
|
+
</endpoint>
|
|
313
|
+
|
|
314
|
+
<endpoint method="POST" path="/accounts">
|
|
315
|
+
<description>Bulk assign users to accounts</description>
|
|
316
|
+
<body>{ items: [{ userId, accountId, role }] }</body>
|
|
317
|
+
<response>200 { count: number }</response>
|
|
318
|
+
<auth>Session + MANAGER role</auth>
|
|
319
|
+
</endpoint>
|
|
320
|
+
|
|
321
|
+
<endpoint method="DELETE" path="/accounts">
|
|
322
|
+
<description>Bulk remove users from accounts</description>
|
|
323
|
+
<body>{ items: [{ userId, accountId }] }</body>
|
|
324
|
+
<response>200 { count: number }</response>
|
|
325
|
+
<auth>Session + MANAGER role</auth>
|
|
326
|
+
</endpoint>
|
|
327
|
+
</users>
|
|
328
|
+
|
|
329
|
+
<accounts prefix="/api/accounts">
|
|
330
|
+
<endpoint method="GET" path="/">
|
|
331
|
+
<description>List user's accounts</description>
|
|
332
|
+
<query>page, limit</query>
|
|
333
|
+
<response>200 { data: Account[], meta }</response>
|
|
334
|
+
<auth>Session</auth>
|
|
335
|
+
</endpoint>
|
|
336
|
+
|
|
337
|
+
<endpoint method="GET" path="/:id">
|
|
338
|
+
<description>Get account by ID</description>
|
|
339
|
+
<response>200 { account: Account }</response>
|
|
340
|
+
<auth>Session + Account member</auth>
|
|
341
|
+
</endpoint>
|
|
342
|
+
|
|
343
|
+
<endpoint method="POST" path="/">
|
|
344
|
+
<description>Create new account</description>
|
|
345
|
+
<body>{ name: string, description?: string }</body>
|
|
346
|
+
<response>201 { account: Account }</response>
|
|
347
|
+
<auth>Session + Super Admin</auth>
|
|
348
|
+
<audit>INSERT event logged</audit>
|
|
349
|
+
</endpoint>
|
|
350
|
+
|
|
351
|
+
<endpoint method="PATCH" path="/:id">
|
|
352
|
+
<description>Update account</description>
|
|
353
|
+
<body>{ name?: string, description?: string }</body>
|
|
354
|
+
<response>200 { account: Account }</response>
|
|
355
|
+
<auth>Session + Account ADMIN</auth>
|
|
356
|
+
<audit>UPDATE event logged</audit>
|
|
357
|
+
</endpoint>
|
|
358
|
+
|
|
359
|
+
<endpoint method="DELETE" path="/:id">
|
|
360
|
+
<description>Soft delete account</description>
|
|
361
|
+
<response>204 No Content</response>
|
|
362
|
+
<auth>Session + Super Admin</auth>
|
|
363
|
+
<audit>DELETE event logged</audit>
|
|
364
|
+
</endpoint>
|
|
365
|
+
|
|
366
|
+
<endpoint method="POST" path="/:id/restore">
|
|
367
|
+
<description>Restore soft-deleted account</description>
|
|
368
|
+
<response>200 { account: Account }</response>
|
|
369
|
+
<auth>Session + Super Admin</auth>
|
|
370
|
+
<audit>UPDATE event logged</audit>
|
|
371
|
+
</endpoint>
|
|
372
|
+
</accounts>
|
|
373
|
+
|
|
374
|
+
<invitations prefix="/api/invitations">
|
|
375
|
+
<endpoint method="POST" path="/">
|
|
376
|
+
<description>Create invitation or link existing user</description>
|
|
377
|
+
<body>{ email: string, role: Role }</body>
|
|
378
|
+
<response>201 { invitation } or 200 { linked: true }</response>
|
|
379
|
+
<auth>Session + Account member</auth>
|
|
380
|
+
<notes>
|
|
381
|
+
- If user exists: links immediately to account
|
|
382
|
+
- If user not found: sends email with invitation link
|
|
383
|
+
- Token valid for 7 days
|
|
384
|
+
</notes>
|
|
385
|
+
<audit>INSERT event logged</audit>
|
|
386
|
+
</endpoint>
|
|
387
|
+
|
|
388
|
+
<endpoint method="GET" path="/">
|
|
389
|
+
<description>List pending invitations for current account</description>
|
|
390
|
+
<response>200 { data: Invitation[] }</response>
|
|
391
|
+
<auth>Session + Account member</auth>
|
|
392
|
+
</endpoint>
|
|
393
|
+
|
|
394
|
+
<endpoint method="DELETE" path="/:id">
|
|
395
|
+
<description>Revoke pending invitation</description>
|
|
396
|
+
<response>204 No Content</response>
|
|
397
|
+
<auth>Session + MANAGER role</auth>
|
|
398
|
+
<audit>DELETE event logged</audit>
|
|
399
|
+
</endpoint>
|
|
400
|
+
</invitations>
|
|
401
|
+
|
|
402
|
+
<audits prefix="/api/audits">
|
|
403
|
+
<endpoint method="GET" path="/">
|
|
404
|
+
<description>Query audit logs with filters</description>
|
|
405
|
+
<query>
|
|
406
|
+
- page, limit (pagination)
|
|
407
|
+
- entity (filter by entity type)
|
|
408
|
+
- entityId (filter by entity ID)
|
|
409
|
+
- action (filter by action type)
|
|
410
|
+
</query>
|
|
411
|
+
<response>200 { data: AuditLog[], meta }</response>
|
|
412
|
+
<auth>Session + ADMIN or ANALYTICS role</auth>
|
|
413
|
+
<notes>Super admin sees all accounts, others see only their account</notes>
|
|
414
|
+
</endpoint>
|
|
415
|
+
</audits>
|
|
416
|
+
|
|
417
|
+
<storage prefix="/api/storage">
|
|
418
|
+
<endpoint method="POST" path="/upload-url">
|
|
419
|
+
<description>Generate upload URL for internal API upload endpoint</description>
|
|
420
|
+
<body>{ filename: string, contentType: string }</body>
|
|
421
|
+
<response>200 { url: string, name: string, publicUrl: string }</response>
|
|
422
|
+
<auth>Session</auth>
|
|
423
|
+
<notes>URL points to /api/storage/upload/:key; not a direct R2 presigned URL</notes>
|
|
424
|
+
</endpoint>
|
|
425
|
+
|
|
426
|
+
<endpoint method="PUT" path="/upload/:key">
|
|
427
|
+
<description>Upload file via API and store in R2</description>
|
|
428
|
+
<body>Binary file data</body>
|
|
429
|
+
<response>200 { success: true, key: string, publicUrl: string }</response>
|
|
430
|
+
<auth>Session</auth>
|
|
431
|
+
</endpoint>
|
|
432
|
+
|
|
433
|
+
<endpoint method="DELETE" path="/:key">
|
|
434
|
+
<description>Delete file from R2</description>
|
|
435
|
+
<response>204 No Content</response>
|
|
436
|
+
<auth>Session</auth>
|
|
437
|
+
</endpoint>
|
|
438
|
+
</storage>
|
|
439
|
+
|
|
440
|
+
<health prefix="/health">
|
|
441
|
+
<endpoint method="GET" path="/">
|
|
442
|
+
<description>Health check endpoint</description>
|
|
443
|
+
<response>200 { status: "ok", timestamp, environment }</response>
|
|
444
|
+
<auth>None</auth>
|
|
445
|
+
</endpoint>
|
|
446
|
+
</health>
|
|
447
|
+
|
|
448
|
+
<documentation>
|
|
449
|
+
<endpoint method="GET" path="/api/doc">OpenAPI JSON schema</endpoint>
|
|
450
|
+
<endpoint method="GET" path="/api/swagger">Swagger UI</endpoint>
|
|
451
|
+
</documentation>
|
|
452
|
+
</api_endpoints>
|
|
453
|
+
|
|
454
|
+
<frontend_pages>
|
|
455
|
+
<public_routes>
|
|
456
|
+
<route path="/">
|
|
457
|
+
<name>Landing Page</name>
|
|
458
|
+
<description>Marketing homepage with hero section and feature highlights</description>
|
|
459
|
+
<components>Hero, Features, CTA</components>
|
|
460
|
+
</route>
|
|
461
|
+
|
|
462
|
+
<route path="/login">
|
|
463
|
+
<name>Login Page</name>
|
|
464
|
+
<description>Google OAuth login button, redirects to /auth/login</description>
|
|
465
|
+
<components>LoginCard, GoogleButton</components>
|
|
466
|
+
</route>
|
|
467
|
+
|
|
468
|
+
<route path="/invite/:token">
|
|
469
|
+
<name>Invitation Page</name>
|
|
470
|
+
<description>Accept invitation, validates token, redirects to login</description>
|
|
471
|
+
<components>InvitationCard, AcceptButton</components>
|
|
472
|
+
</route>
|
|
473
|
+
</public_routes>
|
|
474
|
+
|
|
475
|
+
<authenticated_routes layout="_authenticated">
|
|
476
|
+
<route path="/dashboard">
|
|
477
|
+
<name>Dashboard</name>
|
|
478
|
+
<description>Main workspace overview with stats and quick actions</description>
|
|
479
|
+
<sections>
|
|
480
|
+
- Welcome message with user's first name
|
|
481
|
+
- Stats cards (users, accounts, API requests, uptime)
|
|
482
|
+
- Quick action cards (invite team, database, security)
|
|
483
|
+
- Recent activity feed (placeholder)
|
|
484
|
+
</sections>
|
|
485
|
+
</route>
|
|
486
|
+
|
|
487
|
+
<route path="/team">
|
|
488
|
+
<name>Team Management</name>
|
|
489
|
+
<description>Manage team members and invitations</description>
|
|
490
|
+
<sections>
|
|
491
|
+
- Active members list with roles
|
|
492
|
+
- Search/filter members by name/email
|
|
493
|
+
- Invite member dialog (email + role selector)
|
|
494
|
+
- Pending invitations with expiry countdown
|
|
495
|
+
- Resend/revoke invitation buttons
|
|
496
|
+
</sections>
|
|
497
|
+
<dialogs>InviteMemberDialog</dialogs>
|
|
498
|
+
</route>
|
|
499
|
+
|
|
500
|
+
<route path="/settings">
|
|
501
|
+
<name>User Settings</name>
|
|
502
|
+
<description>Personal profile and preferences</description>
|
|
503
|
+
<sections>
|
|
504
|
+
- Profile card (avatar, name, email)
|
|
505
|
+
- Edit profile form
|
|
506
|
+
- Connected accounts (Google, future: GitHub)
|
|
507
|
+
- Notification preferences (toggles)
|
|
508
|
+
- Account deletion
|
|
509
|
+
</sections>
|
|
510
|
+
<dialogs>DeleteAccountDialog</dialogs>
|
|
511
|
+
</route>
|
|
512
|
+
|
|
513
|
+
<route path="/account">
|
|
514
|
+
<name>Account Security</name>
|
|
515
|
+
<description>Security settings and session management</description>
|
|
516
|
+
<sections>
|
|
517
|
+
- Connected OAuth accounts
|
|
518
|
+
- Two-factor authentication (future)
|
|
519
|
+
- Password management (OAuth-only note)
|
|
520
|
+
- Active sessions list with device/location
|
|
521
|
+
- API keys management (future)
|
|
522
|
+
- Danger zone (export data, delete account)
|
|
523
|
+
</sections>
|
|
524
|
+
<dialogs>DeleteAccountDialog</dialogs>
|
|
525
|
+
</route>
|
|
526
|
+
|
|
527
|
+
<route path="/integrations">
|
|
528
|
+
<name>Integrations</name>
|
|
529
|
+
<description>Third-party connections and webhooks</description>
|
|
530
|
+
<sections>
|
|
531
|
+
- Integration grid (Slack, Discord, Stripe, GitHub, Linear, Zapier)
|
|
532
|
+
- Filter by category
|
|
533
|
+
- Search integrations
|
|
534
|
+
- Webhooks configuration
|
|
535
|
+
- Create webhook dialog
|
|
536
|
+
</sections>
|
|
537
|
+
<dialogs>CreateWebhookDialog</dialogs>
|
|
538
|
+
</route>
|
|
539
|
+
</authenticated_routes>
|
|
540
|
+
</frontend_pages>
|
|
541
|
+
|
|
542
|
+
<ui_components>
|
|
543
|
+
<layout>
|
|
544
|
+
<sidebar>
|
|
545
|
+
- Navigation links (Dashboard, Team, Settings, Account, Integrations)
|
|
546
|
+
- User profile card with avatar and name
|
|
547
|
+
- Logout button
|
|
548
|
+
- Collapsible on mobile
|
|
549
|
+
</sidebar>
|
|
550
|
+
<main_content>
|
|
551
|
+
- Container with max-width constraint
|
|
552
|
+
- Responsive padding
|
|
553
|
+
- Page header with title and description
|
|
554
|
+
</main_content>
|
|
555
|
+
</layout>
|
|
556
|
+
|
|
557
|
+
<primitives>
|
|
558
|
+
<button variants="default, secondary, outline, destructive, ghost, link" />
|
|
559
|
+
<input types="text, email, password, search" />
|
|
560
|
+
<badge variants="default, secondary, outline, destructive" />
|
|
561
|
+
<avatar fallback="initials from name" />
|
|
562
|
+
<card sections="header, content, footer" />
|
|
563
|
+
<dialog modal="true, with overlay" />
|
|
564
|
+
<tabs orientation="horizontal" />
|
|
565
|
+
<separator orientation="horizontal, vertical" />
|
|
566
|
+
<skeleton loading_state="true" />
|
|
567
|
+
</primitives>
|
|
568
|
+
|
|
569
|
+
<forms>
|
|
570
|
+
<pattern>React Hook Form + Zod validation</pattern>
|
|
571
|
+
<components>Form, FormField, FormItem, FormLabel, FormControl, FormMessage</components>
|
|
572
|
+
<error_handling>Inline validation messages</error_handling>
|
|
573
|
+
</forms>
|
|
574
|
+
|
|
575
|
+
<feedback>
|
|
576
|
+
<toast provider="Sonner">
|
|
577
|
+
- Success (green)
|
|
578
|
+
- Error (red)
|
|
579
|
+
- Info (blue)
|
|
580
|
+
- Warning (yellow)
|
|
581
|
+
</toast>
|
|
582
|
+
<error_fallback>
|
|
583
|
+
- Error message display
|
|
584
|
+
- Retry button
|
|
585
|
+
- Go back button
|
|
586
|
+
- Go home button
|
|
587
|
+
</error_fallback>
|
|
588
|
+
</feedback>
|
|
589
|
+
</ui_components>
|
|
590
|
+
|
|
591
|
+
<design_system>
|
|
592
|
+
<colors>
|
|
593
|
+
<light_mode>
|
|
594
|
+
- Background: white (#ffffff)
|
|
595
|
+
- Foreground: near-black (#0a0a0a)
|
|
596
|
+
- Card: white (#ffffff)
|
|
597
|
+
- Border: light gray (#e5e5e5)
|
|
598
|
+
- Primary: brand color
|
|
599
|
+
- Muted: gray (#f5f5f5)
|
|
600
|
+
- Destructive: red (#dc2626)
|
|
601
|
+
</light_mode>
|
|
602
|
+
<dark_mode>
|
|
603
|
+
- Background: near-black (#0a0a0a)
|
|
604
|
+
- Foreground: off-white (#fafafa)
|
|
605
|
+
- Card: dark gray (#0a0a0a)
|
|
606
|
+
- Border: dark gray (#262626)
|
|
607
|
+
- Primary: brand color (adjusted)
|
|
608
|
+
- Muted: dark gray (#262626)
|
|
609
|
+
- Destructive: red (#dc2626)
|
|
610
|
+
</dark_mode>
|
|
611
|
+
</colors>
|
|
612
|
+
|
|
613
|
+
<typography>
|
|
614
|
+
<font_family>Inter, system-ui, sans-serif</font_family>
|
|
615
|
+
<font_mono>JetBrains Mono, Consolas, monospace</font_mono>
|
|
616
|
+
<scale>
|
|
617
|
+
- text-xs: 0.75rem
|
|
618
|
+
- text-sm: 0.875rem
|
|
619
|
+
- text-base: 1rem
|
|
620
|
+
- text-lg: 1.125rem
|
|
621
|
+
- text-xl: 1.25rem
|
|
622
|
+
- text-2xl: 1.5rem
|
|
623
|
+
- text-3xl: 1.875rem
|
|
624
|
+
</scale>
|
|
625
|
+
</typography>
|
|
626
|
+
|
|
627
|
+
<spacing>
|
|
628
|
+
<scale>4px base (0.25rem)</scale>
|
|
629
|
+
<common>
|
|
630
|
+
- p-2: 8px
|
|
631
|
+
- p-4: 16px
|
|
632
|
+
- p-6: 24px
|
|
633
|
+
- p-8: 32px
|
|
634
|
+
- gap-2, gap-4, gap-6
|
|
635
|
+
</common>
|
|
636
|
+
</spacing>
|
|
637
|
+
|
|
638
|
+
<borders>
|
|
639
|
+
<radius>
|
|
640
|
+
- rounded-sm: 2px
|
|
641
|
+
- rounded: 4px
|
|
642
|
+
- rounded-md: 6px
|
|
643
|
+
- rounded-lg: 8px
|
|
644
|
+
- rounded-xl: 12px
|
|
645
|
+
- rounded-full: 9999px
|
|
646
|
+
</radius>
|
|
647
|
+
</borders>
|
|
648
|
+
|
|
649
|
+
<shadows>
|
|
650
|
+
<elevation>
|
|
651
|
+
- shadow-sm: subtle depth
|
|
652
|
+
- shadow: default cards
|
|
653
|
+
- shadow-md: elevated elements
|
|
654
|
+
- shadow-lg: modals, dropdowns
|
|
655
|
+
</elevation>
|
|
656
|
+
</shadows>
|
|
657
|
+
|
|
658
|
+
<animations>
|
|
659
|
+
<transitions>150ms ease-in-out default</transitions>
|
|
660
|
+
<patterns>
|
|
661
|
+
- Fade in for page transitions
|
|
662
|
+
- Slide in for sidebars/panels
|
|
663
|
+
- Scale for modals
|
|
664
|
+
- Skeleton pulse for loading
|
|
665
|
+
</patterns>
|
|
666
|
+
</animations>
|
|
667
|
+
</design_system>
|
|
668
|
+
|
|
669
|
+
<security>
|
|
670
|
+
<authentication>
|
|
671
|
+
- OAuth 2.0 with PKCE (no client secret in browser)
|
|
672
|
+
- Session cookies: httpOnly, secure, sameSite=Lax
|
|
673
|
+
- Session stored in KV with expiration
|
|
674
|
+
- Refresh tokens hashed before storage (SHA-256)
|
|
675
|
+
</authentication>
|
|
676
|
+
|
|
677
|
+
<authorization>
|
|
678
|
+
- Role-based access control (RBAC)
|
|
679
|
+
- Hierarchical roles with level comparison
|
|
680
|
+
- Account-scoped permissions
|
|
681
|
+
- Super admin bypass for system operations
|
|
682
|
+
</authorization>
|
|
683
|
+
|
|
684
|
+
<data_protection>
|
|
685
|
+
- Soft deletes preserve data integrity
|
|
686
|
+
- Audit logging for all state changes
|
|
687
|
+
- Request context (IP, User-Agent) captured
|
|
688
|
+
- Transaction IDs for operation correlation
|
|
689
|
+
</data_protection>
|
|
690
|
+
|
|
691
|
+
<api_security>
|
|
692
|
+
- Input validation with Zod schemas
|
|
693
|
+
- CORS configuration per environment
|
|
694
|
+
- Error messages sanitized (no stack traces in prod)
|
|
695
|
+
- Rate limiting (Cloudflare default)
|
|
696
|
+
</api_security>
|
|
697
|
+
</security>
|
|
698
|
+
|
|
699
|
+
<implementation_status>
|
|
700
|
+
<completed>
|
|
701
|
+
- Google OAuth login with PKCE flow
|
|
702
|
+
- Session management (KV + cookies)
|
|
703
|
+
- Multi-tenant user/account system
|
|
704
|
+
- User-account relationships with roles
|
|
705
|
+
- Invitation system with email sending
|
|
706
|
+
- Audit logging (all CRUD + auth events)
|
|
707
|
+
- Soft delete with restore functionality
|
|
708
|
+
- File storage (R2) with presigned URLs
|
|
709
|
+
- OpenAPI/Swagger documentation
|
|
710
|
+
- Error handling + validation
|
|
711
|
+
- Role-based access control
|
|
712
|
+
- Pagination + search
|
|
713
|
+
- Super admin pre-registration
|
|
714
|
+
- Logout with redirect
|
|
715
|
+
- 95% test coverage (server)
|
|
716
|
+
- 90% test coverage (client)
|
|
717
|
+
</completed>
|
|
718
|
+
|
|
719
|
+
<partial>
|
|
720
|
+
- Webhooks (schema exists, storage not implemented)
|
|
721
|
+
- Integrations page (UI mockups only)
|
|
722
|
+
- Dashboard analytics (placeholder data)
|
|
723
|
+
</partial>
|
|
724
|
+
|
|
725
|
+
<planned>
|
|
726
|
+
- Two-factor authentication (TOTP)
|
|
727
|
+
- GitHub OAuth integration
|
|
728
|
+
- API keys management
|
|
729
|
+
- Payment/billing integration (Stripe)
|
|
730
|
+
- Email templates customization
|
|
731
|
+
- Real-time notifications (WebSocket)
|
|
732
|
+
- Activity feed with actual data
|
|
733
|
+
- Export data functionality
|
|
734
|
+
- Account switching UI
|
|
735
|
+
</planned>
|
|
736
|
+
</implementation_status>
|
|
737
|
+
|
|
738
|
+
<environment_variables>
|
|
739
|
+
<required>
|
|
740
|
+
GOOGLE_CLIENT_ID # Google OAuth client ID
|
|
741
|
+
GOOGLE_CLIENT_SECRET # Google OAuth client secret
|
|
742
|
+
GOOGLE_REDIRECT_URI # OAuth callback URL
|
|
743
|
+
APP_URL # Application base URL
|
|
744
|
+
JWT_SECRET # Session signing key (min 32 chars)
|
|
745
|
+
SENDGRID_API_KEY # SendGrid API key for emails
|
|
746
|
+
SENDGRID_FROM_EMAIL # Sender email address
|
|
747
|
+
</required>
|
|
748
|
+
|
|
749
|
+
<optional>
|
|
750
|
+
ENVIRONMENT # production | staging | development
|
|
751
|
+
SUPER_ADMIN_EMAILS # Comma-separated admin emails
|
|
752
|
+
CORS_ORIGINS # Comma-separated allowed origins
|
|
753
|
+
R2_PUBLIC_URL # R2 bucket public URL
|
|
754
|
+
JWT_EXPIRY_MINUTES # Access token expiry (default: 15)
|
|
755
|
+
REFRESH_TOKEN_EXPIRY_DAYS # Refresh token expiry (default: 30)
|
|
756
|
+
</optional>
|
|
757
|
+
|
|
758
|
+
<cloudflare_bindings>
|
|
759
|
+
DB # D1 Database binding
|
|
760
|
+
SESSIONS # KV Namespace for sessions
|
|
761
|
+
R2_BUCKET # R2 Bucket for file storage
|
|
762
|
+
ASSETS # Static assets binding
|
|
763
|
+
</cloudflare_bindings>
|
|
764
|
+
</environment_variables>
|
|
765
|
+
|
|
766
|
+
<development>
|
|
767
|
+
<commands>
|
|
768
|
+
npm run dev # Start dev server (Vite + Wrangler)
|
|
769
|
+
npm run build # Build for production
|
|
770
|
+
npm run deploy # Deploy to Cloudflare Workers
|
|
771
|
+
|
|
772
|
+
npm run db:migrate:local # Apply migrations locally
|
|
773
|
+
npm run db:migrate:remote # Apply migrations to production
|
|
774
|
+
npm run db:seed # Seed test data
|
|
775
|
+
|
|
776
|
+
npm run test:unit:server # Backend unit tests
|
|
777
|
+
npm run test:unit:client # Frontend tests
|
|
778
|
+
npm run test:integration # Integration tests
|
|
779
|
+
npm run test:e2e # Playwright E2E tests
|
|
780
|
+
npm run test:e2e:ui # Playwright interactive UI
|
|
781
|
+
|
|
782
|
+
npm run lint # ESLint
|
|
783
|
+
npm run cf-typegen # Generate Cloudflare types
|
|
784
|
+
</commands>
|
|
785
|
+
|
|
786
|
+
<path_aliases>
|
|
787
|
+
@/ → src/client/
|
|
788
|
+
@shared/ → src/shared/
|
|
789
|
+
@server/ → src/server/
|
|
790
|
+
</path_aliases>
|
|
791
|
+
|
|
792
|
+
<workflow>
|
|
793
|
+
1. Make changes
|
|
794
|
+
2. Run unit tests for affected area
|
|
795
|
+
3. Run lint to check code style
|
|
796
|
+
4. Run E2E tests for critical paths
|
|
797
|
+
5. Verify build succeeds
|
|
798
|
+
6. Deploy with `npm run deploy`
|
|
799
|
+
</workflow>
|
|
800
|
+
</development>
|
|
801
|
+
|
|
802
|
+
<file_structure>
|
|
803
|
+
src/
|
|
804
|
+
├── server/ # Backend (Hono.js)
|
|
805
|
+
│ ├── routes/ # API endpoints
|
|
806
|
+
│ │ ├── auth/ # OAuth, logout, me
|
|
807
|
+
│ │ ├── users/ # User CRUD
|
|
808
|
+
│ │ ├── accounts/ # Account CRUD
|
|
809
|
+
│ │ ├── invitations/ # Team invites
|
|
810
|
+
│ │ ├── audits/ # Audit log queries
|
|
811
|
+
│ │ ├── storage/ # R2 file operations
|
|
812
|
+
│ │ └── health/ # Health check
|
|
813
|
+
│ ├── services/ # Business logic
|
|
814
|
+
│ ├── middleware/ # Auth, CORS, logging
|
|
815
|
+
│ ├── db/
|
|
816
|
+
│ │ ├── schema/ # Drizzle table definitions
|
|
817
|
+
│ │ └── migrations/ # SQL migrations
|
|
818
|
+
│ ├── lib/ # Utilities
|
|
819
|
+
│ └── auth/ # RBAC guards
|
|
820
|
+
│
|
|
821
|
+
├── client/ # Frontend (React)
|
|
822
|
+
│ ├── routes/ # TanStack file-based routing
|
|
823
|
+
│ │ ├── _authenticated/ # Protected pages
|
|
824
|
+
│ │ └── *.tsx # Public pages
|
|
825
|
+
│ ├── components/
|
|
826
|
+
│ │ └── ui/ # Reusable UI components
|
|
827
|
+
│ └── hooks/ # React hooks
|
|
828
|
+
│
|
|
829
|
+
├── shared/ # Shared between client/server
|
|
830
|
+
│ ├── schemas/ # Zod validation schemas
|
|
831
|
+
│ └── types/ # TypeScript types
|
|
832
|
+
│
|
|
833
|
+
└── e2e/ # Playwright E2E tests
|
|
834
|
+
</file_structure>
|
|
835
|
+
|
|
836
|
+
<key_files>
|
|
837
|
+
src/server/index.ts # Hono app entry
|
|
838
|
+
src/server/routes/index.ts # API router
|
|
839
|
+
src/server/db/schema/ # Database schema
|
|
840
|
+
src/client/routes/__root.tsx # React app root
|
|
841
|
+
src/client/routes/_authenticated.tsx # Auth layout
|
|
842
|
+
wrangler.json # Cloudflare config
|
|
843
|
+
drizzle.config.ts # Drizzle ORM config
|
|
844
|
+
playwright.config.ts # E2E test config
|
|
845
|
+
vitest.config.ts # Unit test config
|
|
846
|
+
</key_files>
|
|
847
|
+
|
|
848
|
+
<success_criteria>
|
|
849
|
+
<functionality>
|
|
850
|
+
- OAuth authentication works smoothly
|
|
851
|
+
- Multi-tenant isolation is enforced
|
|
852
|
+
- Role-based access control is accurate
|
|
853
|
+
- Invitation system sends emails correctly
|
|
854
|
+
- Audit logging captures all events
|
|
855
|
+
- File uploads to R2 work reliably
|
|
856
|
+
</functionality>
|
|
857
|
+
|
|
858
|
+
<performance>
|
|
859
|
+
- Page loads under 500ms (edge deployment)
|
|
860
|
+
- API responses under 100ms
|
|
861
|
+
- No blocking operations in critical path
|
|
862
|
+
- Efficient database queries with indexes
|
|
863
|
+
</performance>
|
|
864
|
+
|
|
865
|
+
<reliability>
|
|
866
|
+
- 95%+ test coverage on server
|
|
867
|
+
- 90%+ test coverage on client
|
|
868
|
+
- Error boundaries prevent crashes
|
|
869
|
+
- Graceful degradation for network issues
|
|
870
|
+
</reliability>
|
|
871
|
+
|
|
872
|
+
<security>
|
|
873
|
+
- No sensitive data in logs
|
|
874
|
+
- Proper CORS configuration
|
|
875
|
+
- Session security (httpOnly, secure)
|
|
876
|
+
- Input validation on all endpoints
|
|
877
|
+
</security>
|
|
878
|
+
</success_criteria>
|
|
879
|
+
</project_specification>
|