Skip to content

Commit cf19793

Browse files
author
CIS Guru
committed
chore: complete Nine rebranding - remove all Aquiis/SimpleStart references
- Rename SimpleStartDbContext → NineDbContext (file + class) - Rename SimpleStartFinancialReportService → NineFinancialReportService (file + class) - Fix app data storage path to ~/.config/Nine (was ~/.config/Aquiis) - Fix GitHub URLs in ApplicationSettings.razor (xnodeoncode/nine) - Fix user upgrade message and limit display text - Update .vscode/launch.json and tasks.json (Nine paths, net10.0) - Update all shell scripts (diagnose, install, prepare-appimage-hub, bump-version, watch, copilot-review) - Update copilot-instructions.md files (root + inner 4-Nine) - Update README files (3-Nine.Shared.UI, 4-Nine, 6-Tests) - Fix test namespace (Nine.Tests) and test data - Fix ElectronHostHook/package.json name and version - Fix OrganizationService.cs double-operator bug (++ → +) - Build: passing 0 errors 0 warnings
1 parent e4b37ab commit cf19793

File tree

71 files changed

+675
-1195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+675
-1195
lines changed

.github/copilot-instructions.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Aquiis Property Management System - AI Agent Instructions
1+
# Nine Property Management System - AI Agent Instructions
22

33
## Development Workflow
44

@@ -42,15 +42,15 @@ feature/Phase-X-Feature-Name
4242

4343
```bash
4444
# Ensure build succeeds with 0 errors
45-
dotnet build Aquiis.sln
45+
dotnet build Nine.sln
4646

4747
# Switch to development and merge
4848
git checkout development
4949
git pull origin development
5050
git merge feature/Phase-X-Feature-Name
5151

5252
# Test the merged code in development
53-
dotnet build Aquiis.sln
53+
dotnet build Nine.sln
5454
dotnet test
5555
```
5656

@@ -73,7 +73,7 @@ feature/Phase-X-Feature-Name
7373
git pull origin main
7474

7575
# Test locally to verify
76-
dotnet build Aquiis.sln
76+
dotnet build Nine.sln
7777
dotnet test
7878
```
7979

@@ -87,7 +87,7 @@ feature/Phase-X-Feature-Name
8787

8888
## Project Overview
8989

90-
Aquiis is a multi-tenant property management system built with **ASP.NET Core 9.0 + Blazor Server**. It manages properties, tenants, leases, invoices, payments, documents, inspections, and maintenance requests with role-based access control.
90+
Nine is a multi-tenant property management system built with **ASP.NET Core 9.0 + Blazor Server**. It manages properties, tenants, leases, invoices, payments, documents, inspections, and maintenance requests with role-based access control.
9191

9292
## Architecture Fundamentals
9393

@@ -100,20 +100,20 @@ Aquiis is a multi-tenant property management system built with **ASP.NET Core 9.
100100

101101
### Service Layer Architecture
102102

103-
Aquiis uses a **layered service architecture** with entity-specific services inheriting from a base service:
103+
Nine uses a **layered service architecture** with entity-specific services inheriting from a base service:
104104

105105
**Service Hierarchy:**
106106

107107
```
108-
BaseService<TEntity> (2-Aquiis.Application/Services/BaseService.cs)
108+
BaseService<TEntity> (2-Nine.Application/Services/BaseService.cs)
109109
├─ LeaseService (Entity-specific CRUD + business logic)
110110
├─ PropertyService
111111
├─ TenantService
112112
├─ InvoiceService
113113
├─ MaintenanceService
114114
└─ [Entity]Service
115115
116-
Workflow Services (2-Aquiis.Application/Services/Workflows/)
116+
Workflow Services (2-Nine.Application/Services/Workflows/)
117117
├─ LeaseWorkflowService (Complex lease lifecycle management)
118118
├─ ApplicationWorkflowService (Rental application processing)
119119
└─ AccountWorkflowService (User account workflows)
@@ -321,29 +321,29 @@ private async Task CreateProperty()
321321

322322
### Component Architecture
323323

324-
Aquiis uses a **three-tier component hierarchy** to enable code reuse across SimpleStart and Professional products while maintaining different complexity levels:
324+
Nine uses a **three-tier component hierarchy** to enable code reuse across Nine and Professional products while maintaining different complexity levels:
325325

326326
**Component Tiers:**
327327

328328
```
329-
Entity Components (Tier 1) (3-Aquiis.UI.Shared/Components/Entities/)
329+
Entity Components (Tier 1) (3-Nine.Shared.UI/Components/Entities/)
330330
├─ Pure presentation components
331331
├─ Minimal business logic
332332
├─ Maximum reusability
333333
└─ Examples: LeaseListView, PropertyCard, TenantSearchBox
334334

335-
Feature Components (Tier 2) (3-Aquiis.UI.Shared/Features/)
335+
Feature Components (Tier 2) (3-Nine.Shared.UI/Features/)
336336
├─ Fully-featured implementations
337337
├─ Complete CRUD operations
338338
├─ Business logic included
339339
├─ Service injection
340340
└─ Examples: LeaseManagement, PropertyManagement, TenantManagement
341341

342-
Product Pages (Tier 3) (4-Aquiis.SimpleStart/Features/ or 5-Aquiis.Professional/Features/)
342+
Product Pages (Tier 3) (4-Nine/Features/ or 5-Nine.Professional (not included)/Features/)
343343
├─ Composition layer
344344
├─ Product-specific UX
345345
├─ Routing decisions
346-
└─ Examples: SimpleStart uses Feature components directly, Professional uses custom compositions
346+
└─ Examples: Nine uses Feature components directly, Professional uses custom compositions
347347
```
348348

349349
**When to Use Each Tier:**
@@ -353,15 +353,15 @@ Product Pages (Tier 3) (4-Aquiis.SimpleStart/Features/ or 5-Aquiis.
353353
- Usage: `<LeaseListView Leases="@leases" GroupedLeases="@groupedLeases" />`
354354
- **Feature Component**: Complete feature implementation ready to use
355355
- Example: `LeaseManagement.razor` provides full lease CRUD with navigation
356-
- Usage: SimpleStart: `<LeaseManagement />` (5 lines), Professional: Custom composition
356+
- Usage: Nine: `<LeaseManagement />` (5 lines), Professional: Custom composition
357357
- **Product Page**: Top-level routing and product-specific UX
358-
- Example: SimpleStart `/propertymanagement/leases` → Uses LeaseManagement directly
358+
- Example: Nine `/propertymanagement/leases` → Uses LeaseManagement directly
359359
- Example: Professional `/leases` → Custom layout with LeaseListView + custom panels
360360

361361
**File Naming & Organization:**
362362

363363
```
364-
3-Aquiis.UI.Shared/
364+
3-Nine.Shared.UI/
365365
├── Components/
366366
│ ├── Common/ (Cross-cutting: EntityFilterBar, Modal, etc.)
367367
│ └── Entities/ (Entity-specific: Leases/, Properties/, Tenants/)
@@ -370,10 +370,10 @@ Product Pages (Tier 3) (4-Aquiis.SimpleStart/Features/ or 5-Aquiis.
370370
├── LeaseManagement/
371371
└── TenantManagement/
372372

373-
4-Aquiis.SimpleStart/Features/
373+
4-Nine/Features/
374374
└── PropertyManagement/Index.razor (@page "/propertymanagement/leases")
375375

376-
5-Aquiis.Professional/Features/
376+
5-Nine.Professional (not included)/Features/
377377
└── Leases/Index.razor (@page "/leases")
378378
```
379379

@@ -391,10 +391,10 @@ The `Components/Common/` folder contains reusable components used across all ent
391391
- **Modal.razor**: Reusable modal dialog with customizable content and actions
392392
- **ConfirmDialog.razor**: Confirmation prompts with Yes/No actions
393393

394-
**Example: SimpleStart vs Professional Usage:**
394+
**Example: Nine vs Professional Usage:**
395395

396396
```csharp
397-
// SimpleStart: Direct feature usage (simple, fast to implement)
397+
// Nine: Direct feature usage (simple, fast to implement)
398398
@page "/propertymanagement/leases"
399399
<LeaseManagement />
400400

@@ -559,7 +559,7 @@ Properties follow a status-driven lifecycle (string values from `ApplicationCons
559559

560560
```csharp
561561
@page "/propertymanagement/entities/create"
562-
@using Aquiis.SimpleStart.Components.PropertyManagement.Entities
562+
@using Nine.Components.PropertyManagement.Entities
563563
@attribute [Authorize(Roles = "Administrator,PropertyManager")]
564564
@inject PropertyService PropertyService
565565
@inject UserContextService UserContext
@@ -640,8 +640,8 @@ public async Task<Entity> AddEntityAsync(Entity entity)
640640

641641
1. **EF Core Migrations**: Primary approach for schema changes
642642
- Migrations stored in `Data/Migrations/`
643-
- Run `dotnet ef migrations add MigrationName --project Aquiis.SimpleStart`
644-
- Apply with `dotnet ef database update --project Aquiis.SimpleStart`
643+
- Run `dotnet ef migrations add MigrationName --project Nine`
644+
- Apply with `dotnet ef database update --project Nine`
645645
- Generate SQL script: `dotnet ef migrations script --output schema.sql`
646646
2. **SQL Scripts**: Reference scripts in `Data/Scripts/` (not executed, for documentation)
647647
3. Update `ApplicationDbContext.cs` with DbSet and entity configuration
@@ -654,7 +654,7 @@ public async Task<Entity> AddEntityAsync(Entity entity)
654654

655655
- **Ctrl+Shift+B** to run `dotnet watch` (hot reload, default build task)
656656
- **F5** in VS Code to debug (configured in `.vscode/launch.json`)
657-
- Or: `dotnet run` in `Aquiis.SimpleStart/` directory
657+
- Or: `dotnet run` in `Nine/` directory
658658
- Default URLs: Check terminal output for ports
659659
- Default admin: `superadmin@example.local` / `SuperAdmin@123!`
660660

@@ -760,12 +760,12 @@ Components/PropertyManagement/[Entity]/
760760

761761
1. **Create entity model** inheriting `BaseModel` with `OrganizationId` property
762762
2. **Add DbSet** to `ApplicationDbContext` with proper relationships and configuration
763-
3. **Create EF Core migration**: `dotnet ef migrations add [Name] --project Aquiis.SimpleStart`
763+
3. **Create EF Core migration**: `dotnet ef migrations add [Name] --project Nine`
764764
4. **Create entity-specific service** inheriting `BaseService<TEntity>`:
765765
- Add constructor with dependencies (DbContext, Logger, UserContext, Settings)
766766
- Override `ValidateEntityAsync()` for business rules
767767
- Add entity-specific query methods with org filtering
768-
- Register service in DI container (`2-Aquiis.Application/DependencyInjection.cs`)
768+
- Register service in DI container (`2-Nine.Application/DependencyInjection.cs`)
769769
5. **Create workflow service** (if complex state transitions needed):
770770
- Inherit from `BaseWorkflowService`
771771
- Implement `IWorkflowState<TStatus>` if status machine required
@@ -782,7 +782,7 @@ Components/PropertyManagement/[Entity]/
782782
**Example Entity Service Creation:**
783783

784784
```csharp
785-
// 2-Aquiis.Application/Services/[Entity]Service.cs
785+
// 2-Nine.Application/Services/[Entity]Service.cs
786786
public class DocumentService : BaseService<Document>
787787
{
788788
public DocumentService(

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ jobs:
1717
- name: Setup .NET
1818
uses: actions/setup-dotnet@v4
1919
with:
20-
dotnet-version: "9.0.x"
20+
dotnet-version: "10.0.x"
2121

2222
- name: Restore
23-
run: dotnet restore Aquiis.sln
23+
run: dotnet restore Nine.sln
2424

2525
- name: Build
26-
run: dotnet build Aquiis.sln --no-restore --configuration Release
26+
run: dotnet build Nine.sln --no-restore --configuration Release
2727

2828
- name: Test Core Layer
29-
run: dotnet test 6-Tests/Aquiis.Core.Tests/Aquiis.Core.Tests.csproj --no-build --configuration Release --verbosity normal
29+
run: dotnet test 6-Tests/Nine.Core.Tests/Nine.Core.Tests.csproj --no-build --configuration Release --verbosity normal
3030

3131
- name: Test Application Layer
32-
run: dotnet test 6-Tests/Aquiis.Application.Tests/Aquiis.Application.Tests.csproj --no-build --configuration Release --verbosity normal
32+
run: dotnet test 6-Tests/Nine.Application.Tests/Nine.Application.Tests.csproj --no-build --configuration Release --verbosity normal
3333

3434
- name: Test Shared UI Components (bUnit)
35-
run: dotnet test 6-Tests/Aquiis.UI.Shared.Tests/Aquiis.UI.Shared.Tests.csproj --no-build --configuration Release --verbosity normal
35+
run: dotnet test 6-Tests/Nine.Shared.UI.Tests/Nine.Shared.UI.Tests.csproj --no-build --configuration Release --verbosity normal

.vscode/launch.json

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,13 @@
55
"version": "0.2.0",
66
"configurations": [
77
{
8-
"name": "Launch SimpleStart",
8+
"name": "Launch Nine",
99
"type": "dotnet",
1010
"request": "launch",
1111
"preLaunchTask": "build",
12-
"program": "${workspaceFolder}/Aquiis.SimpleStart/bin/Debug/net9.0/Aquiis.SimpleStart.dll",
12+
"program": "${workspaceFolder}/4-Nine/bin/Debug/net10.0/Nine.dll",
1313
"args": [],
14-
"cwd": "${workspaceFolder}/Aquiis.SimpleStart",
15-
"stopAtEntry": false,
16-
"serverReadyAction": {
17-
"action": "openExternally",
18-
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
19-
},
20-
"env": {
21-
"ASPNETCORE_ENVIRONMENT": "Development"
22-
}
23-
},
24-
{
25-
"name": "Launch Professional",
26-
"type": "dotnet",
27-
"request": "launch",
28-
"preLaunchTask": "build",
29-
"program": "${workspaceFolder}/Aquiis.Professional/bin/Debug/net9.0/Aquiis.Professional.dll",
30-
"args": [],
31-
"cwd": "${workspaceFolder}/Aquiis.Professional",
14+
"cwd": "${workspaceFolder}/4-Nine",
3215
"stopAtEntry": false,
3316
"serverReadyAction": {
3417
"action": "openExternally",

.vscode/tasks.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"label": "watch",
66
"command": "dotnet",
77
"type": "process",
8-
"args": ["watch", "--project", "${workspaceFolder}/Aquiis.SimpleStart"],
8+
"args": ["watch", "--project", "${workspaceFolder}/4-Nine"],
99
"problemMatcher": "$msCompile",
1010
"group": {
1111
"kind": "build",
@@ -16,7 +16,7 @@
1616
"label": "build",
1717
"command": "dotnet",
1818
"type": "process",
19-
"args": ["build", "${workspaceFolder}/Aquiis.sln"],
19+
"args": ["build", "${workspaceFolder}/Nine.sln"],
2020
"problemMatcher": "$msCompile"
2121
},
2222
{

0-Nine.Core/Constants/ApplicationSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class ApplicationSettings
1212
public string PreviousDatabaseFileName { get; set; } = string.Empty;
1313
public bool SoftDeleteEnabled { get; set; }
1414
public string SchemaVersion { get; set; } = string.Empty;
15-
public int MaxOrganizationUsers { get; set; } = 0; // 0 = unlimited (Professional), 3 = SimpleStart limit
15+
public int MaxOrganizationUsers { get; set; } = 0; // 0 = unlimited (Professional), 3 = Nine limit
1616
public string License { get; set; } = string.Empty;
1717
public string LicenseUrl { get; set; } = string.Empty;
1818
public string HelpUrl { get; set; } = string.Empty;

0-Nine.Core/Entities/Repair.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class Repair : BaseModel
1919
// Optional Relationships (Soft References)
2020
/// <summary>
2121
/// Optional: Links this repair to a MaintenanceRequest workflow (Professional product).
22-
/// Null for standalone repairs (SimpleStart product).
22+
/// Null for standalone repairs (Nine product).
2323
/// </summary>
2424
public Guid? MaintenanceRequestId { get; set; }
2525

1-Nine.Infrastructure/Data/ApplicationDbContext.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
576576
entity.HasIndex(e => e.OwnerId);
577577
entity.HasIndex(e => e.IsActive);
578578

579-
// OwnerId is a string foreign key to AspNetUsers (managed by SimpleStartDbContext)
579+
// OwnerId is a string foreign key to AspNetUsers (managed by NineDbContext)
580580
// No navigation property configured here
581581
});
582582

@@ -590,7 +590,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
590590
.HasForeignKey(uo => uo.OrganizationId)
591591
.OnDelete(DeleteBehavior.Cascade);
592592

593-
// UserId and GrantedBy are string foreign keys to AspNetUsers (managed by SimpleStartDbContext)
593+
// UserId and GrantedBy are string foreign keys to AspNetUsers (managed by NineDbContext)
594594
// No navigation properties configured here
595595

596596
// Unique constraint: one role per user per organization
@@ -629,7 +629,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
629629
.HasForeignKey(n => n.OrganizationId)
630630
.OnDelete(DeleteBehavior.Cascade);
631631

632-
// RecipientUserId is a string foreign key to AspNetUsers (managed by SimpleStartDbContext)
632+
// RecipientUserId is a string foreign key to AspNetUsers (managed by NineDbContext)
633633
// No navigation property configured here
634634
});
635635

@@ -651,7 +651,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
651651
.HasForeignKey(np => np.OrganizationId)
652652
.OnDelete(DeleteBehavior.Cascade);
653653

654-
// UserId is a string foreign key to AspNetUsers (managed by SimpleStartDbContext)
654+
// UserId is a string foreign key to AspNetUsers (managed by NineDbContext)
655655
// No navigation property configured here
656656
});
657657

1-Nine.Infrastructure/Interfaces/IKeychainService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Nine.Infrastructure.Interfaces;
77
public interface IKeychainService
88
{
99
/// <summary>Store a password/key in the platform keychain</summary>
10-
bool StoreKey(string password, string label = "Aquiis Database Encryption Key");
10+
bool StoreKey(string password, string label = "Nine Database Encryption Key");
1111

1212
/// <summary>Retrieve the stored password/key, or null if not found</summary>
1313
string? RetrieveKey();

1-Nine.Infrastructure/Services/DatabaseEncryptionService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public DatabaseEncryptionService(
124124
await Task.Delay(200);
125125

126126
// Store password in keychain (best effort - don't fail if keychain unavailable)
127-
var stored = _keychain.StoreKey(password, "Aquiis Database Encryption Password");
127+
var stored = _keychain.StoreKey(password, "Nine Database Encryption Password");
128128
if (!stored)
129129
{
130130
_logger.LogWarning("Failed to store password in keychain - you'll need to enter it manually on next startup");

1-Nine.Infrastructure/Services/LinuxKeychainService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public class LinuxKeychainService : IKeychainService
1717
/// <summary>
1818
/// Initialize keychain service with app-specific identifier
1919
/// </summary>
20-
/// <param name="appName">Application name (e.g., "SimpleStart-Web", "SimpleStart-Electron", "Professional-Web") to prevent keychain conflicts</param>
21-
public LinuxKeychainService(string appName = "Aquiis-Electron")
20+
/// <param name="appName">Application name (e.g., "Nine-Web", "Nine-Electron", "Professional-Web") to prevent keychain conflicts</param>
21+
public LinuxKeychainService(string appName = "Nine-Electron")
2222
{
2323
// Make keychain entry unique per application to prevent password conflicts
2424
_keyValue = $"database-encryption-{appName}";
@@ -31,7 +31,7 @@ public LinuxKeychainService(string appName = "Aquiis-Electron")
3131
/// <param name="keyHex">Hex-encoded encryption key</param>
3232
/// <param name="label">Human-readable label for the key</param>
3333
/// <returns>True if stored successfully</returns>
34-
public bool StoreKey(string keyHex, string label = "Aquiis Database Encryption Key")
34+
public bool StoreKey(string keyHex, string label = "Nine Database Encryption Key")
3535
{
3636
if (!OperatingSystem.IsLinux())
3737
return false;

0 commit comments

Comments
 (0)