Skip to content

Conversation

@ngholiza
Copy link
Collaborator

@ngholiza Navid Gholizadeh (ngholiza) commented Oct 16, 2026 •

Why

A signed-in user should see their own projects and data plus open (public) projects, and nothing beyond that. The data-access audit (ledger #90) found places in the web app and the AI assistant that showed more.

What changes

Area Before After
Uploads (list, attachments, process) Everyone in the same organization (nearly all "Purdue University") Only the uploader and admins; others get 404. The DB3 pilot keeps its shared queue
Data card Statistics over every project's runs Only runs the user can see (row-level security)
Dataset snapshots Any user (platform-wide counts) Admins only
Upload template No visibility check Same visibility as the equipment page; 404 otherwise
Equipment connection host/port/database Everyone who can see the equipment Owner, maintainers and admins (registered and legacy configs)
Equipment run counts / last data date Platform-wide Only runs the user can see (admins: platform-wide)
ML importance and proposals Could use the model trained on all projects That model only for an admin viewing all projects; everyone else gets a fit on their visible runs
ML response cache Kept results up to 6 h after access was lost Key includes the user's visible projects and a fingerprint of their visible runs
System/ingestion token check != hmac.compare_digest; empty expected token never matches
resolve_request_user Unused, trusted an unverified bearer value Removed
AI assistant Snapshots offered to everyone Snapshots admin-only; tool descriptions match what they return

Closed-loop and other system jobs are unchanged.

Second commit: Navid's decisions

Area Before After
Unit-experiment templates marked Private Visible to the owner's whole organization Owner; readers of a project that uses it; anyone who can read an experiment built on it
Execution queue Equipment owners saw requests for all of their organization's equipment Only equipment the user owns or is a trusted maintainer of (admins: all). Maintainers of any role now get the page

Changed in both the API and the row-level security functions (app_experiment_type_readable, app_manages_equipment). New GET /admin/execution-queue/access tells the web menu whether to show the queue.

Kept as is (decided OK): draft publication requests visible to readers of open projects; /ml/status showing the global model's size and metrics.

Tests

  • New api/tests/test_data_scoping.py: 26 tests; 15 of the first 18 fail on the old code.
  • Full API suite: 547 passed, 101 skipped. One failure, test_rcac_gateway, also fails on dev without these changes. 4 modules can't be collected locally (missing pymatgen/rcac_runner/PG env).
  • Web: type check, lint and 21 unit tests pass.
  • Codex review: first commit approved on round 2, second commit approved on round 2.
  • Postgres-backed tests (row-level security integration and others) run against a disposable local postgres:15: 94 passed, including new tests for private templates, owner/maintainer queue access and the ML cache signature query. The data card, uploads list and scoped equipment counts were also run on it. The template filter was also checked with row-level security bypassed.

Deploy

Run the migration Job first: add_row_level_security.sql changed, and the migration re-applies it (by checksum). Then rebuild dt-api (and the retrain cronjob image) and dt-web.

🤖 Generated with Claude Code

The audit found places that showed data beyond a user's own projects and
open projects. Each one is now limited:

- Uploads: only the uploader (and admins) can list, open, attach to or
  process an upload; same organization is no longer enough. The DB3
  pilot keeps its shared queue.
- Data card: statistics cover only the runs the user can see.
- Dataset snapshots: admins only (platform-wide counts).
- Upload template: checks equipment visibility, 404 otherwise.
- Equipment: connection host/port/database only for the owner,
  maintainers and admins; run counts cover only visible runs.
- ML: importance and proposals use the model trained on all projects only
  for an admin viewing all projects; the ML cache key now tracks the
  user's visible projects and runs, so lost access takes effect at once.
- System and ingestion tokens are compared in constant time, and an
  unused helper that trusted an unverified bearer value is removed.
- AI assistant: dataset snapshots tool is admin-only; tool descriptions
  say what each returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A unit-experiment template marked Private is no longer visible to the
  rest of its owner's organization. It stays readable to its owner, to
  readers of a project that uses it, and to anyone who can read an
  experiment built on it.
- The execution queue shows requests only for equipment the user owns or
  is a trusted maintainer of (admins: all). The same organization no
  longer counts. Maintainers of any role now get the queue page; the web
  menu asks the new /admin/execution-queue/access endpoint.
- The row-level security functions app_manages_equipment and
  app_experiment_type_readable change the same way; the migration job
  re-applies the script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation on GitHub.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant