Skip to content

Develop - #204

Merged
alex-struk merged 4 commits into
mainfrom
develop
Jun 24, 2026
Merged

Develop#204
alex-struk merged 4 commits into
mainfrom
develop

Conversation

@alex-struk

Copy link
Copy Markdown
Collaborator

Summary

AI-###

Changes

Testing

Checklist

By submitting this pull request, I acknowledge that I have attempted to meet the following:

  • a self-review of my code
  • commented code particularly in hard-to-understand areas
  • corresponding changes to the documentation where required
  • changes tested to the best of my ability
  • no new errors or non-functional code

alex-struk and others added 4 commits June 23, 2026 15:01
…ence paths

Closes six cross-tenant (group) isolation gaps found in the develop-branch
authorization audit. Each affected endpoint was reachable by an API key (or a
JWT member of another group) and either loaded/mutated a resource by its own
global id, or accepted a reference to another entity, without verifying the
owning group. All fixes treat a foreign-group reference as not-found so resource
existence is not leaked across groups.

- Workflow config IDOR (upload): WorkflowService.resolveWorkflowVersionId and
  getModelIdDefault now scope WorkflowVersion/Lineage lookups to the caller's
  group via the owning lineage, so a foreign workflow config cannot be resolved,
  executed, or disclosed at document upload.
- Benchmark definition references: createDefinition/updateDefinition require the
  datasetVersionId and workflowVersionId to belong to the project's group;
  startRun requires candidateWorkflowVersionId's lineage to be in the project's
  group - preventing pinning/executing another group's dataset/workflow and
  exfiltrating ground truth.
- Benchmark candidate writes: applyToBaseWorkflow/promoteCandidateWorkflow verify
  the candidate AND the base lineage being written into belong to the project's
  group, preventing writes into another group's workflow lineage.
- Confusion profiles: findById/update/delete are scoped by group_id so path-group
  membership no longer grants access to another group's profile by id.
- Template-model children: field update/delete and label delete are scoped to the
  owning template model (and labeling document), closing child-row IDOR.
- GET /api/models: trained-model listing is filtered to the caller's groups via
  getIdentityGroupIds; prebuilt models remain global.

Adds/updates unit tests (including explicit cross-group negative cases) for every
change and documents the pattern in docs-md/GROUP_RESOURCE_AUTHORIZATION.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(security): enforce cross-group isolation on resource-id and reference paths
Opt-in, per-workflow ephemeral policy. When a workflow declares
metadata.ephemeral, documents it processes are purged once they reach a
terminal status — blob files and/or the Temporal execution record are
deleted per the policy — while the OCR result in Postgres is retained.

- metadata.ephemeral: true | { files, temporalRecord } for per-target control
- EphemeralDocumentCleanupService: @Cron(EVERY_MINUTE) janitor, gated solely
  by workflow config (no global flag, no per-group setting)
- TemporalClientService.deleteWorkflowExecution (idempotent on NOT_FOUND)
- documents.purged_at marker + partial index documents_purge_scan_idx
  (WHERE purged_at IS NULL) to keep the janitor scan cheap at high volume
- docs-md/ephemeral-document-cleanup.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat: ephemeral-document cleanup (per-workflow blob + Temporal purge)
@alex-struk
alex-struk merged commit cd5cf89 into main Jun 24, 2026
29 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