UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

65 lines (64 loc) • 2.98 kB
/** * directory/port — the four directory operations `directory-password` needs, * as a port, so the rules run over a fake directory in tests and over LDAPS * (`ldapDirectory`, through `ldapts`) in a deployment. */ /// <reference types="node" /> /// <reference types="node" /> import type { AdSubCodeName } from '../../../hosting/signin/audit.js'; /** One entry a search found. Binary attributes (objectGUID, objectSid) arrive as bytes. */ export interface DirectoryEntry { readonly dn: string; readonly objectGUID?: Buffer; readonly displayName?: string; } /** * A refused bind that says WHY: Active Directory's sub-code from the LDAP * error (`… data 52e, v1db1` → `'52e'`). For the operator's audit record only — * the person gets one answer whatever it says. */ export interface DirectoryBindRefused { readonly kind: 'invalid'; /** AD's sub-code, lower-case hex, when the error carried one. */ readonly adSubCode?: string; } /** What a bind answered: `'ok'`, or a refusal — bare, or with AD's sub-code. */ export type DirectoryBind = 'ok' | 'invalid' | DirectoryBindRefused; /** One connection, used for exactly one sign-in attempt, then closed. */ export interface DirectorySession { /** * A simple bind, sent ONCE — never retried. `'ok'` when the directory * authenticated the name and password; `'invalid'` (or * `{ kind: 'invalid', adSubCode }`) for ANY wrong credential. The sub-code * reaches the audit record and never the person. Throws only when it could * not ask. */ bind(name: string, password: string): Promise<DirectoryBind>; /** RFC 4532 "Who am I?" — the authzId the directory says this connection is, e.g. `u:CORP\\alice`. Empty = anonymous. */ whoAmI(): Promise<string>; /** A search below `base` (subtree) or AT `base` (`scope: 'base'`). */ search(base: string, filter: string, scope: 'sub' | 'base'): Promise<readonly DirectoryEntry[]>; close(): Promise<void>; } /** Where connections come from. */ export interface Directory { open(): Promise<DirectorySession>; } /** * What an AD bind sub-code means: `52e` bad password, `775` locked, `532` * password expired, `773` must change at next logon, `533` disabled, `701` * account expired; anything else (`525` no such user, `530`/`531` logon * hours/workstation, a code a later AD invents) is `'unknown'`. */ export declare function adSubCodeName(code: string): AdSubCodeName; /** * RFC 4515 §3: escape a value for an LDAP search filter. A string escapes `*`, * `(`, `)`, `\` and NUL (and every non-ASCII byte, so nothing depends on how a * server reads UTF-8 in a filter); bytes are escaped whole. */ export declare function escapeFilterValue(value: string | Buffer): string; /** * A SID in SDDL string form (`S-1-5-21-…-1104`) as the binary `objectSid` a * filter compares, or `undefined` when it is not one. */ export declare function sidToBytes(sid: string): Buffer | undefined;