Skip to content

Fix HTTPS capture uploads and document token setup - #145

Merged
bjones1 merged 4 commits into
bjones1:mainfrom
jspahn80134:main
Aug 28, 2026
Merged

Fix HTTPS capture uploads and document token setup#145
bjones1 merged 4 commits into
bjones1:mainfrom
jspahn80134:main

Conversation

@jspahn80134

@jspahn80134 jspahn80134 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes the CodeChat capture client path so token validation and event upload work against the AWS-hosted CaptureWebService HTTPS endpoint, then documents the updated capture setup and behavior for students, extension users, and maintainers.

What Changed

  • Enables HTTPS support for the Rust minreq HTTP client used by the bundled CodeChat server.

    • Without this feature, the extension reports the capture service as unavailable before the request ever reaches the AWS service.
    • The fix updates server/Cargo.toml and the corresponding lockfiles used by the server and VS Code extension build.
  • Adds a student-facing HTML setup guide at docs/capture-token-setup-guide.html.

    • Explains how to request a capture token through the registration portal.
    • Explains how to paste the token into the CodeChat VS Code extension.
    • Explains how to validate the token, give consent, turn on recording, and interpret capture status states.
    • Keeps internal-only debugging tools out of the student instructions.
    • Avoids exposing the capture service base URL in the student guide.
    • Opens the registration portal link in a separate browser tab/window.
  • Updates documentation in the main README and VS Code extension README.

    • Links to the student setup guide.
    • Describes the capture token flow through VS Code SecretStorage.
    • Clarifies that CodeChat no longer connects directly to the capture database.
    • Clarifies that capture events are sent only through CaptureWebService using a portal-issued bearer token.
    • Notes that developer builds must keep HTTPS support enabled for capture service access.
  • Updates implementation documentation.

    • Documents the AWS capture path: VS Code extension -> local CodeChat server -> CaptureWebService HTTPS API -> API Gateway/Lambda -> SQS -> writer Lambda -> capture.events.
    • Documents local spool behavior, token/service identity matching, HTTPS requirements, and the database boundary.
    • Records the event families verified during integration testing.
  • Updates CI/test maintenance.

    • Updates the changelog with the HTTPS capture fix, documentation additions, and CI cargo-audit follow-up.
    • Hardens the long-doc-block browser regression test by waiting for the visible TinyMCE editor to become interactable before typing.

CI Follow-Up

The first PR run failed in the Ubuntu Run tests job during cargo audit. I corrected that failure in commit f494070.

  • Updated all audited Rust lockfiles to remove the vulnerable webbrowser 1.2.1 path by resolving to webbrowser 1.2.4.
  • Updated the minify-html git dependency resolution from b5cce195 to 1519cf31, which removes the vulnerable rkyv 0.7.46 dependency chain from the server, VS Code extension, and standalone lockfiles.
  • Updated actix-http lockfile resolution from 3.13.1 to 3.13.3 everywhere it is audited.
  • Added a narrowly scoped cargo audit --ignore RUSTSEC-2026-0258 in builder/src/main.rs for the remaining h2 advisory.
    • The remaining h2 0.3.27 dependency is transitive through the current compatible actix-http release.
    • The ignore is documented beside the builder command and should be removed once actix-http exposes an h2 0.4.16+ dependency path.
    • No broad audit suppression was added; the ignore applies only to RUSTSEC-2026-0258.

The next PR run passed Ubuntu, then failed on macOS in overall_5::test_edit_preserves_cursor_scroll_in_large_doc_block with ChromeDriver ElementNotInteractable while typing into TinyMCE. I corrected that failure in commit ce98afb.

  • The test was already clicking a paragraph, then immediately querying #TinyMCE-inst and sending keys.
  • On macOS ChromeDriver, the TinyMCE element can exist before it is ready for input.
  • The test now queries the visible TinyMCE editor with .CodeChat-CodeMirror #TinyMCE-inst:not(.CodeChat-doc-hidden) and waits for wait_until().clickable() before sending keys.
  • This matches the interaction pattern already used by another overall browser test in the suite.

Security / Privacy Notes

  • The clear capture token is never written to repository files, workspace settings, or JSON configuration.
  • The VS Code extension stores the token only in VS Code SecretStorage.
  • Participant/instance identity comes from the CaptureWebService token-status response, not from token text supplied by the client.
  • Capture events use the CaptureWebService boundary; CodeChat does not read or store database credentials.
  • The student setup guide does not include internal service-base URL details or debugging-tool references.

Validation Performed

  • Ran npm run compile from extensions/VSCode.

    • Rust build completed.
    • 13 Rust export-binding tests passed.
    • TypeScript tsc -noEmit completed through the extension build.
    • The first compile attempt failed only because a running Extension Development Host had the native .node file loaded; after closing that host, the compile passed cleanly.
  • Reproduced the failed CI area locally.

    • Ran the server cargo audit path with the scoped RUSTSEC-2026-0258 ignore.
    • Ran the audited lockfile checks for builder, extensions/VSCode, extensions/standalone, and test_utils with the same scoped ignore.
    • Confirmed rkyv is no longer present in the VS Code extension dependency tree.
    • Confirmed webbrowser resolves to 1.2.4 in the standalone/extension dependency paths.
  • Ran builder validation locally.

    • cargo fmt --manifest-path builder/Cargo.toml --all --check passed.
    • cargo check --manifest-path builder/Cargo.toml passed.
    • cargo run --manifest-path builder/Cargo.toml flint passed after installing the same dev helper and JS dependencies that CI installs through ./bt install --dev.
    • flint still reports existing allowed/non-fatal warnings: the Rust chacha20 yank warning, the builder proc-macro-error2 unmaintained warning, and client-side pnpm audit advisories. These are not the failing cargo audit vulnerabilities from the PR run.
  • Validated the macOS test hardening locally as far as this Windows workstation allows.

    • cargo fmt --manifest-path server/Cargo.toml --all --check passed after rustfmt formatting.
    • cargo check --manifest-path server/Cargo.toml --tests passed.
    • The specific browser test compiles locally, but cannot execute here because this host does not have a Chrome install detectable by thirtyfour/ChromeDriver. The GitHub macOS runner is the authoritative execution path for that browser-specific failure.
  • Verified capture service behavior through the live AWS dev/test deployment.

    • Token status returned capture_enabled=true for a valid portal-issued token.
    • Bad bearer token was rejected with 403.
    • Malformed event payload was rejected with 400 and did not insert rows.
  • Verified the actual CodeChat extension capture path.

    • Turned capture on in the VS Code Extension Development Host.
    • Started the CodeChat Editor.
    • Created, edited, and saved a Markdown file.
    • Inserted a reflection prompt through the contributed CodeChat command.
    • Confirmed local capture status reached Capture: Remote.
    • Confirmed the local capture spool had no pending backlog.
  • Verified resulting rows in the AWS PostgreSQL capture database.

    • Extension/user-flow rows landed for session_start, write_doc, reflection_prompt_inserted, and save.
    • A synthetic public-API batch also exercised representative optional event types: write_code, switch_pane, doc_session, compile, compile_end, run, run_end, session_end, capture_settings_changed, task_start, task_submit, debug_task_start, debug_task_submit, handoff_start, and handoff_end.

Files Changed

  • server/Cargo.toml
  • server/Cargo.lock
  • server/tests/overall/overall_5.rs
  • extensions/VSCode/Cargo.lock
  • extensions/standalone/Cargo.lock
  • builder/src/main.rs
  • README.md
  • extensions/VSCode/README.md
  • docs/implementation.md
  • docs/capture-token-setup-guide.html
  • CHANGELOG.md

Compile the Rust capture HTTP client with minreq HTTPS support so token validation and event uploads can reach the AWS CaptureWebService endpoint.

Add the student-facing capture token setup guide and link it from the main README and VS Code extension README.

Document the SecretStorage token flow, local spool behavior, AWS ingestion path, and verified capture event coverage in the implementation notes and changelog.
Update Rust dependency locks to remove vulnerable webbrowser and rkyv paths reported by cargo-audit.

Document and apply a scoped temporary ignore for RUSTSEC-2026-0258 because h2 0.3.x is still pulled through the latest compatible actix-http release.
@bjones1

bjones1 commented Aug 28, 2026

Copy link
Copy Markdown
Owner

At first glance, this looks good! Thanks for updating docs, not just code.

Wait for the visible TinyMCE editor to become interactable before typing in the long-doc-block scroll preservation regression test.

This addresses the macOS ChromeDriver element-not-interactable failure reported by the PR check.
@bjones1

bjones1 commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Excerpts of a Claude review:

1. Student-facing guide points at a plain-HTTP bare IP

capture-token-setup-guide.html:310 tells students to visit http://3.146.138.182/capture-registration/ and submit their MSU email address and class code.

This undercuts the security posture the same PR documents. capture.rs:397 hard-rejects non-HTTPS service URLs, and README/implementation.md both stress "token-bearing requests require HTTPS" — then the guide trains students that the legitimate way to obtain that token is an unauthenticated form on an unencrypted bare IP. Anyone on-path at a coffee shop or on campus wifi can serve a lookalike page and harvest addresses; the guide even helpfully publishes the cccap_v1_ token prefix and the fact that the class code is ECE9990, which is most of what a convincing phish needs.

Separately, a raw EC2 public IP checked into the repo will rot the first time that instance is replaced. Recommend a DNS name with a real certificate before this goes to students, even for the dev/test deployment.

2. https feature ignores the OS trust store

minreq's https feature aliases to https-rustls → rustls + webpki-roots (bundled Mozilla roots). It does not consult the platform certificate store. On a university or corporate network doing TLS inspection, every capture request fails handshake — surfacing as Capture: Service unavailable, precisely the symptom this PR set out to eliminate, and the guide's advice for that row ("update to the current CodeChat build") won't help.

https-rustls-probe uses rustls-platform-verifier instead, and that crate is already in server/Cargo.lock on main (something else pulls it in), so the swap costs essentially nothing in build weight:

minreq = { version = "3", features = ["https-rustls-probe"] }

Related: the proxy feature is off, so HTTPS_PROXY/HTTP_PROXY are ignored. If any target network requires an egress proxy, uploads will fail with no diagnostic. Worth deciding deliberately rather than by default.

3. Nothing guards against this regression returning

Every HTTPS-related test in capture.rs is URL-parsing only (lines 1676, 2168–2332). Drop the feature again and cargo test still passes — the failure only shows up as a runtime status change in a deployed extension. A cheap offline guard:

#[test]
fn minreq_https_feature_is_enabled() {
    // Connection to port 1 is refused instantly; we only care which error we get.
    let err = minreq::get("https://127.0.0.1:1/").with_timeout(1).send().unwrap_err();
    assert!(!matches!(err, minreq::Error::HttpsFeatureNotEnabled), "{err}");
}

(HttpsFeatureNotEnabled confirmed present in minreq 3.0.0's error.rs.)

3. Doc nits

  • Log example case. capture-token-setup-guide.html:427 shows capture token status: accepted …, but captureTokenStatusLabel returns "Accepted" (extension.ts:1134), so the real line is capture token status: Accepted …. Trivial, but the rest of the doc is exact enough that a student may take it literally.
  • Missing states. The status table covers Remote/Uploading/Queued/Starting; reachable-but-undocumented are Capture: Waiting (server not running — a likely first-run state, see extension.ts:1344), Capture: Off, and Capture: Error.
  • Schema leak. line 442 names capture_admin.instances.token_hash in a student-facing doc. Line 443 already says the same thing in plain language; the internal table name adds nothing for the audience.

Switch the capture HTTP client from minreq's bundled-root HTTPS feature to https-rustls-probe plus proxy support so AWS capture requests use platform certificate verification and standard proxy environment variables.

Add a unit regression guard that fails if minreq is built without HTTPS support, keeping token validation and upload failures from silently returning as service-unavailable at runtime.

Tighten the student capture setup guide by removing the insecure temporary portal URL, public class code, token-format hint, and internal schema detail, then document the reachable Waiting, Off, and Error status states and fix the token-status log casing.

Update README, VS Code README, implementation notes, changelog, and all tracked Cargo lockfiles to reflect the reviewed transport behavior.
@jspahn80134

Copy link
Copy Markdown
Contributor Author

Workoff for Bryan/Claude review comments:

  • Replaced minreq's bundled-root https feature with https-rustls-probe plus proxy, so capture HTTPS calls use platform certificate verification and honor standard proxy environment variables.
  • Added capture::tests::minreq_https_feature_is_enabled so a future build without HTTPS support fails in tests instead of surfacing only as runtime Capture: Service unavailable.
  • Updated the student setup guide to remove the raw EC2 HTTP portal URL, public class code, token prefix hint, and internal DB schema/table detail.
  • Updated the guide status reference for the reachable Capture: Waiting, Capture: Off, and Capture: Error states, and fixed the token-status log example casing to Accepted.
  • Updated README, VS Code README, implementation notes, changelog, and lockfiles to document the new transport behavior.

Regression run before pushing:

  • cargo tree --manifest-path server/Cargo.toml -e features -i minreq confirms https-rustls-probe and proxy are active.
  • cargo test --manifest-path server/Cargo.toml minreq_https_feature_is_enabled passed.
  • cargo test --manifest-path server/Cargo.toml capture passed: 25 capture-related tests.
  • npm run compile in extensions/VSCode passed.
  • cargo run --manifest-path builder/Cargo.toml flint exited 0. It still prints the repository's existing production-audit advisories for client packages, while the VS Code package audit remains clean.
  • Live AWS regression passed against the deployed dev API: health 200, invalid token rejected with 403, valid token status 200/capture-enabled, four representative events (session_start, write_doc, reflection_prompt_inserted, save) accepted with 202, duplicate submit accepted idempotently, and PostgreSQL capture.events contained exactly one row for each submitted event. The matching capture_admin participant/instance metadata was active/consented with identity metadata present.

@bjones1
bjones1 merged commit 5d41a71 into bjones1:main Aug 28, 2026
8 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.

2 participants