FEAT-IDEN-003: Teacher-Initiated Reset Code Generation
[NEW - Compliant with DOM-IDEN Authority]
| Reference Number | Version | Effective Date | Supersedes | Authority Level | Status |
|---|---|---|---|---|---|
| FEAT-IDEN-003 | 1.1 | 2026-09-15 | 1.0 | Normative | ACTIVE |
I. Purpose
This FEAT is the first step of the student account recovery workflow. A teacher initiates recovery for a student who has lost access to their account, generating a short-lived reset code that the student will use to regain access.
Per DOM-IDEN-002 §IX (Student Account Recovery) Step 1:
“A teacher with an active administrative seat in the student’s class initiates a recovery reset for a claimed student seat… Generates a new 8-character random alphanumeric reset code; Sets
reset_code_generated_at = now; Setsreset_code_expires_at = reset_code_generated_at + 10 minutes”
This FEAT implements Step 1 of the recovery flow.
Governing Authority:
- DOM-IDEN-002 §IX (Student Account Recovery)
- DOM-IDEN-005 §IX (Identity Recovery)
- FEAT-CORE-000 (Feature Execution Constitutional Directive)
II. Execution Context
1. Required Inputs
seat_id: The claimed student seat (identifying the account to recover).teacher_user_id: The authenticated teacher initiating the recovery (from request context).idempotency_key: Client-provided unique request ID.
2. Resolved Context (MANDATORY)
Before mutation, the FEAT MUST resolve:
student_seat: TheSeatrecord matchingseat_id.student_user: TheUserrecord bound tostudent_seat.user_id.class_id: Fromstudent_seat.class_id.teacher_authorization: Verify the authenticated teacher has an administrative seat in the same class.
III. Orchestration Logic
A. Verification Phase (Read-Only)
Step 1: Validate Student Seat
- Query
Seatwhereid = seat_id. - Verify
Seat.claimed_at IS NOT NULL(seat must be claimed). - Verify
Seat.user_id IS NOT NULL(seat must be bound to a user). - Verify
Seat.role = 'student'(seat must be a student seat, not admin). - Extract
user_idandclass_idfrom the seat. - Failure Behavior: Abort with
STUDENT_SEAT_NOT_FOUNDorINVALID_SEAT_STATE.
Step 2: Validate Student User
- Query
Userwhereid = student_user_id. - Verify
User.user_role = 'student'. - Failure Behavior: Abort with
STUDENT_USER_NOT_FOUND.
Step 3: Validate Teacher Authorization
Per DOM-IDEN-005 §IX:
“Recovery MAY… restore credentials… Recovery SHALL NOT… create Users… Recovery never reconstructs identity.”
The teacher initiating recovery MUST have administrative authority in the class:
- Query administrative
Seatwhere:user_id = teacher_user_idclass_id = student_seat.class_idrole = 'admin'
- If no matching seat found: Abort with
UNAUTHORIZED(403). - Failure Behavior: Return 403 Forbidden.
Step 4: Check Single Active Code Invariant
Per DOM-IDEN-002 §IX:
“Single active code: Only one active reset code per student identity at any time.”
- Check if
student_user.reset_codealready exists. - If yes: Log that the existing code will be overwritten.
- This is not a failure; new code overwrites old (per spec).
B. Mutation Phase (Atomic Transaction)
Step 1: Generate Reset Code
- Generate a random 8-character alphanumeric reset code.
- Characters: A-Z, 0-9 (no lowercase, no special chars)
- Example: “A7F2K9M1”
- Verify the code is not trivially weak:
- ❌ NOT all the same character (e.g., “AAAAAAAA”)
- ❌ NOT sequential (e.g., “ABCDEFGH”)
- Single Active Code Invariant: If a code already exists, it will be overwritten (no extra check needed).
Step 2: Write Reset Code to User
Update the User record:
- Set
reset_code = generated_code(overwrites any existing code). - Set
reset_code_generated_at = NOW()(UTC). - Set
reset_code_expires_at = NOW() + 10 minutes. - Clear
recovery_setup_nonce_hashandrecovery_setup_expires_atto invalidate any previously accepted recovery session. Lock the User row while issuing so issuance serializes with acceptance and credential completion.
Per DOM-IDEN-002 §IX:
“Reset codes are short-lived (10-minute TTL), teacher-visible, and communicated in person. Plaintext storage is acceptable for this handoff artifact.”
Note: Reset codes are stored in plaintext because they are:
- Short-lived (10 min)
- Teacher-visible only
- Communicated verbally to student
- Not a permanent credential
Step 3: Emit Audit Trace
Per FEAT-CORE-000 §III.4:
- Call
DOM-OPSto emitACT-IDEN-003audit event. - Required fields:
feat_id: “FEAT-IDEN-003”user_id:student_user_idseat_id:student_seat_idclass_id: The class contextinitiator_user_id: The teacher’s user_ididempotency_key: The provided keyoutcome:"RESET_CODE_GENERATED"(only possible outcome)timestamp: ISO 8601 UTC timestamp
Security Note: DO NOT log the reset code itself (even though it’s not hashed). Log only that a code was generated.
IV. Invariants & Constraints
1. Single Active Code (MANDATORY)
Per DOM-IDEN-002 §IX:
“Only one active reset code per student identity at any time. New code generation will overwrite the existing code.”
- If a code already exists, it is silently overwritten (no error).
- Only one valid code can be active per user.
2. 10-Minute TTL (MANDATORY)
Per DOM-IDEN-002 §IX:
“Hard TTL: 10 minutes.”
reset_code_expires_at = reset_code_generated_at + 10 minutes (exactly).- No sliding window, no renewal on activity.
- Code is invalid after 10 minutes.
3. Teacher Initiation Only (MANDATORY)
Per DOM-IDEN-002 §IX:
“Teacher-initiated. Students cannot self-initiate recovery. A teacher must generate the reset code.”
- Only teachers with administrative seat in the class can initiate.
- Students cannot request code generation directly.
- No self-service recovery code path.
4. No Credential Modification (MANDATORY)
Per DOM-IDEN-005 §IX:
“Recovery restores authentication capability without altering participation…”
This FEAT:
- ✓ Sets reset code (for authorization)
- ❌ Does NOT modify username, PIN, or passphrase (done in FEAT-IDEN-004/FEAT-IDEN-002)
- ❌ Does NOT modify seat bindings
- ❌ Does NOT modify economic records
5. Idempotency (MANDATORY)
- Idempotency key + student_user_id ensures replay safety.
- Retrying the same teacher recovery for the same student returns success.
- Audit log uses key to detect duplicate events.
V. Failure Scenarios
When the FEAT fails, the system SHALL:
- Rollback all mutations (if any).
- Emit audit event with outcome
FAILEDand error code. - Return error response to teacher.
- NOT display the reset code (if code generation failed).
Failure Cases:
| Scenario | Error Code | HTTP Status | Teacher Message |
|---|---|---|---|
| Student seat not found | STUDENT_SEAT_NOT_FOUND |
404 | “Student seat not found. Check the student ID.” |
| Seat not claimed | INVALID_SEAT_STATE |
409 | “This student has not completed account setup yet.” |
| Seat not bound to user | INVALID_SEAT_STATE |
409 | “Student seat has no linked user account.” |
| Student user not found | STUDENT_USER_NOT_FOUND |
404 | “Student account not found.” |
| Teacher not in class | UNAUTHORIZED |
403 | “You do not have permission to recover accounts in this class.” |
| Database error | INTERNAL_ERROR |
500 | “An error occurred. Please try again.” |
VI. Audit Requirements
The DOM-OPS audit log MUST contain:
| Field | Type | Required | Rationale |
|---|---|---|---|
feat_id |
String | ✓ | Identifies FEAT (always “FEAT-IDEN-003”) |
user_id |
Integer | ✓ | The student user (not the teacher) |
seat_id |
Integer | ✓ | The student seat |
class_id |
UUID | ✓ | The classroom context |
initiator_user_id |
Integer | ✓ | The teacher who initiated recovery |
idempotency_key |
String | ✓ | Replay detection |
outcome |
Enum | ✓ | Must be: RESET_CODE_GENERATED |
timestamp |
ISO 8601 | ✓ | UTC timestamp of code generation |
reset_code |
String | ✗ | DO NOT log (security) |
error_code |
String | ⚠️ | Only if outcome is FAILED |
Outcomes (Only One Possible):
RESET_CODE_GENERATED: Reset code successfully created.
VII. Integration with Recovery Flow
FEAT-IDEN-003 is Step 1 of the student recovery workflow:
Step 1: FEAT-IDEN-003 (Teacher Initiates)
├─ Teacher action: Select student, request recovery
├─ System: Generate reset code, write to user.reset_code
├─ Expiry: NOW() + 10 minutes
└─ Output: Display code to teacher (e.g., "A7F2K9M1")
Step 2: FEAT-IDEN-004 (Student Validates Code)
├─ Student action: Receive code from teacher, enter it
├─ System: Validate code, clear old credentials
└─ Output: Redirect to credential setup
Step 3: FEAT-IDEN-002 (Credential Setup - reused)
├─ Student action: Enter new username, PIN, passphrase
├─ System: Activate credentials
└─ Output: Student can log in with new credentialsVIII. Rate Limiting
Per DOM-IDEN-002 §IX:
“Rate-limit reset code generation and submission.”
Recommended limits:
- Per teacher per student: Max 5 code generations per hour
- Per teacher per class: Max 20 code generations per hour
- Global: Max 100 code generations per hour
Exceeding limits returns 429 Too Many Requests.
IX. Teacher UX Considerations
After code generation, the system displays the code to the teacher with:
- Clear prominence (large, readable font)
- Expiry warning (“Expires in 10 minutes”)
- Action prompt (“Give this code to the student verbally”)
- Re-display option (teacher can view code again until it expires or is used)
- Confirmation (success message with timestamp)
Example message:
“Reset code generated for [Student Name]: A7F2K9M1 — Expires in 10 minutes. Give this code to the student.”
X. Dependencies
docs/FEATURE-EXECUTION/FEAT-CORE-000_FEATURE_EXECUTION_CONSTITUTIONAL_DIRECTIVE.mddocs/DOMAIN/DOM-IDEN-002_STUDENT_IDENTITY_ARCHITECTURE.mddocs/DOMAIN/DOM-IDEN-005_IDENTITY_BINDING_AND_LIFECYCLE.mddocs/DOMAIN/DOM-IDEN-006_CANONICAL_CONTEXT_RESOLUTION.md
XI. Implementation Checklist
Before code review, verify:
- Teacher authorization is checked (admin seat in same class)
- Student seat is claimed and bound to a user
- Reset code is 8 characters, alphanumeric only
- Code is not trivially weak (all same char, sequential)
- Expiry is exactly 10 minutes (not sliding, not renewable)
- Old code is overwritten (single active code invariant)
- Audit event is emitted with all required fields
- Reset code is NOT logged in audit
- Idempotency check prevents duplicate audit events
- Rate limiting is enforced
- Error messages don’t reveal whether user exists
- Tests cover success, authorization failure, and replay scenarios
XII. Amendments
Revisions to this document SHALL:
- Increment the version.
- Update the effective date.
- Maintain consistency with DOM-IDEN-002 §IX.
- Maintain consistency with FEAT-CORE-000.
- Maintain consistency with FEAT-IDEN-004.
Version 1.1 (2026-09-15): serialize issuance on User and invalidate outstanding recovery-session authority.
Last updated: 2026-09-15