Skip to content

mdcode: don't let an ambiguous 403 masquerade as "absent" in sync - #317

Draft
libei wants to merge 1 commit into
GoogleCloudPlatform:mainfrom
libei:worktree-fix-403-sync
Draft

mdcode: don't let an ambiguous 403 masquerade as "absent" in sync#317
libei wants to merge 1 commit into
GoogleCloudPlatform:mainfrom
libei:worktree-fix-403-sync

Conversation

@libei

@libei libei commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Fixes #308.

The Catalog API returns 403 for both "entry does not exist" and "caller lacks permission" (noted at src/libts/sync.ts). Both sync paths treated any non-200 lookup as "absent", producing a wrong outcome in each direction.

pull — reported success over a snapshot it did not take

A pull in which every entry 403'd skipped every entry and still returned {success: true} → the user saw Successfully updated local snapshot over an empty/partial snapshot.

Now pull counts the skips and, when any occur, returns success: false (surfaced by the CLI, exit 1) with a message that names the 403 ambiguity and the first skipped entry. Readable entries are still stored, so the pull is partial rather than aborted, and SyncResult gains a skipped count.

push — attempted a create on an entry that exists

A 403 on the lookup read as "not there", so push called createEntry, the service returned 409, and the whole push aborted reporting Failed to create entry — the wrong problem.

Now a 409 on create is reported as already-exists, i.e. the lookup's 403 was a permission problem on an existing entry, not a missing one. The genuine-new-entry create path is unchanged (new entries also lookup-403, then create succeeds).

Test

Adds tests/libts/sync.test.ts covering both failure modes (pull skip-counting incl. all-403, push 409→already-exists vs. create-success) with lightweight fakes. Typechecks clean; full existing suite unaffected (pre-existing polyglot-wasm failures are environmental).

The Catalog API returns 403 for both "entry does not exist" and "caller
lacks permission" (noted at sync.ts). Both sync paths treated any non-200
lookup as "absent", producing a wrong outcome each way:

- pull skipped every 403'd entry yet returned {success: true}, so the user
  saw "Successfully updated local snapshot" over an empty/partial snapshot
  with nothing indicating entries were skipped. Now pull counts the skips
  and, when any occur, returns success:false with a message naming the
  ambiguity and the first skipped entry (readable entries are still stored,
  so the pull is partial rather than aborted).

- push read a 403 lookup as "not there", tried to createEntry, got 409, and
  aborted the whole push reporting "Failed to create entry" — pointing at the
  wrong problem. Now a 409 on create is reported as already-exists, i.e. the
  lookup's 403 was a permission problem, not a missing entry.

Adds a unit test covering both failure modes.

Fixes GoogleCloudPlatform#308
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.

mdcode: a 403 reads as "not found" — pull reports success, push attempts a create

1 participant