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
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
**/wwwroot/**/*.js text eol=lf
**/wwwroot/**/*.css text eol=lf

# Shell scripts must keep LF endings. A CRLF checkout turns a script's shebang into `#!/bin/sh\r`, and a
# container that copies the script then fails to start because no interpreter by that name exists.
*.sh text eol=lf

# Vendored specification cassettes are verified against the SHA-256 of the upstream file recorded in their
# manifest. Line ending normalization would rewrite the bytes and break that check on Windows checkouts.
tests/CrestApps.OrchardCore.Tests/Telephony/Cassettes/** -text

# Ensure binary files are never treated as text.
*.webp binary
*.png binary
Expand Down
33 changes: 26 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
# Disable version update PRs; only Dependabot security updates create PRs.
open-pull-requests-limit: 0
interval: "weekly"
# Version update PRs are enabled so patched versions arrive before an advisory is published.
# NuGetAudit fails the build on a known advisory, so a dependency left to drift becomes a hard
# stop rather than a warning. OrchardCore packages stay pinned via the ignore list below.
open-pull-requests-limit: 10
groups:
# One PR per weekly run for routine bumps keeps review load proportional to risk.
non-major-dependencies:
update-types:
- "minor"
- "patch"
ignore:
# OrchardCore packages are pinned; never auto-update them.
- dependency-name: "OrchardCore.*"
Expand All @@ -19,11 +27,22 @@ updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 0
interval: "weekly"
open-pull-requests-limit: 5
groups:
non-major-dependencies:
update-types:
- "minor"
- "patch"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 0
interval: "weekly"
# Action versions are part of the supply chain: a stale action is an unpatched dependency that runs
# with repository credentials.
open-pull-requests-limit: 5
groups:
actions:
patterns:
- "*"
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
config-file: ./.github/codeql/codeql-config.yml

- name: Build solution
run: dotnet build CrestApps.OrchardCore.slnx -c Release /p:NuGetAudit=false
run: dotnet build CrestApps.OrchardCore.slnx -c Release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/main_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v6
with:
# The migration additive-only gate checks never-released justifications against stable release tags.
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: "15"
Expand All @@ -37,7 +40,7 @@ jobs:
- name: Build
# See pr_ci.yml for the reason why we disable NuGet audit warnings.
run: |
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true /p:NuGetAudit=false
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true
- name: Unit Tests
run: |
dotnet test -c Release --no-build ./tests/CrestApps.OrchardCore.Tests/CrestApps.OrchardCore.Tests.csproj
5 changes: 4 additions & 1 deletion .github/workflows/pr_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
name: Build & Test
steps:
- uses: actions/checkout@v6
with:
# The migration additive-only gate checks never-released justifications against stable release tags.
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: "15"
Expand All @@ -33,7 +36,7 @@ jobs:
# treat warnings as errors could break anytime, without us changing the code. This prevents that. Treating them as
# warnings and other better approaches don't work, see https://github.com/OrchardCMS/OrchardCore/pull/16317.
run: |
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true /p:NuGetAudit=false
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true
- name: Unit Tests
run: |
dotnet test -c Release --no-build ./tests/CrestApps.OrchardCore.Tests/CrestApps.OrchardCore.Tests.csproj
5 changes: 4 additions & 1 deletion .github/workflows/preview_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
name: Build, Test, Deploy
steps:
- uses: actions/checkout@v6
with:
# The migration additive-only gate checks never-released justifications against stable release tags.
fetch-depth: 0
- name: Check if should publish
id: check-publish
shell: pwsh
Expand All @@ -40,7 +43,7 @@ jobs:
if: steps.check-publish.outputs.should-publish == 'true'
# See pr_ci.yml for the reason why we disable NuGet audit warnings.
run: |
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true /p:NuGetAudit=false
dotnet build -c Release -warnaserror /p:TreatWarningsAsErrors=true /p:RunAnalyzers=true
- name: Unit Tests
if: steps.check-publish.outputs.should-publish == 'true'
run: |
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/validate_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: Validate Documentation
on:
pull_request:
paths:
- 'src/CrestApps.Docs/**'
- '.github/workflows/validate_docs.yml'
- 'src/**'
- 'tests/**'

permissions:
contents: read
Expand All @@ -29,7 +31,10 @@ jobs:
run: npm ci

- name: Build and validate links
# `set -o pipefail` is required: without it the pipeline exit status is `tee`'s, so a failing
# docusaurus build reported success and only broken links were ever caught.
run: |
set -o pipefail
npx docusaurus build 2>&1 | tee build-output.txt
if grep -qi "broken link" build-output.txt; then
echo ""
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate_prompts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
10.0.x
- name: Build prompt validation tool
run: |
dotnet build -c Release src/Common/CrestApps.Core.Templates/CrestApps.Core.Templates.csproj /p:NuGetAudit=false
dotnet build -c Release src/Common/CrestApps.Core.Templates/CrestApps.Core.Templates.csproj
- name: Validate template file structure
shell: bash
run: |
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,9 @@ src/docs/node_modules/
src/docs/build/
src/docs/.docusaurus/
src/docs/.cache-loader/

# Public API approval output written when a recorded surface no longer matches.
*.received.txt

# Playwright MCP planning scaffolding (not part of the shipped product).
.playwright-mcp/
30 changes: 29 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,37 @@
<CommonTargetFrameworks>$(DefaultTargetFramework)</CommonTargetFrameworks>
</PropertyGroup>

<!--
The GitHub Copilot SDK downloads a platform-specific Copilot CLI tarball from registry.npmjs.org during
BeforeBuild. That makes the whole solution unbuildable without public npm egress, which breaks air-gapped
and restricted-network builds and pulls an unpinned artifact into the build. The download is opt-in here.

To build the Copilot chat orchestrator with its CLI, set one of:
-p:CopilotSkipCliDownload=false downloads the CLI from the configured npm registry
-p:CopilotCliBinaryPath=<path-to-binary> uses a vendored binary and skips the download entirely
-->
<PropertyGroup>
<CopilotSkipCliDownload Condition="'$(CopilotSkipCliDownload)' == '' And '$(CopilotCliBinaryPath)' == ''">true</CopilotSkipCliDownload>
</PropertyGroup>

<!--
Dependency vulnerability auditing. This has to be a build failure rather than a warning: CI previously
passed -p:NuGetAudit=false on every workflow, so advisories against transitive packages went unseen.
Auditing every package at the lowest severity is deliberate - a transitive moderate advisory is exactly
what the suppressed builds were hiding. When a new advisory appears, pin the patched version in
Directory.Packages.props rather than lowering these settings.
-->
<PropertyGroup>
<NuGetAudit Condition="'$(NuGetAudit)' == ''">true</NuGetAudit>
<NuGetAuditMode Condition="'$(NuGetAuditMode)' == ''">all</NuGetAuditMode>
<NuGetAuditLevel Condition="'$(NuGetAuditLevel)' == ''">low</NuGetAuditLevel>
<WarningsAsErrors>$(WarningsAsErrors);NU1901;NU1902;NU1903;NU1904</WarningsAsErrors>
</PropertyGroup>

<!-- Default TFMs to use when building and packaging -->
<PropertyGroup>
<TargetFrameworks>$(CommonTargetFrameworks)</TargetFrameworks>
<TargetFramework Condition="$([System.String]::Copy('$(CommonTargetFrameworks)').Contains(';')) == 'False'">$(CommonTargetFrameworks)</TargetFramework>
<TargetFrameworks Condition="$([System.String]::Copy('$(CommonTargetFrameworks)').Contains(';')) == 'True'">$(CommonTargetFrameworks)</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Authors>Mike Alhayek</Authors>
<Company>CrestApps</Company>
Expand Down
6 changes: 6 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<PackageVersion Include="ZString" Version="2.6.0" />
<PackageVersion Include="YesSql.Abstractions" Version="5.4.7" />
<PackageVersion Include="YesSql.Core" Version="5.4.7" />
<PackageVersion Include="YesSql.Provider.PostgreSql" Version="5.4.7" />
<PackageVersion Include="YesSql.Provider.Sqlite" Version="5.4.7" />
</ItemGroup>
<ItemGroup>
Expand All @@ -34,6 +35,7 @@
<PackageVersion Include="OrchardCore.Alias" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.ArchiveLater" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.Autoroute.Core" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.AuditTrail.Abstractions" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.ContentFields" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.ContentManagement" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.ContentManagement.Abstractions" Version="$(OrchardCoreVersion)" />
Expand Down Expand Up @@ -72,6 +74,7 @@
<PackageVersion Include="OrchardCore.PublishLater" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.Recipes.Abstractions" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.Redis" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.Redis.Abstractions" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.ResourceManagement" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.Roles.Abstractions" Version="$(OrchardCoreVersion)" />
<PackageVersion Include="OrchardCore.AzureAI.Core" Version="$(OrchardCoreVersion)" />
Expand Down Expand Up @@ -136,6 +139,7 @@
<PackageVersion Include="Azure.Identity" Version="1.21.0" />
<PackageVersion Include="Azure.Messaging.EventGrid" Version="5.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Compliance.Abstractions" Version="10.8.0" />
<PackageVersion Include="Microsoft.Extensions.Compliance.Redaction" Version="10.8.0" />
Expand All @@ -149,8 +153,10 @@
<ItemGroup>
<!-- Testing Packages -->
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.61.0" />
<PackageVersion Include="PublicApiGenerator" Version="11.5.4" />
<PackageVersion Include="xunit.v3" Version="3.2.2" />
<PackageVersion Include="xunit.analyzers" Version="1.27.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
Expand Down
2 changes: 1 addition & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ gulp.task('default', gulp.series(['build']));
*/

function getAssetGroups() {
var assetManifestPaths = glob.sync("./src/{Modules,Resources,Themes}/*/Assets.json", {});
var assetManifestPaths = glob.sync("./src/{Modules,Resources,Startup,Themes}/*/Assets.json", {});
var assetGroups = [];
assetManifestPaths.forEach(function (assetManifestPath) {
var assetManifest = require("./" + assetManifestPath);
Expand Down
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
},
"dependencies": {
"chart.js": "^4.5.1",
"extendable-media-recorder": "^9.2.36"
"extendable-media-recorder": "^9.2.36",
"sip.js": "0.21.2"
},
"overrides": {
"brace-expansion": "^5.0.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using CrestApps.OrchardCore.Telephony.Models;

namespace CrestApps.OrchardCore.Telephony;

/// <summary>
/// Contributes contextual cards shown alongside a ringing inbound call in the soft-phone
/// incoming-call modal. Other modules implement this contract to surface related records, such as a
/// Contact Center showing customers matched by the caller's phone number, without the Telephony
/// module taking a dependency on them.
/// </summary>
public interface IIncomingCallContextProvider
{
/// <summary>
/// Contributes cards for the ringing inbound call described by the supplied context.
/// </summary>
/// <param name="context">The contribution context that carries the call and accepts the cards.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
Task ContributeAsync(IncomingCallContributionContext context, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using CrestApps.OrchardCore.Telephony.Models;

namespace CrestApps.OrchardCore.Telephony;

/// <summary>
/// Pushes a ringing inbound call to a specific user's connected soft phone. The dispatcher gathers
/// the contextual cards from the registered <see cref="IIncomingCallContextProvider"/> instances and
/// raises the incoming-call modal on every soft-phone connection the user currently has open.
/// </summary>
public interface IIncomingCallDispatcher
{
/// <summary>
/// Offers the ringing inbound call to the specified user's soft phone.
/// </summary>
/// <param name="userId">The identifier of the user the call is offered to.</param>
/// <param name="call">The ringing inbound call.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
Task DispatchAsync(string userId, TelephonyCall call, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using CrestApps.OrchardCore.Telephony.Models;

namespace CrestApps.OrchardCore.Telephony;

/// <summary>
/// Contributes canonical provider identities so that voice ingress can resolve provider aliases to a
/// single stable technical name without referencing provider implementation assemblies. Provider modules
/// implement this contract to register their canonical name and any alternate runtime names.
/// </summary>
public interface IProviderIdentityProvider
{
/// <summary>
/// Gets the canonical provider identities contributed by the implementing provider module.
/// </summary>
/// <returns>The canonical provider identities and their aliases.</returns>
IEnumerable<ProviderIdentity> GetIdentities();
}
Loading
Loading