Skip to content

Commit c02bc17

Browse files
authored
Fixing Aspire startup (#208)
1 parent 6e202c2 commit c02bc17

16 files changed

Lines changed: 261 additions & 110 deletions

docs/enhancements.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Sudoku App — Enhancement Backlog
2+
3+
> Both frontend apps (Blazor and React) should be kept in feature parity unless noted otherwise.
4+
5+
---
6+
7+
## Infrastructure & Deployment
8+
9+
- [ ] **Deploy Sudoku.React to Static Web App** — Add the React frontend to the existing Azure deployment pipeline, alongside the Blazor app. A spec for this already exists at `docs/specs/setup-deployment-react-static-web-app.md`.
10+
- [ ] **Add VNet to infrastructure** — Integrate a Virtual Network into the Bicep infrastructure (`infra/main.bicep`) to secure communication between the API, storage, and frontends.
11+
12+
---
13+
14+
## User Profiles & Identity
15+
16+
- [ ] **Profile creation flow** — Replace the auto-generated alias with an explicit "create your profile" onboarding step when a user first visits the app. The user picks their own alias/display name.
17+
- [ ] **Passwordless profile locking** — Secure profiles without traditional passwords. Options to explore: a device-bound passkey (WebAuthn/FIDO2), a one-time magic link sent to email, or a PIN stored in a signed/encrypted browser token. Goal: prevent another user from claiming or hijacking an existing alias.
18+
- [ ] **User profile page** — A dedicated page where users can view and edit their alias/display name, see their profile info, and manage their identity across sessions.
19+
20+
---
21+
22+
## Navigation & UX
23+
24+
- [ ] **New landing/home page** — Replace the current entry point with a proper home screen offering clear navigation to: Manage Profile, View Game Stats, Start a New Game, and Browse Game List.
25+
- [ ] **Game stats page** — Surface per-user statistics: games played, win rate, average solve time by difficulty, best times, streaks, etc.
26+
27+
---
28+
29+
## Progressive Web App (PWA)
30+
31+
- [ ] **Convert Sudoku.React to PWA** — Add a Web App Manifest, service worker, and offline caching strategy so the React app can be installed on mobile/desktop and played without a connection.
32+
- [ ] **Convert Sudoku.Blazor to PWA** — Add PWA support to the Blazor Server app. Note: Blazor Server relies on a live SignalR connection, so offline play may be limited — consider caching the shell and showing a graceful offline message.
33+
34+
---
35+
36+
## Gameplay Enhancements
37+
38+
- [ ] **Timer display** — Show an elapsed timer per game session, visible in both frontends.
39+
- [ ] **Hint system** — Allow users to request a hint (reveal one correct cell) with a configurable limit per game.
40+
- [ ] **Difficulty-based scoring** — Award points based on difficulty, solve time, and hints used.
41+
- [ ] **Pause/resume** — Let players pause a game (hiding the board) and resume later without losing progress.
42+
- [ ] **Keyboard navigation** — Full keyboard support for cell selection and number entry (important for desktop PWA experience).
43+
44+
---
45+
46+
## Quality & Polish
47+
48+
- [ ] **Feature flag / shared feature contract** — Define a shared list of features that both Blazor and React must implement, so parity gaps are caught early (could be a simple checklist in this file or a lightweight config).
49+
- [ ] **End-to-end tests** — Add Playwright or Cypress tests covering the main user flows (new game, solve, profile creation) for both frontends.
50+
- [ ] **Mobile-responsive layout audit** — Review both frontends on small screens now that PWA is a goal; fix any layout issues.

scripts/set-app-config.sh

Lines changed: 160 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,184 @@
11
#!/bin/bash
22
# =============================================================================
3-
# Azure App Configuration – Sudoku Production Settings
3+
# Azure App Configuration – Sudoku Settings
44
# =============================================================================
55
# Usage:
66
# chmod +x set-app-config.sh
7-
# ./set-app-config.sh
7+
# ./set-app-config.sh # push both Development and Production
8+
# ./set-app-config.sh Development # push Development only
9+
# ./set-app-config.sh Production # push Production only
810
#
911
# Prerequisites:
1012
# - Azure CLI installed and logged in (az login)
1113
# - Contributor or App Configuration Data Owner role on the App Config store
1214
# =============================================================================
1315

1416
APP_CONFIG_NAME="appcs-xenobiasoft-prod"
15-
LABEL="Production"
16-
17-
echo "Setting App Configuration keys for: $APP_CONFIG_NAME (label: $LABEL)"
18-
echo "---------------------------------------------------------------------"
17+
TARGET_LABEL=${1:-"both"}
1918

2019
set_key() {
21-
local key=$1
22-
local value=$2
23-
echo "Setting: $key = $value"
20+
local label=$1
21+
local key=$2
22+
local value=$3
23+
echo " [$label] $key = $value"
2424
az appconfig kv set \
2525
--name "$APP_CONFIG_NAME" \
2626
--key "$key" \
2727
--value "$value" \
28-
--label "$LABEL" \
28+
--label "$label" \
2929
--yes
3030
}
3131

32-
# -----------------------------------------------------------------------------
33-
# Cosmos DB
34-
# -----------------------------------------------------------------------------
35-
set_key "UseCosmosDb" "true"
36-
set_key "CosmosDb:DatabaseName" "sudoku"
37-
set_key "CosmosDb:ContainerName" "games"
38-
set_key "CosmosDb:UseManagedIdentity" "true"
39-
set_key "CosmosDb:AccountEndpoint" "https://cosmos-sudoku-prod.documents.azure.com:443/"
40-
set_key "CosmosDb:ConnectionMode" "Direct"
41-
42-
# -----------------------------------------------------------------------------
43-
# Azure Storage
44-
# -----------------------------------------------------------------------------
45-
set_key "AzureStorage:ContainerName" "sudoku-games"
46-
set_key "AzureStorage:UseManagedIdentity" "true"
47-
set_key "AzureStorage:AccountName" "stxenobiasoftprod"
48-
49-
# -----------------------------------------------------------------------------
50-
# API & CORS
51-
# -----------------------------------------------------------------------------
52-
set_key "ApiBaseUrl" "https://xenobiasoftsudokuapi-prod.azurewebsites.net/"
53-
set_key "AllowedHosts" "*"
54-
set_key "Cors:AllowedOrigins:0" "https://sudoku.xenobiasoft.com"
55-
set_key "Cors:AllowedOrigins:1" "https://xenobiasoftsudoku-prod.azurewebsites.net"
56-
57-
# -----------------------------------------------------------------------------
58-
# Sudoku Game Settings
59-
# -----------------------------------------------------------------------------
60-
set_key "Sudoku:Game:DefaultDifficulty" "Medium"
61-
set_key "Sudoku:Game:MaxHintsPerGame" "3"
62-
set_key "Sudoku:Game:AutoSaveIntervalSeconds" "30"
63-
set_key "Sudoku:Game:EnableStatistics" "true"
64-
set_key "Sudoku:UI:DefaultTheme" "Light"
65-
set_key "Sudoku:UI:ShowTimer" "true"
66-
set_key "Sudoku:UI:EnableAnimations" "true"
67-
set_key "Sudoku:UI:CellSizePixels" "40"
68-
set_key "Sudoku:Performance:GameStateCacheTimeoutSeconds" "300"
69-
set_key "Sudoku:Performance:MaxConcurrentGamesPerUser" "5"
70-
set_key "Sudoku:Performance:EnableResponseCompression" "true"
71-
72-
# -----------------------------------------------------------------------------
73-
# Logging
74-
# -----------------------------------------------------------------------------
75-
set_key "Logging:LogLevel:Default" "Information"
76-
set_key "Logging:LogLevel:Microsoft.AspNetCore" "Warning"
77-
set_key "Logging:ApplicationInsights:LogLevel:Default" "Information"
78-
set_key "Logging:ApplicationInsights:LogLevel:Microsoft" "Warning"
79-
80-
# -----------------------------------------------------------------------------
81-
# Swagger (temporary — disable when done testing)
82-
# -----------------------------------------------------------------------------
83-
set_key "EnableSwagger" "false"
32+
# =============================================================================
33+
# Production settings
34+
# =============================================================================
35+
push_production() {
36+
local LABEL="Production"
37+
echo ""
38+
echo "Setting App Configuration keys (label: $LABEL)"
39+
echo "---------------------------------------------------------------------"
40+
41+
# -------------------------------------------------------------------------
42+
# Cosmos DB
43+
# -------------------------------------------------------------------------
44+
set_key "$LABEL" "UseCosmosDb" "true"
45+
set_key "$LABEL" "CosmosDb:DatabaseName" "sudoku"
46+
set_key "$LABEL" "CosmosDb:ContainerName" "games"
47+
set_key "$LABEL" "CosmosDb:UseManagedIdentity" "true"
48+
set_key "$LABEL" "CosmosDb:AccountEndpoint" "https://cosmos-sudoku-prod.documents.azure.com:443/"
49+
set_key "$LABEL" "CosmosDb:ConnectionMode" "Direct"
50+
51+
# -------------------------------------------------------------------------
52+
# Azure Storage
53+
# -------------------------------------------------------------------------
54+
set_key "$LABEL" "AzureStorage:ContainerName" "sudoku-games"
55+
set_key "$LABEL" "AzureStorage:UseManagedIdentity" "true"
56+
set_key "$LABEL" "AzureStorage:AccountName" "stxenobiasoftprod"
57+
58+
# -------------------------------------------------------------------------
59+
# API & CORS
60+
# -------------------------------------------------------------------------
61+
set_key "$LABEL" "ApiBaseUrl" "https://xenobiasoftsudokuapi-prod.azurewebsites.net/"
62+
set_key "$LABEL" "AllowedHosts" "*"
63+
set_key "$LABEL" "Cors:AllowedOrigins:0" "https://sudoku.xenobiasoft.com"
64+
set_key "$LABEL" "Cors:AllowedOrigins:1" "https://xenobiasoftsudoku-prod.azurewebsites.net"
65+
66+
# -------------------------------------------------------------------------
67+
# Sudoku Game Settings
68+
# -------------------------------------------------------------------------
69+
set_key "$LABEL" "Sudoku:Game:DefaultDifficulty" "Medium"
70+
set_key "$LABEL" "Sudoku:Game:MaxHintsPerGame" "3"
71+
set_key "$LABEL" "Sudoku:Game:AutoSaveIntervalSeconds" "30"
72+
set_key "$LABEL" "Sudoku:Game:EnableStatistics" "true"
73+
set_key "$LABEL" "Sudoku:UI:DefaultTheme" "Light"
74+
set_key "$LABEL" "Sudoku:UI:ShowTimer" "true"
75+
set_key "$LABEL" "Sudoku:UI:EnableAnimations" "true"
76+
set_key "$LABEL" "Sudoku:UI:CellSizePixels" "40"
77+
set_key "$LABEL" "Sudoku:Performance:GameStateCacheTimeoutSeconds" "300"
78+
set_key "$LABEL" "Sudoku:Performance:MaxConcurrentGamesPerUser" "5"
79+
set_key "$LABEL" "Sudoku:Performance:EnableResponseCompression" "true"
80+
81+
# -------------------------------------------------------------------------
82+
# Logging
83+
# -------------------------------------------------------------------------
84+
set_key "$LABEL" "Logging:LogLevel:Default" "Information"
85+
set_key "$LABEL" "Logging:LogLevel:Microsoft.AspNetCore" "Warning"
86+
set_key "$LABEL" "Logging:ApplicationInsights:LogLevel:Default" "Information"
87+
set_key "$LABEL" "Logging:ApplicationInsights:LogLevel:Microsoft" "Warning"
88+
89+
# -------------------------------------------------------------------------
90+
# Swagger (disabled in production)
91+
# -------------------------------------------------------------------------
92+
set_key "$LABEL" "EnableSwagger" "false"
93+
94+
echo ""
95+
echo "Done! Production keys set in '$APP_CONFIG_NAME'."
96+
}
97+
98+
# =============================================================================
99+
# Development settings
100+
# =============================================================================
101+
push_development() {
102+
local LABEL="Development"
103+
echo ""
104+
echo "Setting App Configuration keys (label: $LABEL)"
105+
echo "---------------------------------------------------------------------"
106+
107+
# -------------------------------------------------------------------------
108+
# Cosmos DB (same account as prod, separate container for dev data)
109+
# -------------------------------------------------------------------------
110+
set_key "$LABEL" "UseCosmosDb" "true"
111+
set_key "$LABEL" "CosmosDb:DatabaseName" "sudoku"
112+
set_key "$LABEL" "CosmosDb:ContainerName" "games-dev"
113+
set_key "$LABEL" "CosmosDb:UseManagedIdentity" "true"
114+
set_key "$LABEL" "CosmosDb:AccountEndpoint" "https://cosmos-sudoku-prod.documents.azure.com:443/"
115+
set_key "$LABEL" "CosmosDb:ConnectionMode" "Direct"
116+
117+
# -------------------------------------------------------------------------
118+
# Azure Storage
119+
# -------------------------------------------------------------------------
120+
set_key "$LABEL" "AzureStorage:ContainerName" "sudoku-games"
121+
set_key "$LABEL" "AzureStorage:UseManagedIdentity" "true"
122+
set_key "$LABEL" "AzureStorage:AccountName" "stxenobiasoftprod"
123+
124+
# -------------------------------------------------------------------------
125+
# API (no CORS restriction — API uses AllowAnyOrigin() in Development)
126+
# -------------------------------------------------------------------------
127+
set_key "$LABEL" "ApiBaseUrl" "http://sudoku-api"
128+
set_key "$LABEL" "AllowedHosts" "*"
129+
130+
# -------------------------------------------------------------------------
131+
# Sudoku Game Settings (same as production)
132+
# -------------------------------------------------------------------------
133+
set_key "$LABEL" "Sudoku:Game:DefaultDifficulty" "Medium"
134+
set_key "$LABEL" "Sudoku:Game:MaxHintsPerGame" "3"
135+
set_key "$LABEL" "Sudoku:Game:AutoSaveIntervalSeconds" "30"
136+
set_key "$LABEL" "Sudoku:Game:EnableStatistics" "true"
137+
set_key "$LABEL" "Sudoku:UI:DefaultTheme" "Light"
138+
set_key "$LABEL" "Sudoku:UI:ShowTimer" "true"
139+
set_key "$LABEL" "Sudoku:UI:EnableAnimations" "true"
140+
set_key "$LABEL" "Sudoku:UI:CellSizePixels" "40"
141+
set_key "$LABEL" "Sudoku:Performance:GameStateCacheTimeoutSeconds" "300"
142+
set_key "$LABEL" "Sudoku:Performance:MaxConcurrentGamesPerUser" "5"
143+
set_key "$LABEL" "Sudoku:Performance:EnableResponseCompression" "true"
144+
145+
# -------------------------------------------------------------------------
146+
# Logging (more verbose in development)
147+
# -------------------------------------------------------------------------
148+
set_key "$LABEL" "Logging:LogLevel:Default" "Debug"
149+
set_key "$LABEL" "Logging:LogLevel:Microsoft.AspNetCore" "Information"
150+
set_key "$LABEL" "Logging:ApplicationInsights:LogLevel:Default" "Information"
151+
set_key "$LABEL" "Logging:ApplicationInsights:LogLevel:Microsoft" "Warning"
152+
153+
# -------------------------------------------------------------------------
154+
# Swagger (enabled in development)
155+
# -------------------------------------------------------------------------
156+
set_key "$LABEL" "EnableSwagger" "true"
157+
158+
echo ""
159+
echo "Done! Development keys set in '$APP_CONFIG_NAME'."
160+
}
161+
162+
# =============================================================================
163+
# Run
164+
# =============================================================================
165+
case "$TARGET_LABEL" in
166+
"Production")
167+
push_production
168+
;;
169+
"Development")
170+
push_development
171+
;;
172+
"both")
173+
push_production
174+
push_development
175+
;;
176+
*)
177+
echo "Unknown label '$TARGET_LABEL'. Valid options: Production, Development, both"
178+
exit 1
179+
;;
180+
esac
84181

85182
echo ""
86-
echo "Done! All keys set under label '$LABEL' in '$APP_CONFIG_NAME'."
183+
echo "All done!"
87184
echo ""

src/backend/Sudoku.Api/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
var keyVaultUri = builder.Configuration["ConnectionStrings:AzureKeyVault"];
1111
if (!string.IsNullOrEmpty(keyVaultUri))
1212
{
13-
builder.Configuration.AddAzureKeyVault(new Uri(keyVaultUri), new ManagedIdentityCredential());
13+
builder.Configuration.AddAzureKeyVault(new Uri(keyVaultUri), new DefaultAzureCredential());
1414
}
1515
else
1616
{

src/backend/Sudoku.Api/Sudoku.Api.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13-
<PackageReference Include="Aspire.Azure.Security.KeyVault" Version="13.2.0" />
14-
<PackageReference Include="Aspire.Microsoft.Azure.Cosmos" Version="13.2.0" />
13+
<PackageReference Include="Aspire.Azure.Security.KeyVault" Version="13.2.2" />
14+
<PackageReference Include="Aspire.Microsoft.Azure.Cosmos" Version="13.2.2" />
1515
<PackageReference Include="MediatR" Version="14.1.0" />
1616
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
1717
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />

src/backend/Sudoku.Api/appsettings.Development.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
"Microsoft.AspNetCore": "Warning"
66
}
77
},
8-
"UseCosmosDb": true,
98
"CosmosDb": {
10-
"DisableSslValidation": true,
11-
"DatabaseName": "sudoku",
12-
"ContainerName": "games"
9+
"ContainerName": "games-dev"
10+
},
11+
"appconfig": {
12+
"Endpoint": "https://appcs-xenobiasoft-prod.azconfig.io",
13+
"ManagedIdentityEnabled": true
1314
},
1415
"AzureAppConfiguration": {
15-
"KeyFilter": "*",
1616
"LabelFilter": "Development"
1717
}
1818
}

src/backend/Sudoku.Api/appsettings.Production.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55
"Microsoft.AspNetCore": "Warning"
66
}
77
},
8-
"AllowedHosts": "*",
98
"appconfig": {
109
"Endpoint": "https://appcs-xenobiasoft-prod.azconfig.io",
1110
"ManagedIdentityEnabled": true
11+
},
12+
"AzureAppConfiguration": {
13+
"LabelFilter": "Production"
14+
},
15+
"Cors": {
16+
"AllowedOrigins": [ "https://sudoku.xenobiasoft.com", "https://xenobiasoftsudokuapi-prod.azurewebsites.net" ]
1217
}
13-
}
18+
}

src/backend/Sudoku.Api/appsettings.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,12 @@
1010
"DatabaseName": "sudoku",
1111
"ContainerName": "games"
1212
},
13-
"appconfig": {
14-
"Endpoint": "https://appcs-xenobiasoft-prod.azconfig.io",
15-
"ManagedIdentityEnabled": true
16-
},
1713
"AzureAppConfiguration": {
1814
"KeyFilter": "*",
19-
"LabelFilter": "Development",
2015
"RefreshInterval": 30,
2116
"FeatureFlags": {
2217
"Enabled": true,
2318
"RefreshInterval": 30
2419
}
25-
},
26-
"Cors": {
27-
"AllowedOrigins": [ "https://sudoku.xenobiasoft.com", "https://xenobiasoftsudoku.azurewebsites.net" ]
2820
}
2921
}

0 commit comments

Comments
 (0)