Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
807 changes: 807 additions & 0 deletions .github/skills/doc-tester/SKILL.md

Large diffs are not rendered by default.

790 changes: 790 additions & 0 deletions .github/skills/doc-writer/SKILL.md

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ FodyWeavers.xsd
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/mcp.json
!.vscode/*.code-snippets

# Local History for Visual Studio Code
Expand All @@ -440,4 +441,11 @@ FodyWeavers.xsd
*.msp

# Mac folder metadata
.DS_Store
.DS_Store

# Documentation tester workspace
.doc-tester-workspace/


bin/
obj/
7 changes: 7 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
"-y",
"@playwright/mcp@latest"
]
},
"hex1b": {
"command": "dnx",
"args": [
"Hex1b.McpServer@0.66.0",
"--yes"
]
}
}
}
28 changes: 28 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"servers": {
"aspire": {
"type": "stdio",
"command": "aspire",
"args": [
"mcp",
"start"
]
},
"playwright": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@playwright/mcp@latest"
]
},
"hex1b": {
"type": "stdio",
"command": "dnx",
"args": [
"Hex1b.McpServer@0.66.0",
"--yes"
]
}
}
}
9 changes: 9 additions & 0 deletions opencode.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
"@playwright/mcp@latest"
],
"enabled": true
},
"hex1b": {
"type": "local",
"command": [
"dnx",
"Hex1b.McpServer@0.66.0",
"--yes"
],
"enabled": true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ param appServiceHostName string
@description('Location for all resources, needed because Aspire always injects a location parameter')
param location string = resourceGroup().location

@description('Rate limit threshold value for rate limit custom rule (requests per 5 minutes)')
param rateLimitThreshold int = 500

resource frontDoorProfile 'Microsoft.Cdn/profiles@2024-02-01' = {
name: take('${frontDoorName}${uniqueString(resourceGroup().id)}', 50)
location: 'Global'
Expand Down Expand Up @@ -96,3 +99,82 @@ resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2025-06-01' = {
}

output endpointUrl string = 'https://${frontDoorEndpoint.properties.hostName}'

// WAF Policy for DDoS compliance
// Note: WAF policy names must be alphanumeric only (no hyphens)
resource wafPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2025-03-01' = {
name: take('${replace(frontDoorName, '-', '')}wafDDoS${uniqueString(resourceGroup().id)}', 128)
location: 'Global'
sku: {
name: 'Premium_AzureFrontDoor'
}
properties: {
policySettings: {
enabledState: 'Enabled'
mode: 'Detection'
customBlockResponseStatusCode: 403
requestBodyCheck: 'Enabled'
javascriptChallengeExpirationInMinutes: 30
}
customRules: {
rules: [
{
name: 'GlobalRateLimitRule'
enabledState: 'Enabled'
priority: 100
ruleType: 'RateLimitRule'
rateLimitDurationInMinutes: 5
rateLimitThreshold: rateLimitThreshold
matchConditions: [
{
matchVariable: 'RequestUri'
operator: 'Contains'
negateCondition: false
matchValue: [
'/'
]
transforms: []
}
]
action: 'Block'
}
]
}
managedRules: {
managedRuleSets: [
{
ruleSetType: 'Microsoft_BotManagerRuleSet'
ruleSetVersion: '1.1'
ruleGroupOverrides: []
exclusions: []
}
]
}
}
}

// Security policy to associate WAF with Front Door endpoint
resource securityPolicy 'Microsoft.Cdn/profiles/securityPolicies@2025-06-01' = {
parent: frontDoorProfile
name: take('${frontDoorName}-AppDDoS${uniqueString(resourceGroup().id)}', 260)
properties: {
parameters: {
type: 'WebApplicationFirewall'
wafPolicy: {
id: wafPolicy.id
}
associations: [
{
domains: [
{
id: frontDoorEndpoint.id
}
]
patternsToMatch: [
'/*'
]
}
]
}
}
}
24 changes: 23 additions & 1 deletion src/frontend/config/sidebar/docs.topics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const docsTopics: StarlightSidebarTopicsUserConfig = {
'pt-PT': 'Versões anteriores',
ru: 'Предыдущие версии',
tr: 'Önceki sürümler',
uk: 'Попередні версії',
uk: 'Попeredні версії',
'zh-CN': '以前的版本',
},
items: [
Expand Down Expand Up @@ -108,6 +108,28 @@ export const docsTopics: StarlightSidebarTopicsUserConfig = {
},
],
},
{
label: 'Upgrade Aspire',
slug: 'whats-new/upgrade-aspire',
translations: {
da: 'Opgrader Aspire',
de: 'Aspire aktualisieren',
en: 'Upgrade Aspire',
es: 'Actualizar Aspire',
fr: 'Mettre à jour Aspire',
hi: 'Aspire अपग्रेड करें',
id: 'Tingkatkan Aspire',
it: 'Aggiorna Aspire',
ja: 'Aspire をアップグレード',
ko: 'Aspire 업그레이드',
'pt-BR': 'Atualizar Aspire',
'pt-PT': 'Atualizar Aspire',
ru: 'Обновить Aspire',
tr: "Aspire'ı Yükselt",
uk: 'Оновити Aspire',
'zh-CN': '升级 Aspire',
},
},
],
translations: {
da: 'Hvad er nyt',
Expand Down
23 changes: 23 additions & 0 deletions src/frontend/config/sidebar/reference.topics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,29 @@ export const referenceTopics: StarlightSidebarTopicsUserConfig = {
},
slug: 'reference/cli/configuration',
},
{
label: 'Microsoft telemetry',
translations: {
da: 'Microsoft telemetri',
de: 'Microsoft-Telemetrie',
en: 'Microsoft telemetry',
es: 'Telemetría de Microsoft',
fr: 'Télémétrie Microsoft',
hi: 'Microsoft टेलीमेट्री',
id: 'Telemetri Microsoft',
it: 'Telemetria Microsoft',
ja: 'Microsoft テレメトリ',
ko: 'Microsoft 원격 분석',
pt: 'Telemetria da Microsoft',
'pt-BR': 'Telemetria da Microsoft',
'pt-PT': 'Telemetria da Microsoft',
ru: 'Телеметрия Microsoft',
tr: 'Microsoft telemetrisi',
uk: 'Телеметрія Microsoft',
'zh-CN': 'Microsoft 遥测',
},
slug: 'reference/cli/microsoft-collected-cli-telemetry',
},
{
label: 'Commands',
translations: {
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/frontend.esproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.3653345">
<PropertyGroup>
<PublishAssetsDirectory>$(MSBuildProjectDirectory)\dist</PublishAssetsDirectory>
<PublishAssetsDirectory>$(MSBuildProjectDirectory)/dist</PublishAssetsDirectory>
<BuildCommand>pnpm run build</BuildCommand>
<ShouldRunNpmInstall>false</ShouldRunNpmInstall>
<!-- Disables running the build (or compile) script located on package.json during Build -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-tra
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { Resource } from '@opentelemetry/resources';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { ZoneContextManager } from '@opentelemetry/context-zone';
Expand All @@ -225,7 +225,7 @@ export function initializeTelemetry(otlpUrl, headers, resourceAttributes) {
attributes[SemanticResourceAttributes.SERVICE_NAME] = 'browser';

const provider = new WebTracerProvider({
resource: new Resource(attributes),
resource: resourceFromAttributes(attributes),
});
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter(otlpOptions)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ Now let's add OpenTelemetry instrumentation to send telemetry data to the Aspire
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');

// Configure the OTLP endpoint for standalone dashboard
const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317';

// Create resource with service name
const resource = new Resource({
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'weather-api-nodejs',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,12 +635,18 @@ JavaScript/Node.js applications can also send telemetry using OpenTelemetry:
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');

const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317';

// Create resource with service name
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'frontend',
});

const sdk = new NodeSDK({
resource: new Resource({ 'service.name': 'frontend' }),
resource: resource,
traceExporter: new OTLPTraceExporter({ url: otlpEndpoint }),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({ url: otlpEndpoint })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ The preceding code:
- Adds an Azure AI Foundry deployment resource named `chat` with a model name of `Phi-4`. The model name must correspond to an [available model](https://learn.microsoft.com/azure/ai-foundry/foundry-models/concepts/models) in the Azure AI Foundry service.

> [!NOTE]
> The `format` parameter of the `AddDeployment(...)` method can be found in the Azure AI Foundry portal in the details page of the model, right after the `Quick facts` text.
> The `format` parameter of the `AddDeployment(...)` method specifies the model publisher or provider. Common values include:
>
> - `"OpenAI"` for GPT models (e.g., GPT-4o, GPT-4, GPT-3.5 Turbo)
> - `"Microsoft"` for Phi models (e.g., Phi-4, Phi-3.5)
>
> For more information, see the [AIFoundryModel API reference](https://learn.microsoft.com/dotnet/api/aspire.hosting.azure.aifoundrymodel).

### Configure deployment properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,13 +677,19 @@ JavaScript / Node.js アプリケーションも、OpenTelemetry を使用して
const {
PeriodicExportingMetricReader,
} = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');

const otlpEndpoint =
process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317';

// Create resource with service name
const resource = resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'frontend',
});

const sdk = new NodeSDK({
resource: new Resource({ 'service.name': 'frontend' }),
resource: resource,
traceExporter: new OTLPTraceExporter({ url: otlpEndpoint }),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({ url: otlpEndpoint }),
Expand Down
Loading