agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
54 lines • 2.94 kB
TypeScript
/**
* verify/claims — reading a verified claim set, one rule per kind of claim.
*
* Three readings, and the difference between them is the whole file:
*
* • **A roles claim is a LIST.** An array contributes each string entry as
* one role; a single string is ONE role. `"Not bot-users"` is the role
* `Not bot-users` — never the two roles `Not` and `bot-users`, which is how
* a space-splitting reader lets a group name satisfy a role gate it does
* not name. (`'space-delimited'` keeps the old reading, by request only.)
* • **A scope claim is space-delimited** — RFC 8693 §4.2 / RFC 9068 §2.2.3
* define `scope` that way, and Entra's `scp` follows it. An array is also
* read, entry by entry.
* • **A claim NAME is never split.** `urn:bot:objectguid` and
* `http://schemas.microsoft.com/…/role` contain dots and colons and are one
* name each. A nested claim is named by a PATH — an array of names
* (`['realm_access', 'roles']` for Keycloak) — never by a dotted string.
*
* Comparison is always exact, and nothing here trims, case-folds or tidies a
* value: ids are opaque bytes (rule 7).
*/
/** A top-level claim name, or a path of names into nested objects. */
export type ClaimPath = string | readonly string[];
/** How a roles claim's single STRING is read. */
export type RolesFormat = 'list' | 'space-delimited';
/** The value at `path`, or `undefined`. A string path is ONE name. */
export declare function claimAt(payload: Readonly<Record<string, unknown>>, path: ClaimPath): unknown;
/** A path, spelled for a banner or a refusal — never a value. */
export declare function pathLabel(path: ClaimPath): string;
/**
* Roles out of a claim value, never invented: ABSENT when the claim is absent,
* empty, or holds no string.
*/
export declare function rolesOf(value: unknown, format: RolesFormat): readonly string[] | undefined;
/**
* Scopes out of a scope claim: a space-delimited string or an array of
* strings. ABSENT when the claim is absent or holds nothing — which is not the
* same fact as "holds no matching scope", and the person test tells them apart.
*/
export declare function scopesOf(value: unknown): readonly string[] | undefined;
/**
* The claims that name the client which OBTAINED a token, in the order they
* are read: `azp` (OIDC, Entra v2, Keycloak), `appid` (Entra v1, AD FS), `cid`
* (Okta), `client_id` (RFC 9068).
*/
export declare const CLIENT_CLAIMS: readonly string[];
/**
* The client that obtained the token: the FIRST of {@link CLIENT_CLAIMS} that
* is present. A present claim that is not a non-empty string names nobody, and
* the answer is `undefined` — never a fall-through to the next claim, which
* would let a token choose which of its claims is read.
*/
export declare function clientOf(payload: Readonly<Record<string, unknown>>): string | undefined;
//# sourceMappingURL=claims.d.ts.map