Skip to content

Export a supported typed client for the local daemon #71

Description

@thymikee

Part of #70. See ADR 0021.

Purpose

Export a supported TypeScript client for the local Simlock daemon.

The current client is private. Its generic request method returns Promise<unknown>.

Host must not import files from src/ or start a command process.

Proposed API

The names can change. The public contract must give equivalent typed operations.

export interface ConnectSimlockOptions {
  socketPath: string;
  startDaemon: boolean;
  protocol: { min: number; max: number };
}

export interface ConnectSimlockAdminOptions extends ConnectSimlockOptions {
  credential: string;
}

export interface SimlockClient {
  protocol: ProtocolInfo;
  listCatalog(input?: { platform?: Platform }): Promise<PlatformCatalog[]>;
  getStatus(): Promise<DaemonStatus>;
  runDoctor(): Promise<DoctorReport>;
  renewLease(input: { leaseId: string; ttlMs?: number }): Promise<Lease>;
  releaseLease(input: { leaseId: string }): Promise<void>;
  close(): Promise<void>;
}

export interface SimlockAdminClient extends SimlockClient {
  // Admin operations from later issues extend this interface.
}

export function connectSimlock(
  options: ConnectSimlockOptions,
): Promise<SimlockClient>;

export function connectSimlockAdmin(
  options: ConnectSimlockAdminOptions,
): Promise<SimlockAdminClient>;

Host will use startDaemon: false. Its supervisor will control the daemon process.

Required behavior

  • Export the clients from a supported package entry point.
  • Keep the Unix socket as the transport.
  • Keep support for an explicit socket path.
  • Keep request ID multiplexing on one connection.
  • Parse each public result before the client returns it.
  • Return typed Simlock errors. Do not expose unknown payloads.
  • Test protocol compatibility during connection.
  • Reject an incompatible version before a mutation starts.
  • Authenticate the admin client with a daemon-configured credential before it can call an admin method.
  • Reject a missing or invalid admin credential before a mutation starts.
  • Do not infer admin authority from the socket path or a client-declared role.
  • Do not return or log the admin credential.
  • Keep private daemon and core types out of the package export.
  • Keep existing socket-based frontends on this client implementation.

Use a stable error for protocol mismatch:

interface ProtocolVersionError {
  code: "PROTOCOL_VERSION_UNSUPPORTED";
  client: { min: number; max: number };
  daemon: { min: number; max: number };
}

Use a stable error for an invalid admin credential:

interface AdminAuthenticationError {
  code: "ADMIN_AUTHENTICATION_FAILED";
}

Completion conditions

  • A Node consumer can use all listed operations from the supported export.
  • One connection can renew concurrent leases independently.
  • Tests reject invalid result payloads at the client boundary.
  • Tests reject protocol mismatch before a mutating request reaches the daemon.
  • Tests prove that an ordinary client cannot call an admin operation.
  • Tests prove that an invalid admin credential causes zero mutation.

This issue provides the client boundary. Later issues can add methods to the same clients.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions