endojs / endo

Endo is a distributed secure JavaScript sandbox, based on SES
Apache License 2.0
762 stars 68 forks source link

make harden() return a readonly type #2244

Open turadg opened 2 months ago

turadg commented 2 months ago

What is the Problem Being Solved?

harden in the SES package makes the argument value immutable. Currently the return type is the value itself, despite this transformation. Here is the rationale: https://github.com/endojs/endo/blob/25dcb30f832cf3acda44c7a38c55d5945386a81d/packages/ses/types.d.ts#L7-L20

Because of this, the type system does not detect when a mutation is attempted on a hardened value. Solving this requires solving several sub-problems:

A migration path

Function signatures currently aren't responsible for saying they won't mutate the parameters. If a Hardened value is passed to a function that doesn't say it accepts readonly then the type checker will complaint that the function expects a mutable version.

Conveying the side effect harden() returns a hardened value, but it also modifies the value itself. In prototyping this with,

declare function enharden<T>(val: T): asserts val is Hardened<T>;

I encountered,

A type predicate's type must be assignable to its parameter's type.
  Type 'Hardened<T>' is not assignable to type 'T'.
    'T' could be instantiated with an arbitrary type which could be unrelated to 'Hardened<T>'.

Enforcement of readonly

Even if we were to solve the above, TypeScript currently doesn't enforce the readonly attribute: https://github.com/microsoft/TypeScript/issues/13347 But this may be solved soon: https://github.com/microsoft/TypeScript/pull/58296

Description of the Design

Very TBD. It's not clear yet whether any design would be worth the cost in DevEx, let alone time to implement.

Migration path

We could have a utility like NoWrite,

type NoWrite<T> = T | Hardened<T>;

function printNum(nums: NoWrite<number[]>) {
  console.log(nums);
  // @ts-expect-error readonly
  nums[0] = 3;
}

Security Considerations

Scaling Considerations

Test Plan

Compatibility Considerations

Upgrade Considerations