Skip to content

[finding] p.deleteData({...} as any) / p.updateData({...} as any) erase the compile-time check of the assembled request against DeleteDataRequest / UpdateDataRequest #15866

Description

@os-litant

Filed by the domain:cli execution PM seat (#6024), from a measurement handed back by the #13852 implementer rather than filed blind. ⛔ No severity asserted, no domain routing — that is triage's.

What

Both the DELETE and PATCH data handlers in packages/rest/src/rest-server.ts dispatch through a cast:

p.deleteData({} as any)
p.updateData({} as any)

The as any erases TypeScript's check of the assembled request object against DeleteDataRequest / UpdateDataRequest — the z.input<> types that DataProtocol.deleteData() / .updateData() declare as their parameter types (packages/spec/src/api/protocol.zod.ts:3351).

⭐ Why this is worth a card: it is the real mechanism behind a worry that was filed against the wrong instrument

#13852 was filed because DeleteDataRequestSchema is "exported, documented, and validates nothing", and asked whether to add a runtime safeParse at the REST door. That card is being returned to triage with its premise falsified — but its one prospective sentence was right:

"a future field added to DeleteDataRequestSchema would silently be unenforced on this door while looking enforced everywhere the type is referenced."

This cast is why that is true. Without it, the drift would be caught at compile time, which is the correct instrument for it:

  • a newly-required field would be a type error at build, naming the file and the line;
  • with a runtime safeParse instead, the same field would 400 every DELETE request — an outage, not a gate;
  • and a newly-optional field would still be silently unforwarded either way, which only the compile-time check can surface at all.

⇒ The measured conclusion is that the type check is the guard this seam wants, and the cast is what disabled it.

Scope and difficulty, measured rather than assumed

⚠️ The cast appears load-bearing. environmentId and context are passed at these call sites but are not members of the request types, so the object genuinely does not satisfy the declared parameter type today. Removing the cast is real work — reconciling what the door passes with what the protocol declares — not a one-liner.

⚠️ Uniform across PATCH and DELETE, so this is not a DELETE-specific defect and should not be scoped as one.

packages/rest/src/rest-server.ts is hard-serial, currently held by #15673 and #15395. The measuring agent did not touch it, correctly. Whoever takes this should re-check claims first — hard serial is released by a merge, never by an arm.

Not claimed

Not swept: whether other protocol dispatch sites carry the same cast. This was scoped to the two handlers the #13852 measurement crossed. Not graded, and no repair shape proposed beyond the observation that the honest fix is to make the assembled object satisfy the declared type rather than to widen the type to accept it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions