Skip to content

Serve content files from the connetto-server executable - #28

Merged
LucaCappelletti94 merged 12 commits into
mainfrom
feat/r69-executable
Sep 17, 2026
Merged

LucaCappelletti94 merged 12 commits into
mainfrom
feat/r69-executable

Conversation

@LucaCappelletti94

@LucaCappelletti94 LucaCappelletti94 commented Sep 17, 2026

Copy link
Copy Markdown
Owner

The server binary can now serve the file side of R69. With the content feature the executable mints one ticket keypair at boot, mounts the four file routes on the auth listener inside its CORS layer, and sweeps retired content on a fixed cadence, so a single process holds the database, the sync listener and the file endpoint the deployment recipe promises.

The routes reuse the file-server crate unchanged, the signer and store are the same objects the feature tests drive directly, and the sweep is the crate's own retention pass on a timer. Configuration rides the existing CONNETTO_FILE_* environment names, and with the feature off the binary behaves exactly as before.

The browser-stack harness still needs the content publication wiring, and that waits on the schema branch, so it is deliberately not included here.

Summary by Sourcery

Enable the server executable to serve authenticated content files alongside its existing database, sync, and authentication services.

New Features:

  • Add optional content serving to the connetto-server executable, including ticket-based file routes mounted on the auth listener and scheduled content cleanup.
  • Support configuring content URLs, ticket keys, storage backends, retention, and sweep behavior through CONNETTO_CONTENT_* environment variables.
  • Allow object-store URLs with path prefixes to create isolated content storage namespaces.

Bug Fixes:

  • Normalize ticket base URLs by removing trailing slashes and reject bases containing queries or fragments to prevent unusable ticket URLs.

Enhancements:

  • Reuse the server's database connections and ticket signer across session content grants and mounted file routes, while preserving no-content behavior when unconfigured.
  • Add startup validation and preflight checks for content storage, keys, database tables, and deployment contract functions.
  • Extend content and server integration coverage for routing, CORS, configuration failures, ticket issuance, downloads, and sweeping.

Build:

  • Add the connetto-file-server dependency behind the default content feature and include ring for content key test support.

Deployment:

  • Integrate content storage, ticket signing, file routing, and retention sweeping into the server deployment configuration.

Documentation:

  • Document the CONNETTO_CONTENT_* environment variables and content-serving behavior in the executable documentation.

Tests:

  • Add unit, integration, and end-to-end tests covering content configuration, storage prefixes, ticket normalization, route mounting, startup validation, CORS, and live ticket round trips.

… under its CORS layer with one ticket keypair and sweep on a cadence

@sourcery-ai sourcery-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.

Sorry @LucaCappelletti94, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 4 days and 14 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Repository: LucaCappelletti94/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 71392f16-2065-4c1b-a548-c6127ec15cc7


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T04:56:19.448196Z 811a6e6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@sourcery-ai

sourcery-ai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

The executable now optionally serves R69 content files from the auth listener: when configured, startup parses the content backend, initializes a ticket keypair and file-server pools, runs schema preflight, mounts the four file routes under the existing CORS layer, wires ticket minting into sessions, and schedules retention sweeps; builds without content or without a content URL retain the previous no-file behavior.

Sequence diagram for configured content startup and file access

sequenceDiagram
    participant Server as connetto-server
    participant DB as Database
    participant Store as ContentStore
    participant FileServer as FileServer
    participant Client as BrowserClient

    Server->>Server: build_content()
    Server->>Store: open_store()
    Server->>Server: ticket_keypair()
    Server->>FileServer: serve(Config)
    FileServer->>DB: Schema preflight
    FileServer-->>Server: file_router
    Server->>Server: mount_on_auth_listener()
    Server->>Client: Auth listener with CORS and file routes
    Client->>Server: Content ticket request
    Server->>Server: ContentTicketSigner::mint()
    Server-->>Client: Ticket URL
    Client->>FileServer: File route request with ticket
    FileServer->>Store: Read or write chunks
    Store-->>FileServer: Content response
    FileServer-->>Client: File response
Loading

State diagram for content feature and configuration behavior

stateDiagram-v2
    [*] --> NoContent
    NoContent: ServerSigner::None
    NoContent: No file router

    [*] --> ContentDisabled
    ContentDisabled: Built without content feature
    ContentDisabled: Warn if CONNETTO_CONTENT_URL is set
    ContentDisabled: No file routes

    [*] --> ContentConfigured
    ContentConfigured: Parse store and keypair
    ContentConfigured: Run file-server preflight
    ContentConfigured: Mount routes under CORS
    ContentConfigured: Start retention sweep

    NoContent --> ContentConfigured: CONNETTO_CONTENT_URL set
    ContentDisabled --> ContentConfigured: Rebuild with content feature
Loading

File-Level Changes

Change Details Files
Adds configurable content-store URL support with prefix isolation for object-store backends.
  • Parse filesystem and object-store URLs into a unified store abstraction.
  • Apply URL paths as object-store prefixes and test sibling isolation.
crates/connetto-file-server/src/store/mod.rs
Cargo.lock
Integrates the file server into the executable behind a default-on content feature.
  • Read CONNETTO_CONTENT_* settings for URL, key, store, ticket limits, and sweep cadence.
  • Create persistent or ephemeral ticket signing keys and configure verifier/store handles.
  • Run file-server preflight during startup and mount its routes on the auth listener.
  • Keep no-content behavior available when the feature is disabled or the content URL is unset.
crates/connetto-server/Cargo.toml
crates/connetto-server/src/bin/connetto-server.rs
Connects content ticket minting and retention cleanup to the server runtime.
  • Use the startup-selected signer for session content ticket requests.
  • Spawn a non-fatal periodic sweep using the file server's retention pass.
  • Use dedicated admin and reader pools for file serving.
crates/connetto-server/src/bin/connetto-server.rs
Adds focused tests for routing, CORS, storage configuration, and ticket-key compatibility.
  • Verify unset deployments reject ticket minting and disabled builds warn without mounting routes.
  • Verify merged file routes share auth CORS behavior.
  • Verify configured and ephemeral keypairs mint tokens accepted by the matching public verifier.
  • Verify store-spec parsing and object-store prefix separation.
crates/connetto-server/src/bin/connetto-server.rs
crates/connetto-file-server/src/store/mod.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 811a6e6a90

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Some(path) => Some(std::fs::read(&path).with_context(|| format!("reading {path}"))?),
None => None,
};
let (signer, public) = ticket_keypair(der.as_deref(), base_url.clone(), ttl, read_ceiling)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize the configured ticket base before minting

When CONNETTO_CONTENT_URL ends with / or contains a path/query, it passes URL validation and is handed unchanged to TicketSigner, whose mint implementation appends /files/... textually. For example, the natural value https://files.example/ yields https://files.example//files/..., while the merged router only serves /files/..., so every minted grant fails unless an intermediary happens to normalize it. Strip/reject unsupported URL components before constructing the signer.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in b00a296 and a93220d. The signer now normalizes the base in both constructors, trailing slashes are trimmed and a base carrying a query or a fragment is refused with a new TicketError::AmbiguousBase naming the base, and connetto-server refuses CONNETTO_CONTENT_URL values with a query or fragment before the signer is built.

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@sonarqubecloud

Copy link
Copy Markdown

@LucaCappelletti94
LucaCappelletti94 merged commit 6ac98e2 into main Sep 17, 2026
54 of 55 checks passed
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.

1 participant