FS-001: User Management Workflows
Overview
This specification defines the user management workflows for the Ptidonjon platform, including user registration, authentication, session management, password reset, and external service integrations. The system supports multiple user acquisition channels (website direct registration and Instagram chatbot) with a unified user model.
User Stories
US-001.1: Website Registration
As a visitor, I want to create an account on the website using my email and password so that I can access the platform's features.
US-001.2: Instagram Auto-Registration
As an Instagram user, I want my account to be automatically created when I first message the chatbot so that I can start using the service without manual registration.
US-001.3: Email/Password Login
As a registered user, I want to log in with my email and password so that I can access my personal space.
US-001.4: Magic Link Login
As a user (especially Instagram-originated), I want to log in via a secure magic link so that I can access my content without remembering credentials.
US-001.5: Profile Completion
As a pre-registered user (via Instagram), I want to complete my profile with email and password so that I have full access to my account.
US-001.6: Password Reset
As a registered user, I want to reset my password via a magic link so that I can regain access to my account if I forget my credentials.
Functional Requirements
FS-001.1: User Registration - Website
Description: The system shall allow visitors to create accounts directly on the website.
Acceptance Criteria:
- AC-001.1.1: The system shall accept email and password for registration
- AC-001.1.2: The system shall validate the password against the password strength requirements (see BS-001.7)
- AC-001.1.3: The system shall verify the email is not already registered (see BS-001.8)
- AC-001.1.4: The system shall create a user record with state "registered" and a unique sourceId in the format "website-{uuid}"
- AC-001.1.5: The system shall hash the password before storage
- AC-001.1.6: The system shall return an authentication token upon successful registration
- AC-001.1.7: The system shall redirect the user to their personal space after registration
Test Scenarios:
GIVEN a visitor on the signup page
WHEN they provide a valid email and password meeting strength requirements
THEN a new user is created with state "registered" and a unique sourceId in the format "website-{uuid}"
AND the user receives an authentication token
AND the user is redirected to their personal space
GIVEN a visitor on the signup page
WHEN they provide a password that does not meet strength requirements
THEN an error message is displayed indicating the password requirements
AND no user is created
GIVEN a visitor on the signup page
WHEN they provide an email that is already registered
THEN an error message is displayed asking to choose another email or use "forgot password"
AND no duplicate user is created
FS-001.2: User Registration - Instagram (Auto-Registration)
Description: The system shall automatically create user accounts when Instagram users first interact with the chatbot.
Acceptance Criteria:
- AC-001.2.1: The system shall detect new Instagram users via webhook messages
- AC-001.2.2: The system shall create a user record with state "preregistered" and sourceId set to the Instagram user ID
- AC-001.2.3: The system shall not create duplicate users for the same Instagram sourceId
- AC-001.2.4: The system shall validate webhook authenticity before processing
Test Scenarios:
GIVEN an Instagram webhook request with a sender ID not in the database
WHEN the request passes authenticity validation
THEN a new user is created with state "preregistered" and sourceId equal to the Instagram sender ID
GIVEN an Instagram webhook request with a sender ID already in the database
WHEN the request is processed
THEN no new user is created
FS-001.3: Authentication - Email/Password Login
Description: The system shall authenticate users via email and password credentials.
Acceptance Criteria:
- AC-001.3.1: The system shall accept email and password for login
- AC-001.3.2: The system shall verify the password against the stored hash
- AC-001.3.3: The system shall return an authentication token upon successful login
- AC-001.3.4: The system shall display an error message for invalid credentials
- AC-001.3.5: The system shall redirect authenticated users to their personal space
Test Scenarios:
GIVEN a registered user
WHEN they provide correct email and password
THEN they receive an authentication token
AND are redirected to their personal space
GIVEN a login attempt
WHEN the credentials are invalid
THEN an error message is displayed
AND no token is issued
FS-001.4: Authentication - Magic Link Login
Description: The system shall provide passwordless authentication via temporary magic links.
Acceptance Criteria:
- AC-001.4.1: The system shall generate magic links containing a secure token with embedded user and context data
- AC-001.4.2: The system shall store the token as a one-time use token on the user record
- AC-001.4.3: The system shall validate the token against the stored one-time token
- AC-001.4.4: The system shall invalidate (delete) the token after successful use
- AC-001.4.5: The system shall return an authentication token and context data (e.g., universeId) upon successful validation
- AC-001.4.6: The system shall reject expired or already-used tokens
Test Scenarios:
GIVEN a valid magic link token
WHEN the user accesses the link
THEN the token is validated
AND the user receives an authentication token
AND the one-time token is deleted from the user record
AND the user is redirected to the appropriate context (e.g., their universe)
GIVEN an invalid or already-used magic link token
WHEN the user accesses the link
THEN an error message is displayed
AND no authentication token is issued
FS-001.5: Profile Completion (Pre-registered to Registered)
Description: The system shall prompt pre-registered users to complete their profile with email and password.
Acceptance Criteria:
- AC-001.5.1: The system shall detect when a pre-registered user has generated content (cover image exists) but lacks an email
- AC-001.5.2: The system shall display a mandatory profile completion modal after a delay
- AC-001.5.3: The modal shall not be dismissible - users must complete their profile to proceed
- AC-001.5.4: The system shall validate the password against strength requirements (see BS-001.7)
- AC-001.5.5: The system shall verify the email is not already registered (see BS-001.8)
- AC-001.5.6: The system shall update the user credentials in the database
- AC-001.5.7: The system shall hide the modal once email and password are provided
- AC-001.5.8: The system shall require authentication (JWT) for the completion endpoint
Test Scenarios:
GIVEN a pre-registered user viewing their book
WHEN a cover image exists AND the user has no email on record
THEN after the configured delay, a profile completion modal is displayed
AND the modal cannot be dismissed
GIVEN the profile completion modal is displayed
WHEN the user submits valid email and password meeting strength requirements
THEN their credentials are updated
AND the modal is hidden
AND a new authentication token is issued
GIVEN the profile completion modal is displayed
WHEN the user submits an email that is already registered
THEN an error message is displayed asking to choose another email or use "forgot password"
AND the modal remains visible
FS-001.6: Session Management
Description: The system shall manage user sessions via JWT tokens with automatic renewal.
Acceptance Criteria:
- AC-001.6.1: All protected endpoints shall require a valid JWT token
- AC-001.6.2: The system shall attach authenticated user data to requests
- AC-001.6.3: The system shall persist the JWT token on the client (local storage)
- AC-001.6.4: The system shall reject requests with invalid or expired tokens
- AC-001.6.5: The system shall allow users to log out by clearing the session
- AC-001.6.6: JWT tokens shall expire after 72 hours (see BS-001.9)
- AC-001.6.7: The system shall automatically renew tokens before expiration (see BS-001.10)
Test Scenarios:
GIVEN a request to a protected endpoint
WHEN a valid JWT is provided
THEN the request is processed with the authenticated user context
GIVEN a request to a protected endpoint
WHEN no JWT or an invalid JWT is provided
THEN the request is rejected with an authorization error
GIVEN an active user session
WHEN the token approaches expiration
THEN the system automatically renews the token
AND the user session continues uninterrupted
FS-001.7: User Data Retrieval
Description: The system shall allow authenticated users to retrieve their profile data.
Acceptance Criteria:
- AC-001.7.1: The system shall provide an endpoint to retrieve the current user's data
- AC-001.7.2: The system shall exclude sensitive fields (password) from the response
- AC-001.7.3: The endpoint shall require authentication
Test Scenarios:
GIVEN an authenticated user
WHEN they request their profile data
THEN they receive their user data without the password field
FS-001.8: Password Reset
Description: The system shall allow registered users to reset their password via a magic link sent to their email.
Acceptance Criteria:
- AC-001.8.1: The system shall provide a "forgot password" option on the login page
- AC-001.8.2: The system shall accept an email address for password reset requests
- AC-001.8.3: The system shall send a magic link to the provided email if the email exists in the system
- AC-001.8.4: The system shall not reveal whether an email exists (security consideration)
- AC-001.8.5: When the user clicks the magic link, a password reset modal shall be displayed
- AC-001.8.6: The password reset modal shall be similar in design to the profile completion modal
- AC-001.8.7: The system shall validate the new password against strength requirements (see BS-001.7)
- AC-001.8.8: Upon successful password reset, the system shall issue a new authentication token
- AC-001.8.9: The magic link shall be single-use (invalidated after use)
Test Scenarios:
GIVEN a user on the login page
WHEN they click "forgot password" and enter their registered email
THEN a magic link is sent to their email
AND a confirmation message is displayed (without revealing if email exists)
GIVEN a user who clicked a valid password reset magic link
WHEN the password reset modal is displayed
AND they enter a new password meeting strength requirements
THEN their password is updated
AND they receive an authentication token
AND are redirected to their personal space
GIVEN a user who clicked an already-used password reset link
WHEN they attempt to reset their password
THEN an error message is displayed
AND no password change occurs
Business Rules
BS-001.1: User Identification and Source Linking
Rule: Each user is associated with a globally unique sourceId that identifies their origin and ensures uniqueness across all users.
Rationale: The platform supports multiple user acquisition channels that need to be tracked and distinguished. Each sourceId must be globally unique to support data integrity during migrations and prevent duplicate user issues.
Specifics:
- For Instagram users: sourceId = Instagram user ID (unique per user)
- For website users: sourceId = "website-{uuid}" where {uuid} is a system-generated unique identifier
- Each sourceId must be globally unique across all users in the system
- No two users may share the same sourceId
Examples:
- Instagram user "123456789" creates sourceId = "123456789" (unique)
- Website user "john@example.com" creates sourceId = "website-550e8400-e29b-41d4-a716-446655440000" (unique)
- Second website user "jane@example.com" creates sourceId = "website-6ba7b810-9dad-11d1-80b4-00c04fd430c8" (different unique value)
- Second message from Instagram "123456789" does not create a new user
Note: The sourceId is primarily meaningful during user registration to identify the acquisition channel. Once registration is complete, the sourceId serves no ongoing functional purpose beyond historical tracking.
BS-001.2: User States
Rule: Users exist in one of two states: "preregistered" or "registered".
Rationale: Instagram users start with minimal information and may later complete their profile.
State Definitions:
- preregistered: User has sourceId only (no email/password). Created via Instagram.
- registered: User has complete credentials (email and password).
State Transitions:
- preregistered -> registered: Via profile completion (providing email/password)
- registered: Created directly via website registration
BS-001.3: Temporary Token Lifecycle
Rule: One-time tokens (magic links) are single-use and must be invalidated after use.
Rationale: Security measure to prevent token reuse and unauthorized access.
Specifics:
- Token is stored on user record upon creation
- Token is deleted from user record upon successful validation
- Invalid tokens (not found) result in authentication failure
BS-001.4: Instagram Webhook Authenticity
Rule: All Instagram webhook requests must be cryptographically verified before processing.
Rationale: Prevents spoofed requests from creating unauthorized users or executing actions.
Verification Method:
- Validate x-hub-signature-256 header against request body using the app secret
BS-001.5: Password Security
Rule: User passwords must be hashed before storage.
Rationale: Protect user credentials in case of database breach.
BS-001.6: Email Update on Payment
Rule: When a payment event occurs, the user's email is updated if not already set.
Rationale: Capture email during checkout for users who haven't completed registration.
Conditions:
- Only updates if user has no existing email
- Email comes from the payment provider (Stripe)
BS-001.7: Password Strength Requirements
Rule: Passwords must meet minimum strength requirements to be accepted.
Rationale: Ensure user accounts are protected with sufficiently strong passwords.
Reference: Password validation is defined in the shared package (packages/shared/src/acceptors/password/condition.ts)
Valid Passwords: A password is considered valid if it meets EITHER the Medium OR Strong criteria:
Medium Password Requirements:
- Minimum 6 characters in length
- Must contain at least 2 of the following:
- At least one lowercase letter (a-z)
- At least one uppercase letter (A-Z)
- At least one number (0-9)
Strong Password Requirements:
- Minimum 8 characters in length
- Must contain ALL of the following:
- At least one lowercase letter (a-z)
- At least one uppercase letter (A-Z)
- At least one number (0-9)
- At least one special character: !@?^#,;:=/$%^&*
Examples:
- "Pass12" - Valid (Medium: 6 chars, uppercase + number)
- "password1" - Valid (Medium: 9 chars, lowercase + number)
- "PASSWORD" - Invalid (only uppercase, missing second character type)
- "Passw0rd!" - Valid (Strong: 8 chars, all requirements met)
BS-001.8: Duplicate Email Prevention
Rule: Each email address can only be associated with one user account.
Rationale: Ensure unique user identification and prevent account confusion.
Behavior:
- When a user attempts to register with an email that already exists
- The system shall display an error message
- The error message shall suggest: choosing a different email address OR using the "forgot password" link to recover the existing account
Examples:
- User A registers with "john@example.com" - succeeds
- User B attempts to register with "john@example.com" - fails with error message
- Error message: "This email is already registered. Please choose another email or click 'Forgot Password' to recover your account."
BS-001.9: JWT Token Expiration
Rule: JWT authentication tokens expire after 72 hours.
Rationale: Balance security (limiting token lifetime) with user convenience (avoiding frequent re-authentication).
Reference: Token expiration is configured in packages/back/src/shared/auth/auth.module.ts
BS-001.10: JWT Token Auto-Renewal
Rule: The system shall automatically renew JWT tokens before they expire for active users.
Rationale: Provide seamless user experience without unexpected session terminations.
Behavior:
- Active user sessions should not be interrupted due to token expiration
- Token renewal should occur transparently without user intervention
- Users who are inactive for the full token lifetime (72 hours) will need to re-authenticate
BS-001.11: Profile Completion Modal Behavior
Rule: The profile completion modal is mandatory and cannot be dismissed.
Rationale: Ensure pre-registered users provide contact information to complete their account.
Behavior:
- Modal appears when conditions are met (pre-registered user with generated content)
- User must provide email and password to close the modal
- No dismiss, close, or skip option is available
Data Requirements
User Entity
| Attribute | Description | Required | Notes |
|---|---|---|---|
| id | Unique identifier | Yes | System-generated |
| state | User state | Yes | "preregistered" or "registered" |
| sourceId | Origin identifier | Yes | Instagram ID or "website-{uuid}" format. Must be globally unique across all users. |
| User email | Conditional | Required for "registered" state | |
| password | Hashed password | Conditional | Required for "registered" state |
| oneTimeToken | Magic link token | No | Temporary, deleted after use |
Future Enhancement - sourceId Optionality: The sourceId attribute is currently required but should be made optional in a future iteration. The sourceId is only meaningful during user registration to identify the acquisition channel. Once registration is complete, the sourceId serves no ongoing functional purpose and could be nullable. This change would simplify the data model for users who do not need acquisition tracking.
User Interactions
Flow 1: Website Registration
1. Visitor navigates to signup page
2. Visitor enters email and password
3. System validates password strength (BS-001.7)
4. System checks for duplicate email (BS-001.8)
5. If validation fails: display appropriate error message
6. If validation passes: System creates registered user
7. System issues JWT token
8. User is redirected to personal space (/universes)
Flow 2: Instagram Auto-Registration
1. Instagram user sends message to chatbot
2. Webhook received with sender ID
3. System validates webhook signature
4. System checks if user exists
5. If new: System creates preregistered user
6. Conversation proceeds (handled by Assistant module)
Flow 3: Login
1. User navigates to login page
2. User enters email and password
3. System validates credentials
4. System issues JWT token
5. User is redirected to personal space (/universes)
Flow 4: Magic Link Access
1. System generates magic link (triggered by book completion)
2. Link is sent to user (via Instagram)
3. User clicks link
4. System validates token
5. System issues JWT token
6. Token is invalidated
7. User is redirected to their content (universe/book)
Flow 5: Profile Completion
1. Pre-registered user accesses book page
2. System detects cover image exists but email is missing
3. After delay, mandatory profile completion modal appears
4. User cannot dismiss the modal
5. User enters email and password
6. System validates password strength (BS-001.7)
7. System checks for duplicate email (BS-001.8)
8. If validation fails: display appropriate error message
9. If validation passes: System updates user credentials
10. Modal is dismissed
11. User continues with full access
Flow 6: Password Reset
1. User navigates to login page
2. User clicks "Forgot Password" link
3. User enters their email address
4. System sends magic link to email (if email exists)
5. System displays confirmation (without revealing if email exists)
6. User clicks magic link in email
7. Password reset modal is displayed
8. User enters new password
9. System validates password strength (BS-001.7)
10. If validation fails: display error message
11. If validation passes: System updates password
12. System issues JWT token
13. User is redirected to personal space
Edge Cases & Error Scenarios
EC-001.1: Duplicate Instagram Registration
- Scenario: Same Instagram user sends multiple messages
- Expected: No duplicate user created; existing user is used
EC-001.2: Invalid Magic Link
- Scenario: User clicks expired or already-used magic link
- Expected: Error displayed; no authentication granted
EC-001.3: Registration with Existing Email
- Scenario: User attempts to register with an email already in use
- Expected: Error displayed: "This email is already registered. Please choose another email or click 'Forgot Password' to recover your account."
EC-001.4: Invalid Webhook Signature
- Scenario: Instagram webhook with invalid signature
- Expected: Request rejected; no user created
EC-001.5: Weak Password Submission
- Scenario: User submits a password that does not meet strength requirements
- Expected: Error displayed with password requirements; form remains for correction
EC-001.6: Session Expiry for Inactive User
- Scenario: User's JWT token expires after 72 hours of inactivity
- Expected: User is prompted to log in again on next request
EC-001.7: Token Auto-Renewal
- Scenario: Active user's token approaches expiration
- Expected: Token is automatically renewed; user session continues uninterrupted
EC-001.8: Password Reset for Non-Existent Email
- Scenario: User requests password reset for an email not in the system
- Expected: Same confirmation message displayed (no email sent); prevents email enumeration
EC-001.9: Profile Completion with Existing Email
- Scenario: Pre-registered user tries to complete profile with an email already in use
- Expected: Error displayed with options to choose different email or use "forgot password"
EC-001.10: Malformed or Non-User Webhook Payload
- Scenario: Instagram webhook passes signature validation but payload structure cannot yield a sender ID (empty entry array, empty messaging array, or missing sender object)
- Expected: Webhook request is acknowledged successfully (no error thrown); user creation step is skipped; webhook processing continues for any other applicable handlers
- Rationale: Instagram sends various webhook event types that may not contain user message data. These should be acknowledged to prevent retries while gracefully skipping user creation logic.
Dependencies
- External: Instagram Graph API (for webhook verification)
- External: Stripe (for payment-triggered email updates) - See FS-XXX Checkout Specification
- Internal: Mail Service (for magic link delivery and password reset emails)
- Internal: Publisher Module (triggers magic link creation on book completion)
- Shared: Password validation module (
packages/shared/src/acceptors/password/condition.ts)
Future Enhancements (Out of Scope)
The following features have been identified but are not included in this specification:
- Email Verification: Verifying user email addresses upon registration
- Pre-registered User Display: How to identify pre-registered users in the UI
- Optional sourceId: Make sourceId nullable since it is only meaningful during registration to identify the acquisition channel. Once registration is complete, the sourceId serves no ongoing functional purpose.
Self-Verification Checklist
- No technology-specific terms used (removed NestJS, JWT library references)
- All requirements have FS identifiers
- All business rules have BS identifiers
- Acceptance criteria are testable
- Edge cases are documented
- Dependencies are identified
- No duplication with existing specs
- File naming follows convention
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | 2026-01-08 | PM Agent | Initial draft from existing SPEC001.md and codebase analysis |
| 1.0 | 2026-01-08 | PM Agent | Incorporated clarification answers: password requirements (BS-001.7), duplicate email handling (BS-001.8), JWT expiry and auto-renewal (BS-001.9, BS-001.10), mandatory profile modal (BS-001.11), password reset flow (FS-001.8) |
| 1.1 | 2026-01-12 | PM Agent | Added EC-001.10: Malformed or Non-User Webhook Payload edge case |
| 1.2 | 2026-01-16 | PM Agent | Updated BS-001.1: sourceId for website users now uses "website-{uuid}" format instead of "website". Each sourceId must be globally unique across all users. Added future enhancement note about making sourceId optional. Updated FS-001.1 acceptance criteria and test scenarios. Updated User Entity data requirements. |