npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@oaaf/sdk

v0.1.0

Published

TypeScript SDK for the Open Agent Authority Framework (OAAF).

Readme

@oaaf/sdk

TypeScript SDK for the Open Agent Authority Framework.

Verify a delegated authority chain, decide whether a requested tool call is permitted, and explain the answer.

Status: early (pre-v1, 0.x). Not yet published to npm — the artifact is certified publish-ready under the name @oaaf/sdk; the @oaaf scope is a pending ownership step. OAAF profiles Internet-Drafts that may change — see Standards and the versioning policy.

Install

npm install @oaaf/sdk

Not yet on npm. The @oaaf scope is a pending ownership step (docs/releasing.md); the command above will work once the first publish happens. Until then, install the certified packed artifact directly — either from a git reference:

npm install github:espradley/oaaf#main --workspace @oaaf/sdk

or by packing it yourself from a clone (npm run build && npm pack -w @oaaf/sdk, then npm install /path/to/oaaf-sdk-0.1.0.tgz). The packed artifact an outsider installs is certified on every change by npm run check:package.

Runtime and module format

| | | | ------------------------ | ---------------------------------------------------------------------------------- | | Node.js | 20 and 22, tested in CI on both | | Module format | ESM only ("type": "module"). No CommonJS build | | Browsers / edge runtimes | Not targeted or tested; Node is the supported runtime | | TypeScript | Complete .d.ts declarations ship; tested against TS 5 with NodeNext resolution |

ESM-only is deliberate: OAAF is 2026 agent infrastructure, its one crypto dependency (jose) is ESM-first, and a dual CJS build would add maintenance surface for no current adopter. If a concrete CJS consumer appears, that is an RFC, not an assumption.

Public API — import paths

Import only these documented paths. Nothing under dist/ internal to them is public.

| Path | What | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | @oaaf/sdk | Core: verifyAuthority, evaluate, verifyAndEvaluate, toExplanation, explain, and the authority/explanation/reason types | | @oaaf/sdk/mcp | MCP / COAZ binding (RFC-0002): enforceOaafPrecondition, enforceAndMapToCoaz, explainMcpResult | | @oaaf/sdk/a2a | A2A binding (RFC-0003): enforceA2aAuthority, explainA2aResult, the extension constants | | @oaaf/sdk/authzen | AuthZEN request/response mapping and types | | @oaaf/sdk/testing | Local authority minting for evaluation, tests, and demos — not a production issuer |

Stability

Pre-v1, all of this may still change, but deliberately and documented (see the versioning policy):

  • Core (@oaaf/sdk) and the explanation contract are the most settled.
  • The MCP and A2A bindings track draft standards (COAZ-MCP Draft 1, A2A 1.0.1) and move with them — treat them as the most likely to change.
  • @oaaf/sdk/testing is for evaluation and tests. It is not a production token-issuance service, and building one is out of OAAF's scope.

Use

import { verifyAndEvaluate, explain } from '@oaaf/sdk';

const decision = await verifyAndEvaluate({
  tokens, // AAT delegation chain, root first
  trustAnchors, // public keys trusted as root issuers
  pop, // proof-of-possession JWT
  tool: 'read_file',
  args: { path: '/data/q4.pdf' },
});

if (!decision.allowed) {
  console.log(explain(decision));
}
DENIED

Requested
  read_file
    path = "/data/q4.pdf"

Chain
  root → hop 1

Leaf permits
  read_file (constrained: path)

Reason
  argument_constraint_violated
    Argument "path" does not satisfy the constraint on "read_file".
    at tool read_file, argument path

The full runnable version is in examples/quickstartnpm run demo.

API

| Export | Purpose | | ----------------------- | ----------------------------------------------------------------------------- | | verifyAuthority | Full verification, including proof of possession. The enforcement entry point | | evaluate | Decide, given verified authority | | verifyAndEvaluate | Convenience composition of the two | | explain | Render a decision for a human | | verifyDelegationChain | Chain only. Inspection, testing, and conformance work — not enforcement |

verifyDelegationChain performs no proof-of-possession check and produces no decision. There is deliberately no option to disable proof of possession while still returning a decision: a verifier that can be configured to skip it will eventually be configured that way in production, and would then claim conformance it does not have.

Standards

OAAF defines no wire format. It implements:

| Concern | Standard | | ----------------- | -------------------------------------------------- | | Delegation chain | draft-niyikiza-oauth-attenuating-agent-tokens-01 | | Decision contract | OpenID AuthZEN Authorization API 1.0 | | Argument binding | RFC 8785 JSON Canonicalization | | Holder identity | RFC 9278 JWK Thumbprint URI |

AAT support is pinned to revision -01, not to "latest". AAT is an individual Internet-Draft with no working group; it may change, lapse, or be replaced, and OAAF's behaviour is tied to that revision until deliberately upgraded.

The mapping between AAT and AuthZEN is an OAAF profile, frozen by RFC-0001. It is not a requirement of either standard.

Understanding a decision (structured explanation)

Every decision can be rendered for a person or inspected as data. explain() gives text; toExplanation() gives a structured, privacy-safe DecisionExplanation.

A DENY, rendered — the locator tells you exactly which token and argument failed:

DENIED

Subject
  urn:ietf:params:oauth:jwk-thumbprint:sha-256:Jl0v…

Requested
  read_file
    path

Chain
  root → hop 1

Leaf permits
  read_file

Reason
  argument_constraint_violated
    Argument "path" does not satisfy the constraint on "read_file".
    at tool read_file, argument path

Note path appears as a name; its value never does. The requested path — which may be a customer record or a secret — is intentionally omitted.

The same DENY, structured (toExplanation(decision, authority)):

{
  "decision": "DENY",
  "reasons": [
    {
      "code": "argument_constraint_violated",
      "stage": "evaluation",
      "message": "Argument \"path\" does not satisfy the constraint on \"read_file\".",
      "tool": "read_file",
      "argument": "path", // name only — no value
    },
  ],
  "authority": {
    "subject": "urn:ietf:params:oauth:jwk-thumbprint:sha-256:Jl0v…",
    "requestedTool": "read_file",
    "requestedArgumentNames": ["path"], // names only
    "grantedTools": ["read_file"],
    "delegationDepth": 1,
    "chainLength": 2,
    "expiresAt": 1780003600,
  },
}

Before O4A, the MCP and A2A adapters flattened each reason to {code, stage, message} and dropped tool, argument, and tokenIndex — so a caller could see that a request was denied but not which token or argument caused it. Both adapters now carry the full locator set, from one shared model.

What is standards-aligned vs OAAF-specific

Reasons are placed following AuthZEN Authorization API 1.0's context convention (its reason_admin / reason_user distinction): OAAF's stable code is the machine reason and message is developer-facing detail. The DecisionExplanation structure itself is OAAF-specific and adds no authorization semantics — using it does not make OAAF a PDP or require AuthZEN.

Privacy

Explanations carry names, never values: argument names, tool names, stages, reason codes, and the subject's public-key thumbprint. They never carry argument values, resource contents, token bytes, signatures, PoP material, or keys. This holds for explain(), toExplanation(), and both transport adapters, and is asserted in the test suite.

Trust anchors

trustAnchors is required, and there is no way to omit it.

A root token is a claim, not a trust root. Verified against its own cnf.jwk, a chain establishes only that it is internally self-consistent — anyone could mint a self-signed root granting themselves anything and it would verify. With an anchor set, verification establishes that the chain terminates in an issuer you explicitly trust. Those are different guarantees, and only the second is worth having.

So there is no permissive mode, no default anchor set, and no flag to skip the check. Omission is a compile error; an empty set is denied with untrusted_root. This is the same reasoning that makes proof of possession non-optional — see ADR-0004.

Bindings at a glance

// MCP: enforce OAAF authority before the COAZ/AuthZEN decision
import { enforceOaafPrecondition } from '@oaaf/sdk/mcp';

// A2A: enforce OAAF authority on an incoming agent message
import { enforceA2aAuthority } from '@oaaf/sdk/a2a';

Both return the same canonical explanation via explainMcpResult / explainA2aResult (see cross-transport equivalence).

MCP / COAZ

@oaaf/sdk also implements RFC-0002: an integration with COAZ, OpenID's MCP tool-authorization binding for AuthZEN. For a runnable version of the snippet below, see examples/mcp-tool-guard (npm run demo:mcp).

COAZ owns the MCP-to-authorization-request mapping; OAAF does not redefine it. enforceOaafPrecondition is inserted as an additional step in COAZ-MCP's own PEP algorithm, applied before a COAZ request is constructed. On failure it returns a JSON-RPC error and the request is never built; on success it returns the verified authority and a context.oaaf fragment the caller may merge into COAZ's request.

import { enforceAndMapToCoaz } from '@oaaf/sdk';

const result = await enforceAndMapToCoaz({
  tokens,
  trustAnchors,
  pop,
  tool: 'read_file',
  args: { path: '/data/q3.pdf' },
  principal, // COAZ's own input: $token.sub
  agent, // COAZ's own input: $token.?client_id
});

if (!result.ok) {
  // JSON-RPC error, per COAZ-MCP — no AuthZEN request was ever built.
  return result.error;
}

// result.request is COAZ's default tools/call mapping, unmodified in
// subject/action/resource, with context.oaaf added.

Existing PDP interoperability

OAAF can sit in front of an existing policy engine (AuthZEN, OPA, Cedar, OpenFGA) rather than replacing it (RFC-0006, docs/pdp-interoperability.md). OAAF makes the authority decision; the PDP makes the org policy decision on top.

toAuthorityContext turns a verified authority into the canonical, PDP-neutral authority context ({ authorityVerified: true, subject, grantedTools, ... }) — names, never values — which AuthZEN carries as context.oaaf and OPA/Cedar read as attributes. authorityVerified: true is OAAF's Decision 1, not a policy permit; the PDP still decides. For a runnable end-to-end demo against a stub PDP, see examples/pdp-coexistence (npm run demo:pdp).

import { verifyAuthority, toAuthorityContext } from '@oaaf/sdk';

const verified = await verifyAuthority({ tokens, trustAnchors, pop, tool, args });
if (verified.ok) {
  const oaaf = toAuthorityContext(verified.authority);
  // hand `oaaf` to your PDP as context; it owns the policy decision.
}

What this does not do

  • No revocation. AAT does not mitigate it and neither does OAAF. Authority is bounded by exp alone.
  • No replay protection. AAT makes stateful jti tracking a deployment responsibility.
  • No signed decision receipts. Portable receipts (O4D) are parked pending evolving standards work and adopter demand.

License

Apache 2.0