Conversation
Dependabot auto-PRs are noisy and often fail with pnpm workspaces. Security alerts remain enabled in repo settings for vulnerability notifications. Dependencies will be updated manually as needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Slug auto-generates from project name by default (read-only). Click "Customize" to edit independently for shorter email domains. Click "Reset to auto" to re-sync with project name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ephemeral per-session demo accounts with 1-hour TTL, L2 capability (sandbox writes, no real SMTP), and an extensibility hook so future tools in the deck can plug in their own seed data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
16 tasks across 4 phases: schema, demo module core, web UI, verification. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add isDemo to the Prisma select in both jwt and jwt-cookie strategies so req.user.isDemo is populated for downstream guards (BlockDemo). Update the JwtAuthGuard handleRequest TUser default to include isDemo: boolean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce DemoSeeder interface and DemoSeederRegistry to coordinate tool-specific demo data seeding. Uses a factory-based provider in DemoModule so concrete seeders (DevInbox, future tools) can be appended to the inject list without colliding on a shared DI token. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces @BlockDemo() decorator and a globally-registered BlockDemoGuard that rejects demo users on routes marked sensitive. Applied to the change-password handler as the first protected route. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Throw UnauthorizedException when a @BlockDemo()-decorated route is hit without req.user, instead of silently allowing. Removes dependence on APP_GUARD ordering between JwtAuthGuard and BlockDemoGuard. Adds a unit test for the missing-user case and documents the invariant on the guard class. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds POST /api/auth/demo that creates a demo user (isDemo=true) with a random unusable password, runs all registered DemoSeeders, and issues JWT + refresh token via auth cookies. Gated by DEMO_MODE_ENABLED (returns 404 when disabled) and rate-limited to 2 requests/hour. Also opens AuthService.generateAccessToken/generateRefreshToken for reuse and adds issueTokensForUser() for passwordless auth flows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restore private visibility on generateAccessToken/generateRefreshToken in AuthService (same-class access from issueTokensForUser is legal). - Wire DEMO_RATE_LIMIT_PER_HOUR into the @Throttle decorator literal and drop the unused DemoConfig.rateLimitPerHour getter. - Add DemoController spec covering service wiring, token issuance, cookie setting, and expiresAt computation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the first concrete DemoSeeder implementation, which creates a "Demo Inbox" project and populates it with 5 clearly-fake sample emails (welcome, password-reset, receipt, newsletter, attachment reference) so new demo users have something to explore immediately. - sample-emails.ts: 5 fixtures using example.com/.org addresses and href="#" placeholders. No real brands, URLs, tracking pixels, or PII. - devinbox-demo.seeder.ts: suffixes the project slug with 6 chars of randomUUID() to sidestep the globally-unique slug constraint across multiple demo users. - Attachment row intentionally not seeded — the 5th email references a pretend PDF in its HTML only, which is enough to exercise the inbox UI without wiring storage paths. - demo.module.ts: extends the factory-based DemoSeederRegistry inject list to include the new seeder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds POST /api/projects/:id/demo/inject-email for demo users to drop a realistic fake email into one of their projects. Enforces: - caller must have isDemo=true (else 403) - project must be owned by the caller (else 404) - cap of 20 injected emails per project (else 403) Cap accounting uses a reserved `@inject.demo.local` sender domain rather than a dedicated boolean marker column. Trade-off: no schema change and self-documenting in DB inspection, at the cost of coupling cap semantics to a magic-string domain. Seeded sample emails (RFC 2606 `@example.com`/`@example.org`) never collide with this count. Ownership check is inlined as a single prisma.project.findFirst rather than depending on ProjectsService, to keep DemoModule from importing ProjectsModule. Pool of 10 injectable templates (shipping, calendar, security, invoice, mention, CI, magic link, product, survey, support) lives in seeders/injectable-emails.ts; injectTestEmail picks one at random. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was demo-inbox-<id>. Shorter slug makes the demo email address (e.g. *@demo-abc123.<domain>) less visually cluttered in the UI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
So demo expiry redirect fires from any page, not only dashboard. Body becomes flex-col so the banner docks above a flex-1 content area; dashboard switches from h-screen to flex-1 min-h-0 to fill that slot. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Button inherited text color against white background, rendering invisible. Explicit text-gray-700 matches the neutral palette. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Type of Change
Related Issues
Closes #
Changes Made
Screenshots (if applicable)
Testing
Checklist
Additional Notes