Repository navigation
fix(file-doc): stop the permission resend loop and restore the 10 MB proxy body limit - #9057
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
[High impact] This PR appears safe to merge; no actionable new issues were found. SummaryThis 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.
No actionable new issues were found in the changes since the previous review. No previous review threads were supplied.
|
…eep capability through the per-socket de-dup
|
@greptile |
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
…nd persist attribution with tests
|
@greptile |
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
…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.
* 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>
Summary
Changes only flag-gated Project file paths (behind the
projectsflag).create,update_content,upload_complete,versions.revert,extract_archive) declarechargesStorageand 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.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 5slock_timeoutnow bounds only the acquisition and the caller's setting is restored.readProjectFileContentand version content reads drop an unused preflight transaction (prepareFromSnapshot); their snapshot use case authorizes, and the final transaction still revalidates after the storage read.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.Expected conflicts for the stacked Project file PRs:
knip.jsonc(#9018 adds entries; its newproject-file*.tscontract files lose the glob ignore),projects/files/application/authorization.ts(#9018 exports helpers),billing/storage/tracking.tsandprojects/membership.ts(#9034).Type of Change
Testing
projects/files/__integration__/authorization.integration.ts: concurrent reads and a folder create proceed while a read holds the Project,lock_timeoutis restored, and exclusive Project and permission-group holders still wait; a storage-charging write still excludes shared holdersprojects/files/application/documents.test.ts: lock conflicts are surfaced, revision conflicts still retry (verified red on the old predicate)Checklist
test-auditauthoring gate)