/** * Device pairing (ADR 0020 Phase 0) * * Delegated device keys under an Ed25519 identity. Never copies identity.json * private key. OOB string payloads: start → join → approve → accept. */ import type { IdentityResolver } from './signing-middleware.js'; export declare const ROOT_DEVICE_ID = "root"; export declare const PAIR_TTL_SECONDS: number; export declare const PAIR_PREFIX = "trellis:pair:v1:"; export declare const JOIN_PREFIX = "trellis:join:v1:"; export declare const AUTH_PREFIX = "trellis:auth:v1:"; export interface PairChallenge { v: 1; challengeId: string; did: string; identityEntityId: string; /** Root public key (base64 SPKI) so B can verify SignedDeviceAuthorization. */ rootPublicKey: string; exp: number; nonce: string; } export interface JoinResponse { v: 1; challengeId: string; devicePublicKey: string; deviceLabel?: string; /** Signature over canonical challenge bytes. */ signature: string; } export interface DeviceAuthorization { v: 1; deviceId: string; identityEntityId: string; did: string; devicePublicKey: string; deviceLabel?: string; issuedAt: string; expiresAt?: string; issuerDeviceId: string; challengeId: string; } export interface SignedDeviceAuthorization { authorization: DeviceAuthorization; signature: string; } export interface DeviceRecord { deviceId: string; devicePublicKey: string; deviceLabel?: string; authorizedAt: string; revokedAt?: string; issuerDeviceId: string; challengeId: string; } export interface DeviceRegistry { identityEntityId: string; did: string; rootPublicKey: string; devices: DeviceRecord[]; } export interface LocalDeviceKey { deviceId: string; identityEntityId: string; did: string; publicKey: string; privateKey: string; deviceLabel?: string; createdAt: string; } export declare function encodePayload(prefix: string, obj: unknown): string; export declare function decodePayload(prefix: string, payload: string): T; /** Crockford base32 short code from challengeId (first 8 chars of hash). */ export declare function challengeShortCode(challengeId: string): string; export declare function deviceFingerprint(publicKeyBase64: string): string; export declare function loadRegistry(trellisDir: string): DeviceRegistry | null; export declare function saveRegistry(trellisDir: string, registry: DeviceRegistry): void; export declare function loadLocalDevice(trellisDir: string): LocalDeviceKey | null; export declare function saveLocalDevice(trellisDir: string, local: LocalDeviceKey): void; export declare function listDevices(trellisDir: string): DeviceRecord[]; export declare function revokeDevice(trellisDir: string, deviceId: string): boolean; export declare function resolveDevicePublicKey(trellisDir: string, identityEntityId: string, deviceId: string): string | null; export declare function resolvePublicKeys(trellisDir: string, identityEntityId: string): string[]; export declare function assertChallengeValid(challenge: PairChallenge): void; export declare function pairStart(trellisDir: string, opts?: { ttlSeconds?: number; }): { challenge: PairChallenge; payload: string; shortCode: string; }; export declare function pairJoin(trellisDir: string, challengePayloadOrCode: string, opts?: { deviceLabel?: string; }): { join: JoinResponse; payload: string; local: LocalDeviceKey; challenge: PairChallenge; }; export declare function pairApprove(trellisDir: string, joinPayload: string, opts?: { yes?: boolean; }): { signed: SignedDeviceAuthorization; payload: string; fingerprint: string; }; export declare function pairAccept(trellisDir: string, authPayload: string): { local: LocalDeviceKey; authorization: DeviceAuthorization; }; /** * Signing material for this install: prefer paired device key, else root identity. */ export declare function getSigningMaterial(trellisDir: string): { privateKey: string; identityEntityId: string; signedWith: string; } | null; /** * Build an `IdentityResolver` bound to a trellis directory (ADR 0022 Phase 3). * * The `IdentityResolver` interface takes only an `entityId` (it is injected * into the engine, which has no filesystem concept), whereas the registry * lookups in this module need the `trellisDir`. This adapter closes that gap: * it captures the dir and forwards to the registry/local-device resolution * that backs ADR 0020 device keys. * * Returns `null` when the directory has no identity at all, so callers can * keep the resolver opt-in (an identity-less repo gets no PKI enforcement). */ export declare function pairingResolver(trellisDir: string): IdentityResolver | null; //# sourceMappingURL=pairing.d.ts.map