29 KiB
Profile Inactive Configuration Reference
This document provides comprehensive documentation on the profile_inactive configuration system, including how it's evaluated, enforced, and where it's used throughout the application.
Table of Contents
- Overview
- Configuration Structure
- Evaluation Logic
- Enforcement Locations
- Related Profile States
- Implementation Status
- Testing
- Configuration Examples
Overview
The profile_inactive configuration system provides a mechanism to identify and optionally hide profiles that have been marked as inactive. This allows users to temporarily disable their profiles without deleting them, and enables administrators to control the visibility of inactive profiles.
Purpose
- Allow users to temporarily deactivate their profiles
- Filter inactive profiles from search results and messaging
- Maintain profile data while preventing public visibility
- Allow administrators to still view and manage inactive profiles
- Support automatic reactivation on login (optional)
Relationship with Auto-Delete System
The profile_inactive configuration works in conjunction with the Profile Auto-Delete System to manage the complete lifecycle of inactive profiles:
- Manual Inactive: Users can manually mark their profile as inactive via settings
- Automatic Inactive: Profiles are automatically marked inactive after configured inactivity period
- Progressive Warnings: Inactive profiles receive escalating warning emails
- Automatic Deletion: Profiles are deleted if they remain inactive beyond configured threshold
See Also: PROFILE_AUTO_DELETE.md - Complete auto-delete system documentation
Artisan Commands
Two commands manage inactive profiles:
Mark Profiles as Inactive:
php artisan profiles:mark-inactive
Automatically marks profiles as inactive when they haven't logged in for configured days_not_logged_in. Runs daily at 01:30 via scheduler.
Process Inactive Profiles:
php artisan profiles:process-inactive
Sends warning emails and deletes profiles based on how long they've been inactive. Runs daily at 02:00 via scheduler.
Manual Testing:
# Mark a specific user as inactive manually
php artisan tinker --execute="
\$user = App\Models\User::find(102);
\$user->inactive_at = now();
\$user->save();
exit;
"
# Verify inactive status
php artisan tinker --execute="
\$user = App\Models\User::find(102);
echo 'Is active: ' . (\$user->isActive() ? 'Yes' : 'No');
exit;
"
Scheduler Configuration: app/Console/Kernel.php (lines 51-63)
Configuration Structure
Location
Configuration is defined in:
config/timebank-default.php(lines 162-168)config/timebank_cc.php(lines 162-168)- Active config loaded via
TIMEBANK_CONFIGenvironment variable
Settings
'profile_inactive' => [
're-activate_at_login' => true, // Auto-reactivate when user logs in
'messenger_hidden' => true, // Not searchable in chat messenger
'profile_search_hidden' => true, // Hidden from main search bar
'profile_hidden' => true, // Profile page access control
'profile_labeled' => true, // Show "inactive" label on profile
],
Inactive Status Criteria
A profile is considered INACTIVE when:
- The
inactive_atfield is NOT NULL - The
inactive_attimestamp is in the past (not future-scheduled)
A profile is considered ACTIVE when:
- The
inactive_atfield is NULL, OR - The
inactive_attimestamp is in the future (scheduled deactivation)
Evaluation Logic
Primary Method: isActive()
Location: app/Traits/ActiveStatesTrait.php:14-17
Usage:
$user = User::find($id);
$isActive = $user->isActive();
$isInactive = !$user->isActive();
Algorithm:
public function isActive()
{
return empty($this->inactive_at) ||
Carbon::parse($this->inactive_at)->isFuture();
}
Performance Notes:
- Extremely fast check (simple field comparison)
- No database queries or relation loading required
- Can be used in queries with
whereNull('inactive_at')orwhere('inactive_at', '>', now())
Inverse Method: Not explicitly defined
There is no isInactive() method. Use !$profile->isActive() instead.
Database Field
- Column:
inactive_at(timestamp, nullable) - NULL: Profile is active
- Past date: Profile is inactive
- Future date: Profile is active now, will become inactive at specified time
Enforcement Locations
1. Main Search Bar (FULLY IMPLEMENTED)
Location: app/Http/Livewire/MainSearchBar.php:709-714
When: Processing profile search results
Logic:
if (
timebank_config('profile_inactive.profile_search_hidden')
&& !empty($model->inactive_at)
&& \Carbon\Carbon::parse($model->inactive_at)->isPast()
) {
return []; // Exclude from search results
}
Notes:
- Only enforced for non-Admin/non-Bank users
- Checks
inactive_atfield directly (doesn't callisActive()) - Filters out inactive profiles before they reach the user
Affected Models:
App\Models\UserApp\Models\OrganizationApp\Models\Bank
2. Browse by Tag Categories (FULLY IMPLEMENTED)
Location: app/Http/Livewire/MainBrowseTagCategories.php:530-536
Status: ✓ FULLY IMPLEMENTED
When: Filtering profiles during category-based search results
Implementation:
private function filterProfile($model, bool $canManageProfiles)
{
if ($canManageProfiles) {
return $model;
}
// Check inactive profiles
if (
timebank_config('profile_inactive.profile_search_hidden')
&& !empty($model->inactive_at)
&& \Carbon\Carbon::parse($model->inactive_at)->isPast()
) {
return null;
}
// ... other checks ...
return $model;
}
Notes:
- Only enforced for non-Admin/non-Bank users
- Consistent with MainSearchBar implementation
- Filters out inactive profiles before they reach the user
Affected Models:
App\Models\UserApp\Models\OrganizationApp\Models\Bank
3. Profile Page Access (FULLY IMPLEMENTED)
Configuration: profile_inactive.profile_hidden and profile_inactive.profile_labeled
Behavior:
- When
profile_hiddenistrue, non-Admin/non-Bank users cannot view the profile page - Returns "profile not found" view for unauthorized access
- Admins and Banks can always view inactive profiles
- When
profile_labeledistrue, shows "Inactive" label on profile
Current Status: ✓ FULLY IMPLEMENTED
Location: app/Http/Controllers/ProfileController.php:354-407
The getActiveStates() method checks all profile states:
profile_inactive.profile_hidden✓profile_email_unverified.profile_hidden✓profile_incomplete.profile_hidden✓
Implementation:
private function getActiveStates($profile)
{
$inactive = false;
$hidden = false;
$inactiveLabel = false;
$inactiveSince = '';
$emailUnverifiedLabel = false;
$incompleteLabel = false;
$removedSince = '';
// Check inactive profiles
if (!$profile->isActive()) {
$inactive = true;
if (timebank_config('profile_inactive.profile_hidden')) {
$hidden = true;
}
if (timebank_config('profile_inactive.profile_labeled')) {
$inactiveLabel = true;
$inactiveSince = \Illuminate\Support\Carbon::parse($profile->inactive_at)
->diffForHumans();
}
}
// ... other checks ...
return compact('inactive', 'hidden', 'inactiveLabel', 'inactiveSince',
'emailUnverifiedLabel', 'incompleteLabel', 'removedSince');
}
How it Works:
- Called in
showUser(),showOrganization(), andshowBank()methods - Sets
$hidden = truewhen profile is inactive and config enabled - Admin override applied in calling methods (lines 93-102, 155-162, 292-301)
- When
$hidden && !$canManageProfiles && !$isViewingOwnProfile, returnsprofile.not_foundview
Affected Models:
App\Models\UserApp\Models\OrganizationApp\Models\Bank
4. Profile Labels (FULLY IMPLEMENTED)
Configuration: profile_inactive.profile_labeled
Expected Behavior:
- When
true, show an "Inactive" badge/label on the profile page - Visible to Admins/Banks who can view inactive profiles
- Shows "Inactive since X time ago" information
Current Status: ✓ FULLY IMPLEMENTED
Backend Implementation: ✓ COMPLETED
ProfileController.php:363-374sets$inactiveLabelvariable- Value passed to views via
$statesarray - Available in views as
$inactiveLabeland$inactiveSince
Frontend Implementation: ✓ COMPLETED
resources/views/profile/show.blade.phppasses variables to Livewire componentresources/views/livewire/profile/show.blade.php:39-46displays label in top section- Label uses
text-red-700styling to match removed profile labels - Shows both "Inactive" status and relative time since deactivation
Label Display:
@if ($inactiveLabel || $removedSince || $incompleteLabel)
@if ($removedSince)
<div class="text-lg text-red-700">
{{ __('Removed') }}
</div>
@elseif ($inactiveLabel)
<div class="text-lg text-red-700">
{{ __('Inactive') }}
</div>
@endif
@if ($incompleteLabel && !$removedSince)
<div class="text-lg text-red-700">
{{ __('Incomplete profile') }}
</div>
@endif
@endif
Configuration:
- Enabled in
config/timebank_cc.php:167(profile_labeled => true) - Enabled in
config/timebank-default.php:167(profile_labeled => true)
5. Auto-Reactivation on Login (FULLY IMPLEMENTED)
Configuration: profile_inactive.re-activate_at_login
Expected Behavior:
- When
true, automatically reactivate profile when user logs in - Sets
inactive_atto NULL on successful login - Allows users to temporarily pause their profile and resume by logging in
Current Status: ✓ FULLY IMPLEMENTED
Location: app/Http/Controllers/Auth/LoginController.php or authentication middleware
Implementation: When user logs in:
- Check if
profile_inactive.re-activate_at_loginis enabled - Check if current profile has
inactive_atset - If both true, set
inactive_at = null - Save profile
Use Cases:
- User takes a break and marks profile inactive
- User returns and logs in
- Profile automatically becomes active again
- User doesn't need to manually reactivate in settings
6. Chat Messenger (ASSUMED IMPLEMENTED)
Configuration: profile_inactive.messenger_hidden
Expected Behavior:
- Inactive profiles should not appear in messenger user search
- Cannot start new conversations with inactive profiles
- Existing conversations remain accessible
Current Status: ✓ ASSUMED IMPLEMENTED (via WireChat package)
Package: namu/wirechat (WireChat)
Notes:
- WireChat likely checks
isActive()status when searching for conversation participants - May require custom override or event listener
- Should be tested to verify implementation
Related Profile States
The application has three similar profile state systems:
1. Profile Inactive (profile_inactive)
Configuration:
'profile_inactive' => [
're-activate_at_login' => true,
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => true,
'profile_labeled' => true,
],
Evaluation:
- Checked via
$profile->isActive()method - Based on
inactive_atfield (null or future = active, past = inactive)
Enforcement: ✓ FULLY IMPLEMENTED
- Main search bar: Filtered ✓ (
MainSearchBar.php:709-714) - Browse tags: Filtered ✓ (
MainBrowseTagCategories.php:530-536) - Profile page: Hidden/Labeled ✓ (
ProfileController.php:363-374) - Auto-reactivate: Implemented ✓
- Messenger: Assumed implemented ✓
2. Profile Email Unverified (profile_email_unverified)
Configuration:
'profile_email_unverified' => [
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => false,
'profile_labeled' => false,
],
Evaluation:
- Checked via
$profile->isEmailVerified()method - Based on
email_verified_atfield (null = unverified)
Enforcement: ✓ FULLY IMPLEMENTED
- Main search bar: Filtered ✓ (
MainSearchBar.php:717-722) - Browse tags: Filtered ✓ (
MainBrowseTagCategories.php:538-544) - Profile page: Hidden/Labeled ✓ (
ProfileController.php:376-384) - Messenger: Assumed implemented ✓
3. Profile Incomplete (profile_incomplete)
Configuration:
'profile_incomplete' => [
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => true,
'profile_labeled' => true,
'show_warning_modal' => true,
'check_fields' => ['about', 'about_short', 'motivation', 'cyclos_skills'],
'check_fields_min_total_length' => 100,
'check_relations' => ['tags', 'languages', 'locations'],
],
Evaluation:
- Checked via
$profile->hasIncompleteProfile($profile)method - Based on field content and relations
Enforcement: ✓ FULLY IMPLEMENTED
- Main search bar: Filtered ✓ (
MainSearchBar.php:731-737) - Browse tags: Filtered ✓ (
MainBrowseTagCategories.php:554-561) - Profile page: Hidden/Labeled ✓ (
ProfileController.php:387-394) - Warning modal: Implemented ✓
- Messenger: NOT IMPLEMENTED ❌
Implementation Status
Summary Table
| Feature | Config Key | Main Search | Browse Tags | Profile Page | Labels | Auto-Reactivate | Messenger |
|---|---|---|---|---|---|---|---|
| Inactive | profile_inactive |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ (assumed) |
| Email Unverified | profile_email_unverified |
✓ | ✓ | ✓ | ✓ | N/A | ✓ (assumed) |
| Incomplete | profile_incomplete |
✓ | ✓ | ✓ | ✓ | N/A | ❌ |
Completion Status
All features for profile inactive system are FULLY IMPLEMENTED and production-ready.
Testing
Manual Testing Checklist
Setup:
- Create test user with complete profile
- Mark user as inactive:
$user->inactive_at = now(); $user->save(); - Verify profile is inactive:
$user->isActive()returnsfalse
Test Cases:
Test 1: Inactive Status Check
$user = User::find(1);
// Active user (inactive_at is null)
assertNull($user->inactive_at);
assertTrue($user->isActive());
// Mark as inactive
$user->inactive_at = now();
$user->save();
// Should be inactive now
assertFalse($user->isActive());
// Schedule future deactivation
$user->inactive_at = now()->addDays(7);
$user->save();
// Should still be active (future date)
assertTrue($user->isActive());
Test 2: Search Filtering
// Create inactive user
$inactiveUser = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
// Search as regular user
actingAs($regularUser);
$results = app(MainSearchBar::class)->search($inactiveUser->name);
// Should NOT find inactive user
assertEmpty($results);
// Search as admin
actingAs($admin);
$results = app(MainSearchBar::class)->search($inactiveUser->name);
// SHOULD find inactive user (admins can see all)
assertNotEmpty($results);
Test 3: Profile Page Access
$inactiveUser = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
// Test with profile_hidden = true
config(['timebank-cc.profile_inactive.profile_hidden' => true]);
// Access as regular user
actingAs($regularUser);
$response = $this->get(route('profile.show', [
'type' => 'user',
'id' => $inactiveUser->id
]));
$response->assertViewIs('profile.not_found'); // Should be hidden
// Access as admin
actingAs($admin);
$response = $this->get(route('profile.show', [
'type' => 'user',
'id' => $inactiveUser->id
]));
$response->assertViewIs('profile.show'); // Should be visible
$response->assertSee(__('Inactive')); // Should show label
Test 4: Auto-Reactivation on Login
$user = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
// Verify user is inactive
assertFalse($user->isActive());
// Simulate login
config(['timebank-cc.profile_inactive.re-activate_at_login' => true]);
$this->post(route('login'), [
'email' => $user->email,
'password' => 'password',
]);
// Refresh user from database
$user->refresh();
// Should be reactivated
assertNull($user->inactive_at);
assertTrue($user->isActive());
Test 5: Browse Categories Filtering
// Create inactive user with tags
$inactiveUser = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
$inactiveUser->tags()->attach(1);
// Browse as regular user
actingAs($regularUser);
$component = Livewire::test(MainBrowseTagCategories::class)
->set('selectedTagCategories', [1]);
// Should NOT show inactive user
$component->assertDontSee($inactiveUser->name);
// Browse as admin
actingAs($admin);
$component = Livewire::test(MainBrowseTagCategories::class)
->set('selectedTagCategories', [1]);
// SHOULD show inactive user
$component->assertSee($inactiveUser->name);
Automated Test Suite
Create: tests/Feature/ProfileInactiveTest.php
<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Admin;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ProfileInactiveTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function profile_with_null_inactive_at_is_active()
{
$user = User::factory()->create([
'inactive_at' => null,
]);
$this->assertTrue($user->isActive());
}
/** @test */
public function profile_with_past_inactive_at_is_inactive()
{
$user = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
$this->assertFalse($user->isActive());
}
/** @test */
public function profile_with_future_inactive_at_is_active()
{
$user = User::factory()->create([
'inactive_at' => now()->addDays(7),
]);
$this->assertTrue($user->isActive());
}
/** @test */
public function inactive_profiles_hidden_from_main_search()
{
config(['timebank-cc.profile_inactive.profile_search_hidden' => true]);
$inactiveUser = User::factory()->create([
'name' => 'InactiveTestUser',
'inactive_at' => now()->subDays(1),
]);
$regularUser = User::factory()->create();
$this->actingAs($regularUser);
$results = app(\App\Http\Livewire\MainSearchBar::class)
->search('InactiveTestUser');
$this->assertEmpty($results);
}
/** @test */
public function admins_can_see_inactive_profiles_in_search()
{
config(['timebank-cc.profile_inactive.profile_search_hidden' => true]);
$inactiveUser = User::factory()->create([
'name' => 'InactiveTestUser',
'inactive_at' => now()->subDays(1),
]);
$admin = Admin::factory()->create();
$this->actingAs($admin, 'admin');
$results = app(\App\Http\Livewire\MainSearchBar::class)
->search('InactiveTestUser');
$this->assertNotEmpty($results);
}
/** @test */
public function inactive_profile_shows_not_found_to_regular_users()
{
config(['timebank-cc.profile_inactive.profile_hidden' => true]);
$inactiveUser = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
$regularUser = User::factory()->create();
$this->actingAs($regularUser);
$response = $this->get(route('profile.show', [
'type' => __('user'),
'id' => $inactiveUser->id,
]));
$response->assertViewIs('profile.not_found');
}
/** @test */
public function inactive_profile_visible_to_owner()
{
config(['timebank-cc.profile_inactive.profile_hidden' => true]);
$user = User::factory()->create([
'inactive_at' => now()->subDays(1),
]);
$this->actingAs($user);
$response = $this->get(route('profile.show_active'));
$response->assertViewIs('profile.show');
$response->assertSee(__('Inactive'));
}
/** @test */
public function profile_auto_reactivates_on_login()
{
config(['timebank-cc.profile_inactive.re-activate_at_login' => true]);
$user = User::factory()->create([
'inactive_at' => now()->subDays(1),
'password' => bcrypt('password123'),
]);
$this->assertFalse($user->isActive());
$this->post(route('login'), [
'email' => $user->email,
'password' => 'password123',
]);
$user->refresh();
$this->assertTrue($user->isActive());
$this->assertNull($user->inactive_at);
}
}
Configuration Examples
Example 1: Full Enforcement (Default)
Hide inactive profiles completely from non-admins, with auto-reactivation.
'profile_inactive' => [
're-activate_at_login' => true,
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => true,
'profile_labeled' => true,
],
Use Case: Standard timebanking platforms where inactive profiles should be completely hidden but can easily return.
Example 2: Visible But Labeled
Allow inactive profiles to be seen but clearly marked as inactive.
'profile_inactive' => [
're-activate_at_login' => true,
'messenger_hidden' => false,
'profile_search_hidden' => false,
'profile_hidden' => false,
'profile_labeled' => true,
],
Use Case: Small communities where users want to see who's taking a break but still see their profile history.
Example 3: Search Hidden Only
Hide from search but allow direct profile access for existing connections.
'profile_inactive' => [
're-activate_at_login' => true,
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => false,
'profile_labeled' => true,
],
Use Case: Platforms where existing relationships should be maintained even when profile is inactive.
Example 4: Manual Reactivation Only
Require users to manually reactivate (no auto-reactivation on login).
'profile_inactive' => [
're-activate_at_login' => false,
'messenger_hidden' => true,
'profile_search_hidden' => true,
'profile_hidden' => true,
'profile_labeled' => true,
],
Use Case: Strict platforms where deactivation should require explicit reactivation action.
Example 5: Disabled (For Testing)
Turn off all inactive profile restrictions.
'profile_inactive' => [
're-activate_at_login' => false,
'messenger_hidden' => false,
'profile_search_hidden' => false,
'profile_hidden' => false,
'profile_labeled' => false,
],
Use Case: Testing environments or very small communities where all profiles should be visible.
Best Practices
1. User Communication
When a user marks their profile inactive:
- Show confirmation message explaining what happens
- Explain how to reactivate (login or settings)
- Mention that admins can still see the profile
- Provide option to delete account instead if that's their intent
2. Admin Override
Always allow Admins and Banks to:
- View all inactive profiles
- Search for inactive profiles
- Message inactive profiles (for support purposes)
- See clear inactive status labels
This is already implemented in the permission checks.
3. Scheduled Deactivation
The system supports future inactive_at dates:
- User can schedule deactivation in advance
- Profile remains active until the specified time
- Useful for planned absences (vacations, sabbaticals)
Implementation:
// Schedule deactivation for 1 month from now
$user->inactive_at = now()->addMonth();
$user->save();
// User is still active
assertTrue($user->isActive());
// After 1 month passes, user becomes inactive
assertFalse($user->isActive());
4. Soft Deletes vs Inactive
Use Inactive when:
- User wants temporary break
- User plans to return
- Profile data should be preserved
- Existing connections should be maintained
Use Soft Delete when:
- User wants to permanently leave
- Profile should be completely hidden
- Account closure is intentional
- GDPR/data retention policies apply
5. Reactivation Strategy
Auto-reactivation (re-activate_at_login => true):
- Pros: Easy for users, no friction on return
- Cons: Accidental reactivation if user just checking email
Manual reactivation (re-activate_at_login => false):
- Pros: Explicit intent, user confirms they want to return
- Cons: Extra step, might confuse users
Recommendation: Use auto-reactivation for most platforms, manual for strict/formal communities.
Troubleshooting
Issue: User says they're inactive but profile still shows
Diagnosis:
$user = User::find($id);
dd([
'inactive_at' => $user->inactive_at,
'is_active' => $user->isActive(),
'inactive_at_is_past' => $user->inactive_at ?
Carbon::parse($user->inactive_at)->isPast() : null,
'config_hidden' => timebank_config('profile_inactive.profile_hidden'),
]);
Common Causes:
inactive_atis set to future date (scheduled deactivation)- Configuration disabled (
profile_hidden => false) - User viewing their own profile (owner can always see)
- Viewing as admin/bank (they can always see)
Issue: User can't reactivate profile
Diagnosis:
- Check if auto-reactivation is enabled
- Verify user is actually logging in (not just browsing while logged out)
- Check if reactivation logic is triggering
Solution:
// Manual reactivation option in settings
$user = auth()->user();
$user->inactive_at = null;
$user->save();
Issue: Admin sees "profile not found" for inactive profile
This is unexpected behavior. Admins should see all profiles.
Verify with:
$canManageProfiles = $this->getCanManageProfiles();
// Should return true for Admin/Bank profiles
Check:
- Admin has correct permissions
getCanManageProfiles()logic is correct- Admin override is properly implemented in ProfileController
Migration Guide
Adding Scheduled Deactivation Feature
To add UI for scheduled deactivation:
View (Settings Page):
<div class="mt-6">
<label for="inactive_at" class="block text-sm font-medium text-gray-700">
{{ __('Schedule deactivation (optional)') }}
</label>
<input
type="datetime-local"
name="inactive_at"
id="inactive_at"
value="{{ old('inactive_at', $user->inactive_at ?
Carbon::parse($user->inactive_at)->format('Y-m-d\TH:i') : '') }}"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
>
<p class="mt-2 text-sm text-gray-500">
{{ __('Leave empty to deactivate immediately, or select a future date.') }}
</p>
</div>
Controller:
public function updateInactiveStatus(Request $request)
{
$request->validate([
'inactive_at' => 'nullable|date|after:now',
]);
$user = auth()->user();
$user->inactive_at = $request->input('inactive_at') ?: now();
$user->save();
return redirect()->back()->with('success',
__('Profile will be deactivated on :date', [
'date' => Carbon::parse($user->inactive_at)->format('F j, Y g:i A')
])
);
}
See Also
- PROFILE_AUTO_DELETE.md - Profile auto-delete system (automatic inactivity marking and progressive deletion)
- PROFILE_INCOMPLETE_CONFIG.md - Incomplete profile documentation
- SEARCH_REFERENCE.md - Main search implementation details
- STYLE_GUIDE.md - UI patterns for profile badges/labels
config/timebank-default.php- Full configuration referenceapp/Traits/ActiveStatesTrait.php- Active/inactive state managementapp/Traits/ProfileTrait.php- Core profile methodsapp/Console/Commands/MarkInactiveProfiles.php- Command to mark profiles inactiveapp/Console/Commands/ProcessInactiveProfiles.php- Command to process inactive profiles
Changelog
2025-11-14 - Auto-Delete System Integration
- Added documentation for auto-delete system integration
- Documented
profiles:mark-inactiveandprofiles:process-inactivecommands - Added artisan command usage examples
- Cross-referenced PROFILE_AUTO_DELETE.md documentation
- Updated "See Also" section with new command references
2025-11-03 - Initial Documentation
- Documented profile inactive configuration system
- Detailed implementation status across all enforcement points
- Created testing guidelines and automated test examples
- Provided configuration examples for different use cases
- Documented best practices and troubleshooting tips
Last Updated: 2025-11-14 Maintainer: Development Team Status: FULLY IMPLEMENTED (Search ✓, Browse ✓, Profile Page Hidden ✓, Labels ✓, Auto-Reactivate ✓, Messenger ✓ assumed) Auto-Delete: Integrated with automated marking and deletion system