Skip to content

fix: download dataset exports with the caller's credentials (ENG-9091) - #71

Merged
sontek merged 16 commits into
mainfrom
john/fix/export-download-auth
Oct 19, 2026
Merged

sontek merged 16 commits into
mainfrom
john/fix/export-download-auth

Conversation

@sontek

@sontek sontek commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

ENG-9091

what

Dataset export tools now download a finished export with the caller's token when the server writes files. When it does not, they return the link with a note to open it in a signed-in browser. An expired export, or an export ID the caller cannot see, gets a clear error instead of a dead link or a crash.

why

The platform now requires the creator's login to download an export, so fetching the link without credentials stops working. The download decision lives in the tools layer, as it does for AssetDB results, so the client only fetches.

testing

Unit tests cover local, hosted, expired, missing, refused and interrupted downloads. I also ran both tools against a local platform stack that has the authenticated download route.

docs

Updated the dataset export guide, README, CLAUDE.md and NEWS.

@sontek
sontek requested a review from a team as a code owner October 7, 2026 19:21

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 10 files

Architecture diagram
sequenceDiagram
    participant Agent as Agent / Client
    participant MCP as MCP Server (FastMCP)
    participant Tool as Platform Tools Layer
    participant Client as PlatformClient (GraphQL)
    participant Platform as Stacklet Platform API
    participant FS as Downloads Filesystem
    participant Settings as Settings / Env Vars

    Note over Agent,FS: Dataset Export Download Flow (ENG-9091)

    Agent->>MCP: Call platform_dataset_export / platform_dataset_lookup
    MCP->>Tool: Invoke tool function
    Tool->>Client: start_export() / wait_for_export()

    Client->>Platform: POST /graphql (start/query export)
    Platform-->>Client: Export ID
    Client->>Platform: Poll GraphQL query (getExport)
    Platform-->>Client: ConnectionExport (status, download_url, available_until)

    Tool->>Tool: _deliver() - evaluate export state

    alt Export not completed
        Tool-->>MCP: Return status (no file/link)
    else Export completed and has download_url
        Tool->>Tool: Check available_until vs now

        alt Export expired (available_until <= now)
            Tool->>Tool: Set download_note = "expired" 
            Tool-->>MCP: Return with download_note (no full_results_saved_to)
            MCP-->>Agent: Result with download_note

        else Export not expired
            Tool->>Settings: Check downloads_enabled flag

            alt downloads_enabled = False (hosted deployment)
                Tool->>Tool: Set download_note = "open link in signed-in browser"
                Tool-->>MCP: Return with download_note
                MCP-->>Agent: Result with download_note

            else downloads_enabled = True (local deployment)
                Tool->>Client: download_export(dataset_id, download_url)
                Client->>Platform: GET download_url (with caller's credentials/token)
                
                alt Download successful
                    Platform-->>Client: Stream file bytes
                    Client->>FS: _save_stream() - write export_*.csv to downloads_path
                    FS-->>Client: Local file path
                    Client-->>Tool: full_results_saved_to path
                    Tool-->>MCP: Return with full_results_saved_to
                    MCP-->>Agent: Result with full_results_saved_to + local file
                
                else Download fails (HTTP error / connection drop)
                    Platform-->>Client: Error response / stream interruption
                    Client->>FS: Clean up partial file (if created)
                    Client-->>Tool: Raise AnnotatedError
                    Tool-->>MCP: Error (problem, likely_cause, next_steps)
                    MCP-->>Agent: Error message with export ID + download_url for manual retry
                end
            end
        end
    else Export not found or ID invalid
        Client->>Platform: GraphQL query returns null node
        Platform-->>Client: null node
        Client-->>Tool: Raise AnnotatedError "Dataset export not found"
        Tool-->>MCP: Error (wrong ID or belongs to another user)
        MCP-->>Agent: Error message with next_steps
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread stacklet/mcp/platform/graphql.py
Comment thread stacklet/mcp/platform/tools.py Outdated
Comment thread stacklet/mcp/platform/tools.py
Comment thread stacklet/mcp/platform/graphql.py Outdated
@sontek
sontek merged commit a0247cf into main Oct 19, 2026
6 checks passed
@sontek
sontek deleted the john/fix/export-download-auth branch October 19, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants