Files
PaperClipAI/packages/shared/src/muse-invitations.ts
T
DottaandPaperclip 93ab7bad11 Add immutable Muse clients and OAuth grant contracts (#16447)
Add immutable Muse client assets and the grant-linked private contract.

Keep the grant migration safe for replay and partial schema recovery, preserving exact preview receipts and existing data. Keep public wake signals separate from private provider authority.

Refs #16447.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 14:09:26 -05:00

56 lines
4.5 KiB
TypeScript

import { z } from "zod";
import type { AgentLifecycleState } from "./types/agent-lifecycle.js";
import type { MuseStopBoundary } from "./muse-protocol.js";
/** Only transient pairing responses contain the ticket/setup instruction. */
export interface MuseBinding {
id: string; generation: number; revision: number;
status: "pairing" | "connected" | "ready" | "revoked";
paired: boolean; receiverDetected: boolean; backgroundReplyVerified: boolean;
pairingExpiresAt: string | null; challengeExpiresAt: string | null;
lastReceiverContactAt: string | null; lastWorkerActivityAt: string | null; lastVerifiedReplyAt: string | null;
credentialState: "pending" | "active" | "expired" | "revoked"; refreshExpiresAt: string | null;
receiverContactTrust: "public_untrusted"; contactPersistenceLagMs: number; clientVersion: string | null;
qualification: { id: string; expiresAt: string } | null;
liveAssignments: number; uncertainOperations: number; pendingInputs: number;
cleanup: { detectorEvidence?: MuseDetectorCleanupEvidence | null; attestationEligible?: boolean; hookScript?: string; authenticatedAfterRevocation?: boolean; pending: boolean; detectorRemovalRequested?: boolean; detectorRemoved: boolean; workerQuiescenceReported: boolean; expiresAt: string | null };
stop: { status: "none" | "cannot_confirm" | "worker_reported" | "operator_attested"; nativeEffectsUnknown: boolean; boundary: MuseStopBoundary | null; bindingRevision: number | null };
}
export interface MuseInvitation { agent: { id: string; name: string; status: string }; approvalId: string | null; binding: MuseBinding | null }
export interface MuseConnection {
enabled: boolean; publicOrigin: string | null; agentStatus: string; agentLifecycleState: AgentLifecycleState;
canConfigureConnection: boolean; binding: MuseBinding | null; usage: null; cost: null;
}
export interface MusePairing {
bindingId: string; generation: number; revision: number; ticket: string; expiresAt: string;
setupInstruction: string; assetVersion: 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
}
export interface MuseVerifyResult { bindingId: string; generation: number; revision: number; expiresAt: string; status: "pending" }
export interface MuseInvitationInput { name: string; role: string }
export interface MusePairingInput { replaceBindingId?: string; expectedRevision?: number }
export interface MuseVerifyInput { bindingId: string; generation: number; expectedRevision: number }
export interface MuseRevokeInput extends MuseVerifyInput {}
export const museDetectorCleanupAttestationSchema = z.object({
bindingId: z.uuid(), generation: z.number().int().positive(), expectedRevision: z.number().int().positive(),
qualificationId: z.uuid().nullable(), hookScript: z.string().min(1).max(160), detectorRemoved: z.literal(true),
observation: z.object({ method: z.literal("hooks.list"), includeDisabled: z.literal(true), hookId: z.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/), outcome: z.literal("exact_hook_absent"),
observedAt: z.iso.datetime(), sha256: z.string().regex(/^[a-f0-9]{64}$/) }).strict(),
}).strict();
export type MuseDetectorCleanupAttestationInput = z.infer<typeof museDetectorCleanupAttestationSchema>;
export interface MuseDetectorCleanupEvidence {
bindingId: string; generation: number; qualificationId: string | null; hookScript: string;
source: "authenticated_worker_report" | "operator_runtime_attestation";
recordedAt: string; observedAt: string; operatorId: string | null; hookId: string | null;
}
export interface MuseAttestStopInput { boundary: MuseStopBoundary; expectedRevision: number; workerStopped: true }
export interface MuseQualificationBeginResult { qualificationId: string; startedAt: string; expiresAt: string; revision: number }
export interface MuseQualificationEvidence {
qualificationId: string; startedAt: string; expiresAt: string; stoppedAt: string | null; deadlineEnforcedAt: string | null;
detectorCleanup?: MuseDetectorCleanupEvidence | null;
authorityRevoked: boolean; persistenceLagMs: number; cadenceEvidenceComplete: boolean;
contacts: Array<{ trust: "public_untrusted"; replicaId: string; bucketAt: string; firstAt: string; lastAt: string; contacts: number; gapsAtMostSevenSeconds: number; maxGapMs: number; timestamps: string[]; incomplete: boolean }>;
assignments: Array<{ id: string; runId: string; issueId: string | null; status: string; offeredAt: string; claimedAt: string | null; nativeAcceptedAt: string | null; acceptedResultAt: string | null; finalizedAt: string | null }>;
idleWindows: Array<{ startedAt: string; endedAt: string }>;
}