Skip to content

Flatten dashboard persistence directory layout - #20006

Open
James Newton-King (JamesNK) wants to merge 2 commits into
mainfrom
dashboard-flatten-persistence-layout
Open

Flatten dashboard persistence directory layout#20006
James Newton-King (JamesNK) wants to merge 2 commits into
mainfrom
dashboard-flatten-persistence-layout

Conversation

@JamesNK

Copy link
Copy Markdown
Member

Description

Dashboard persistence currently nests historical runs under an application-specific directory. This makes the storage hierarchy harder to inspect and prevents all run snapshots from sharing one predictable location.

This change:

  • Stores all run snapshots directly under the shared runs directory.
  • Adds an empty marker file named with the application's stable storage key to each run directory, allowing discovery to reject unrelated applications before reading and deserializing run.json.
  • Stores resume-mode databases and their adjacent lock files under a shared resumes directory.
  • Renames the cross-mode working directory property to CurrentWorkingDirectory.
  • Preserves application-scoped retention, pinning, locking, and historical run selection.

User-facing usage

No configuration changes are required. With a configured dashboard data directory, persisted data now has this shape:

<data-root>/
├── runs/
│   ├── <run-id>/
│   │   ├── <application-key>
│   │   ├── dashboard.db
│   │   └── run.json
│   └── <run-id>.lock
└── resumes/
    ├── <application-key>/
    │   └── dashboard.db
    └── <application-key>.lock

Security considerations

Persisted dashboard data can contain telemetry, environment variables, and console logs. The shared runs and resumes directories and resume application directories are restricted to owner-only permissions (0700) on Unix. Windows uses inherited ACLs. Temporary mode uses Directory.CreateTempSubdirectory, which creates an owner-only directory on Unix and inherits the current user's temporary-directory ACL on Windows.

Validation:

dotnet test --project tests/Aspire.Dashboard.Tests/Aspire.Dashboard.Tests.csproj --no-launch-profile -- --filter-class "*.DashboardDataSourceTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
Passed: 44

The focused failed-startup cleanup test also passed with the shared runs directory.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 20006

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 20006"

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical storage collisions and migration gaps must be resolved before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Flattens dashboard persistence into shared runs and resumes directories while preserving application identification.

Changes:

  • Adds application marker files for run discovery.
  • Relocates resume databases and locks.
  • Renames the working-directory property and updates tests.
File summaries
File Description
tests/Aspire.Dashboard.Tests/Model/DashboardDataSourceTests.cs Updates persistence and discovery tests.
tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs Adjusts failed-startup cleanup coverage.
src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs Implements the flattened layout. Outstanding issues include run-ID collisions, missing run/resume migration compatibility, and outdated persistence documentation.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs
Comment thread src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs
Comment thread src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs
Comment thread src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Tests selector

9 / 99 PR test projects · 3 PR jobs · 1 advisory-only target, from 3 changed files.

Selected PR test projects (9 / 99)

Aspire.Cli.EndToEnd.Tests, Aspire.Dashboard.Components.Tests, Aspire.Dashboard.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.RemoteHost.Tests, Aspire.Hosting.Testing.Tests, Aspire.Managed.Tests, Aspire.Playground.Tests

Selected PR jobs (3)

cli-starter-validation, extension-e2e, polyglot

Advisory workflow impact (1)

  • deployment-e2e (schedule/dispatch-only)

How these were chosen — grouped by what changed

🔧 src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs (changed source)
7 via the project graph: Aspire.Dashboard.Components.Tests, Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.RemoteHost.Tests (2 hops), Aspire.Hosting.Testing.Tests, Aspire.Managed.Tests (2 hops), Aspire.Playground.Tests (2 hops)

📦 affected project Aspire.Managed
1 test: Aspire.Cli.EndToEnd.Tests

🧪 tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs (changed test)
1 directly: Aspire.Dashboard.Tests

🧪 tests/Aspire.Dashboard.Tests/Model/DashboardDataSourceTests.cs (changed test)
1 directly: Aspire.Dashboard.Tests

Job reasons

Job Triggered by
cli-starter-validation affected project Aspire.Managed
deployment-e2e affected project Aspire.Managed
extension-e2e src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs
• affected project Aspire.Dashboard
polyglot affected project Aspire.Managed

Selection computed for commit 36e2d41.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Constructor failure cleanup must prevent orphaned run directories, and the security documentation must be made consistent.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

docs/specs/dashboard-persistence.md:95

  • This new permission/layout contract contradicts the unchanged Security and privacy section below: line 330 still says data is under <ASPIRE_HOME>/dashboard/<application-directory>, and line 332 says the Dashboard does not set Unix file modes. Update that section to describe the shared runs/resumes paths and clarify which directories are repaired to 0700 versus which root/file permissions remain the operator's responsibility.
On Unix, the shared `runs` and `resumes` directories are created with owner-only (`0700`) permissions. Resume application directories are also restricted to that mode before persistent data is accessed. Existing directories are repaired to that mode. On Windows, directories are created without Unix permission flags and use inherited ACLs.
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +142 to +148
File.WriteAllText(Path.Combine(CurrentWorkingDirectory, _applicationMarkerFileName), string.Empty);
_runLock = runLock;
}
catch
{
runLock.Dispose();
throw;
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants