Skip to content

fix(file-doc): stop the permission resend loop and restore the 10 MB proxy body limit - #9057

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix/live-doc-permission-loop-and-proxy-limit
Oct 15, 2026
Merged

waleedlatif1 merged 3 commits into
stagingfrom
fix/live-doc-permission-loop-and-proxy-limit

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Changes only flag-gated Project file paths (behind the projects flag).

  • Project file reads and writes that do not charge storage hold the Project lock shared; storage-charging operations (create, update_content, upload_complete, versions.revert, extract_archive) declare chargesStorage and take it exclusively up front, so a shared hold is never upgraded. Lifecycle, payer transfer, retention, and account deletion stay exclusive and still exclude every file operation.
  • The Project file authorizer holds the organization's permission-group lock shared (acquirePermissionGroupOrgReadLock): group writes, workspace creation, and OAuth refresh still wait for it and the capability decision stays current through commit, but file operations no longer serialize on it. The 5s lock_timeout now bounds only the acquisition and the caller's setting is restored.
  • Project storage accounting locks the payer row last and only for a non-zero delta (the global order: Project → owner row → directory → files → payer); the Project row lock taken at prepare keeps the payer identity fixed. Zero-delta writes read usage unlocked.
  • readProjectFileContent and version content reads drop an unused preflight transaction (prepareFromSnapshot); their snapshot use case authorizes, and the final transaction still revalidates after the storage read.
  • Collaborative-document seed/persist retry only on moved revisions (ProjectFileRevisionConflictError) or cached-history conflicts; Project lock timeouts and lifecycle conflicts surface immediately instead of being retried and reported as a document conflict. Persist reads at most the largest editable file size.
  • Archive/restore find files with cached document state in one query instead of locking and decoding every file, and post-commit retirements run at most 8 at a time.
  • Project file id/root-name reference lookups no longer load the whole folder tree.
  • Removes the blanket knip ignores over the Project file contracts: unused aliases are deleted or un-exported; the four files still holding exports consumed only by stacked PRs keep a per-file ignore naming them.

Expected conflicts for the stacked Project file PRs: knip.jsonc (#9018 adds entries; its new project-file*.ts contract files lose the glob ignore), projects/files/application/authorization.ts (#9018 exports helpers), billing/storage/tracking.ts and projects/membership.ts (#9034).

Type of Change

  • Bug fix

Testing

  • New integration checks in projects/files/__integration__/authorization.integration.ts: concurrent reads and a folder create proceed while a read holds the Project, lock_timeout is restored, and exclusive Project and permission-group holders still wait; a storage-charging write still excludes shared holders
  • New projects/files/application/documents.test.ts: lock conflicts are surfaced, revision conflicts still retry (verified red on the old predicate)
  • biome on changed files; type-check, audits, and integration suites run in CI

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 15, 2026 12:09am UTC

Request Review

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

Copy link
Copy Markdown
Contributor

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 26 files

Turn on auto-fix | Re-trigger cubic

Comment thread scripts/generate-cli-docs.ts
@greptile-apps

greptile-apps Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] This PR appears safe to merge; no actionable new issues were found.

Summary

This PR stops repeated document permission messages and update resends. It restores the default 10 MiB proxy limit while letting Project document snapshots bypass that buffer.

  • The relay sends write-permission updates only when access changes.
  • Workspace snapshots can persist even when the stream has no author.
  • Read-only members can view files locally after a join denial.
  • Snapshot persists bypass the 10 MiB proxy body limit.
  • V2 file downloads keep the file's stored name and content type.
  • V2 version lists use the shared file-version serializer.
  • Project-file tools stay out of CLI and MCP listings.

No actionable new issues were found in the changes since the previous review. No previous review threads were supplied.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Sweep[Permission sweep] --> Publisher[Shared permission publisher]
  Frame[Incoming document frame] --> Publisher
  Publisher --> Changed{Write access changed?}
  Changed -->|Yes| Notify[Notify client]
  Changed -->|No| Skip[Send nothing]
Loading

Reviews (3) · Last reviewed commit: "fix(file-doc): reschedule an unattribute..." · Reviewed by Greptile

…eep capability through the per-socket de-dup
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 29 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 30 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit 3ba393d into staging Oct 15, 2026
53 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/live-doc-permission-loop-and-proxy-limit branch October 15, 2026 00:19
mzxchandra added a commit that referenced this pull request Oct 15, 2026
…tory

#9057 hid the projects group from --help and `sim cli` search until
launch, and the inventory printer dropped every hidden command, so the
Mothership worker lost the Project file commands it routes --project to.

List a hidden top-level group that is only unpublished, marked
`unpublished`, so the worker can route to it once Sim enables Projects
for a turn; other hidden commands stay out, and --help is unchanged.
waleedlatif1 added a commit that referenced this pull request Oct 16, 2026
* feat(files): restore Project file browser and Mothership integration

* fix(files): resolve CI audits and test types after restacking on staging

- Keep prepareProjectsForAccountDeletion returning the Project IDs to delete.
  The object return added an unused storageCleanupEventIds field; the
  durable cleanup outbox already processes those events, so restore the
  staging contract and its stronger integration assertions.
- Exempt lib/mothership/generated from the relative-import convention.
  contracts:sync copies those wire contracts verbatim and byte-checks them,
  so their sibling imports must stay relative; drop their baseline rows.
- Re-record the files page module-count baseline for the Project browser.
- Type the test fixtures that regressed, including a queue-recovery
  fixture that persisted the invalid completion status 'success'.

* fix(files): gate Project sandbox callbacks like workspace callbacks

Staging now holds resource-delegated Chat principals to content
admission, so a Project callback read with no gate was refused and the
sandbox got a 503. Run Project callbacks under the same workbench
session gate as workspace callbacks (the gate's workspace is optional,
since Projects have none) and share the withheld-result handling.

The Project CLI read suite now runs reads under the tool executor's
registry gate, as Chat does.

* fix(projects): keep Project chat tabs behind the rollout flag

The chat resources API stored a Project-owned tab without checking the
projects flag. Refuse new Project tabs while Projects are off; removing
or reordering stored tabs stays possible so they can be cleaned up.

Also drop the projects flag check in list_user_projects that could never
run (listProjects already refuses while the flag is off) and the content
delivery barrel export left unused by the shared sandbox delivery helper.

* refactor(files): drop the Project files UI from the Chat transport PR

The Project files UI will be built for the project-first redesign, so
this PR keeps only the backend and Chat transport behind the projects
flag. Restore the workspace Files page, file viewer, Chat resource
panel, add-resource and mention entries, and their client query hooks
and owner adapters to staging. The previous tip is tagged
project-files-ui-seed for that UI work.

Kept: the shared ChatContext wire type (Project contexts and file owners
reach the Chat server) and its exhaustive kind registry entry.

Also drop the UI-only browser constants and response types nothing uses
now, restore the files page module-count baseline, and type the
use-chat fixtures that returned with the staging test.

* fix(files): redact Project file text like workspace file text

Project grep and text reads admitted every Project artifact as opaque
bytes, so any file carrying a secret was refused to Chat instead of
having the secret masked, unlike the same file in a workspace.

Share one text extraction core between workspace text reads and private
file observation: parse, redact before a line window can cut a secret,
then slice. Project text reads now go through readProjectFileText, which
admits the source and every rendered input as complete text and returns
text only. The complete artifact read stays private to that use case, so
bytes never leave under a complete label; readProjectFileArtifact keeps
admitting opaque bytes, and visual reads of a secret still refuse.

* fix(sim-cli): keep unpublished groups in the Mothership command inventory

#9057 hid the projects group from --help and `sim cli` search until
launch, and the inventory printer dropped every hidden command, so the
Mothership worker lost the Project file commands it routes --project to.

List a hidden top-level group that is only unpublished, marked
`unpublished`, so the worker can route to it once Sim enables Projects
for a turn; other hidden commands stay out, and --help is unchanged.

* fix(files): address Cubic and Greptile review findings

Workspace regressions while Projects are off:
- Sandbox file copies between workspaces keep the workspace route when
  the lease has not negotiated the file-owner protocol; only pairs that
  name a Project owner need it.
- Chat upload contexts keep their uploads/ path in the workspace owner
  adapter.

Project transport:
- Project CLI requests refuse mutations during benchmark reference
  generation, as workspace requests do.
- Project grep defaults an omitted scope to files.
- Project files with unrecorded or empty exact provenance are readable
  when the caller holds a registry; a missing registry is still refused.

Mothership inventory:
- Unpublished Project commands carry response shapes from the
  launch-ready Project OpenAPI definitions.
- An operation whose delegated services exclude Chat no longer mints a
  Chat principal, so the refused-route list now matches runtime for
  Project file version history.

* fix(files): address the second review round

- Project `files read` returns binary metadata for undecodable files:
  the text route checked `workspaceFileTextFormat` against null, but it
  returns undefined.
- Workspace file resources keep `workspaceId` beside their new workspace
  owner, so current browsers can open and close those tabs in
  organization chats; the resource key is unchanged.
- The Project tab flag gate is covered against the database instead of
  through mocked collaborators.

* fix(files): choose a generated Project document's read by its rendered type

A generated PDF is stored under its source type (text/x-python-pdf), so
the Project text route treated `files read report.pdf` as text instead
of the default visual representation. Share the workspace reader's type
selection as observedMediaType: a generated document is read as the
type its name promises, otherwise as its effective stored type.

* fix(mothership): close review gaps in Project file transport

- Dispatch CLI services before file-owner adapters, so a service that
  carries a file owner gets the services validation instead of a bridge
  error. The unreachable Project-side service check is removed.
- Check caller-chosen names on Project file renames and folder create
  and update with the same secret-provenance gate as create and upload,
  including workbench history for sandbox callbacks.
- Move first-message file panel resolution into resolveFileAttachment
  and replace the mock-only post test with a database-backed check of
  the saved tab.

* fix(mothership): match chat tabs within the chat's workspace

- The chat resource store now keys tabs with the chat's workspace as the
  fallback scope, so an unscoped tab and the same tab addressed by that
  workspace merge instead of duplicating. Upsert, remove and reorder all
  use the same identity.
- Project file renames and folder writes recheck cancellation after the
  name check and never forward a cancelled write.
- Leave the .claude and .cursor import rules to staging, whose source
  conventions check now exempts generated contract copies itself.

* fix(mothership): bound Project name checks and keep equal owners

- Parse Project file renames and folder writes with their route contracts
  under the inline body limit before the name check, so an oversized body
  is refused instead of buffered. Only those routes copy the request.
- Treat an equal file owner as unchanged when merging chat tabs, so a
  repeated upsert stays a no-op.

* fix(project-files): harden owner hints, grep provenance, and tab identity

- Restore info/warn levels for stale or forbidden tab attachments and skip an unresolvable target instead of throwing
- Make Project owner hints best-effort so a failed lookup never fails the turn; document that a worker rollback needs projects off first
- Cache the worker file-owner protocol probe per base URL (lru-cache, 30s, success only)
- Answer an invalid copy body on an unnegotiated lease from the workspace route (v2 400) instead of a 403
- One tab-key function on server and client, keyed with the chat workspace on both sides
- Project grep withholds a file without provenance instead of failing the search or latching the registry, and stops listing once the file budget is full
- Bound copy effects: one copied file opens a tab, bulk and folder copies refresh the destination owner; org copies carry the destination workspace
- Bound list_user_projects capability fan-out
- Refuse unextractable or oversized Project text reads before download, with the text-extraction size message
- Share the create-file input mapper, the resource authoring version, and isProjectsEnabled

* fix(project-files): refuse secret-bearing raw Project downloads without a workbench tracker

* test(project-files): pin refusals and cover live owner-hint, tab-key and log-level paths

* refactor(project-files): move owner routing and admission behind the file-owner adapter

- copilot-request carries one opaque resource grant per request; the Project file
  and file-copy grants are minted next to their adapters, so the shared route layer
  no longer imports Project or copy policy
- One projectFileDelegationScope for the verifier, the Copilot adapter and the
  request grant; admitsCopilotResourceDelegation shared by the adapter and the grant
- Private v2 transports derive route patterns from their contracts
  (v2RoutePattern / isV2ContractRoute / tryMatchV2Route), including the name-write
  lookup, so a renamed route can no longer skip interception silently
- Project upload and write transports share their route prologue, cancellation
  check and failure envelope
- One forwarded-header strip list and one callback context for sandbox callbacks;
  SandboxResourceScope is exported instead of re-derived
- isOwnerScopedFile replaces adapter field comparisons; the adapter field is
  renamed invocationScope so it no longer reads like Principal.resourceScope
- authoringInvocation picks a turn's chat-or-workspace invocation in one place

* refactor(mothership): share chat tab keys, CLI session setup, and file read helpers

- chatResourceKeyFor binds the tab key to one chat's workspace for the store,
  reorder, stream handler and use-chat; resource removal looks keys up in a Set
- isFileResourceType names the file/filefolder check; shared owner refinement in
  the resource contracts
- prepareCliSession gives every CLI invocation its endpoint, workbench session,
  file provenance and effect sink
- Text-extraction refusals, the default-visual media check and MIME
  normalization are shared rather than copied
- Grep page cap and listing note are shared; a corpus states its own scope
  refusal instead of the engine naming Projects
- resource-effects builds an owned file path once and shares the owner refresh

* perf(project-files): skip the folder tree for grep reads and check hint gates before the flag

- Project grep reads ask the artifact read not to load the owner's whole folder
  tree per file; grep never reads file.folderPath
- File-owner hints run the route, mode and admission checks before awaiting the
  projects flag
- Project text reads reuse the workspace text-extraction refusals; Project grep
  uses the shared page cap and states its own scope refusal

* test(mothership): drive stale-tab and owner-hint failures through the real boundary

* test(project-files): pin upload cancellation during provenance and new-chat tab order

* fix(project-files): recheck cancellation before completing a workbench upload

Provenance resolution can outlast the invocation; completion now rechecks both
signals before it registers the file, as the create path does.

* fix(mothership): persist new-chat tabs in attachment order

Attachments resolve concurrently, so tabs were persisted in completion order.
Each authorized tab now keeps its attachment index.

* fix(mothership): store the recovery authoring marker only while Projects are on

Earlier builds parse recovery config strictly and skip recovery on an unknown
key. Only Project authoring reads the marker, so flag-off turns no longer
write it and stay recoverable across a rollback.

* fix(mothership): tag an unlabeled file selection as a bare mention

* test(project-files): give new suites their own reports and drop an unreachable adapter case

* refactor(files): return readSourceBuffer's TSDoc to its function

---------

Co-authored-by: Waleed Latif <waleed@sim.ai>
Co-authored-by: Waleed Latif <walif6@gmail.com>

This branch was previously deployed

1 inactive deployment
Preview — 1eb5758e Deployed Oct 15, 2026 by vercel[bot]
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