Remotable = (
  // @ts-expect-error I could have different subtype than string
  iface = 'Remotable',
  props = undefined,
  remotable = /** @type {T} */ ({}),
) => {
  assertIface(iface);
  assert(iface);
  // TODO: When iface is richer than just string, we need to get the allegedName
  // in a different way.
  props === undefined || Fail`Remotable props not yet implemented ${props}`;

  // Fail fast: check that the unmodified object is able to become a Remotable.
  assertCanBeRemotable(remotable);

  // Ensure that the remotable isn't already marked.
  !(PASS_STYLE in remotable) ||
    Fail`Remotable ${remotable} is already marked as a ${q(
      remotable[PASS_STYLE],
    )}`;
  // `isFrozen` always returns true with a fake `harden`, but we want that case
  // to succeed anyway. Faking `harden` is only correctness preserving
  // if the code in question contains no bugs that the real `harden` would
  // have caught.
  // @ts-ignore `isFake` purposely not in the type
  harden.isFake ||
    // Ensure that the remotable isn't already frozen.
    !isFrozen(remotable) ||
    Fail`Remotable ${remotable} is already frozen`;
  const remotableProto = makeRemotableProto(remotable, iface);

  // Take a static copy of the enumerable own properties as data properties.
  // const propDescs = getOwnPropertyDescriptors({ ...props });
  const mutateHardenAndCheck = target => {
    // defineProperties(target, propDescs);
    setPrototypeOf(target, remotableProto);
    harden(target);
    assertCanBeRemotable(target);
  };

  // Fail fast: check a fresh remotable to see if our rules fit.
  mutateHardenAndCheck({});

  // Actually finish the new remotable.
  mutateHardenAndCheck(remotable);

  // COMMITTED!
  // We're committed, so keep the interface for future reference.
  assert(iface !== undefined); // To make TypeScript happy
  return /** @type {any} */ (remotable);
}
Create and register a Remotable.  After this, getInterfaceOf(remotable)
returns iface.

// https://github.com/Agoric/agoric-sdk/issues/804

@template {{}} T
@template {InterfaceSpec} I
@param {I} [iface] The interface specification for
the remotable. For now, a string iface must be "Remotable" or begin with
"Alleged: " or "DebugName: ", to serve as the alleged name. More
general ifaces are not yet implemented. This is temporary. We include the
"Alleged" or "DebugName" as a reminder that we do not yet have SwingSet
or Comms Vat
support for ensuring this is according to the vat hosting the object.
Currently, Alice can tell Bob about Carol, where VatA (on Alice's behalf)
misrepresents Carol's `iface`. VatB and therefore Bob will then see
Carol's `iface` as misrepresented by VatA.
@param {undefined} [props] Currently may only be undefined.
That plan is that own-properties are copied to the remotable
@param {T} [remotable] The object used as the remotable
@returns {T & RemotableObject<I> & RemotableBrand<{}, T>}} remotable, modified for debuggability