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

@adjudicate/admin-sdk

v8.0.0

Published

Admin Query Interface (AQI) for adjudicate — Zod-validated read-only audit query handlers + tRPC router. Adopter-deployed; framework-shipped contract.

Readme

@adjudicate/admin-sdk

Status: 2.1.0 — stable wire contract. Read and mutating procedures both ship.

The Admin Query Interface (AQI) for the adjudicate framework. This package owns the wire contract between an adopter's deployed audit infrastructure and any consuming UI (the reference @adjudicate/console, or an adopter-built one).

The framework ships:

  • Zod schemas that validate payloads at the wire boundary
  • An AuditStore interface the adopter implements against their persistence
  • A framework-agnostic handler factory for raw HTTP wiring
  • A tRPC router for TypeScript-end-to-end consumers
  • A Next.js Route Handler adapter (the canonical case; other frameworks are 5-line ports)

The framework does not ship: auth (adopter wraps), persistence (adopter implements AuditStore and the optional read/mutation ports), or hosted infra (the SDK runs in the adopter's process).


Surface map

@adjudicate/admin-sdk           — schemas, AuditStore, handler, in-memory ref
@adjudicate/admin-sdk/trpc      — adminRouter (tRPC v11)
@adjudicate/admin-sdk/adapters/next — toNextRouteHandler

adminRouter exposes these namespaces (see src/trpc/index.ts):

| Namespace | What it covers | |-----------|----------------| | audit | query / byHash — read kernel-emitted decision audits (actor-gated). | | emergency | state / history (read) + update (mutation) — operator kill switch. | | replay | run (mutation) — re-adjudicate a historical record against current policy. | | governance | distributions, drift, red-team, token-budget, config-seal, policy descriptor/manifest reads + recordOutcome (mutation). | | approval | list / history / chain (read) + resolve (mutation) — confirmation engine. | | pack | aiBom / aiBomList / aiBomById — AI Bill-of-Materials reads. | | memory | bySession — cross-session memory snapshot read. | | escalate | raise (mutation) — friction-monotone escalate/recommend surface (escalate-only, rate-limited). |

Optional surfaces (governance/approval/pack/memory/escalate beyond the base reads) are feature-detected at runtime: each procedure throws PRECONDITION_FAILED when its backing port is not wired into AdminContext, so the procedure shape stays static across adopters.

Read-only plane + the escalate write (readOnlyAdminRouter)

@adjudicate/admin-sdk/trpc also exports readOnlyAdminRouter — the §B/§G Inspector-General OBSERVER plane. It is adminRouter MINUS the four AUTHORIZE/WEAKEN mutations (emergency.update, replay.run, governance.recordOutcome, approval.resolve), so a console mounting it physically cannot authorize, weaken, or replay-mutate a decision — those procedures do not exist on the wire (router-level write isolation, not a runtime check).

It is not zero-mutation, though: it carries exactly ONE write — escalate.raise. That is safe on the observer plane precisely because it is friction-monotone by construction (§C / §D inv.7):

  • Escalate-only enum. recommendation is the closed EscalateRecommendationSchemapause / review / escalate. There is no allow / bypass / override / lower-threshold / EXECUTE value, enforced at the wire (a raw-HTTP caller cannot smuggle a friction-decreasing verb), mirroring the emergency status enum's "no allow-all/bypass" invariant.
  • Records a fact, never a decision. The output is a RecordedEscalation (kind: "escalation.raised") — the closed 6-outcome Decision algebra is untouched; the kernel decision hot-path is never reached.
  • Reads, never mutates, the target. It resolves the target decision read-only via AuditStore.getByIntentHash (tenant-scoped); the audit record is never mutated.
  • Actor-gated + rate-limited. UNAUTHORIZED without an actor; TOO_MANY_REQUESTS once a per-actor sliding window is exceeded (createEscalateRateLimiter, default 10/min). Wire an EscalationSink into AdminContext (createInMemoryEscalationSink, or your durable fail-OPEN log); when absent, escalate.raise throws PRECONDITION_FAILED.

The escalation log MAY be fail-OPEN within the governance plane (operator-action precedence): record into the live sink, fire-and-forget the durable write, log (don't throw) on log-infra failure — the same posture as the kill-switch governance log. This fail-OPEN is isolated to the governance plane and never touches the fail-CLOSED decision hot-path.

Governance views (read-only, on the observer plane)

The three governance surfaces below are pure .query procedures — they read recorded snapshots through feature-detected AdminContext ports and never authorize, weaken, or mutate a decision (§C / §D-7). They ride the read-only plane verbatim (governanceReadOnlyRouter = the governance reads with no recordOutcome), so an Inspector-General app exposes them while the lone governance mutation stays on the operator console. Each omitted port self-fences with PRECONDITION_FAILED, so the surface is runtime-feature-detectable (the procedure shape stays static across adopters; an unwired view returns a typed precondition error, never a crash or a fabricated empty value):

| View | Reads | Port | Omitted ⇒ | |------|-------|------|-----------| | Policy-version history | governance.describePolicy / governance.policyManifest | ctx.policyDescriptor / ctx.policyManifest (typically describePolicyBundle(pack.policy) / the ibx policy export artifact, computed at route-handler startup) | PRECONDITION_FAILED | | Dashboards | governance.guardFireStats / governance.outcomeDistribution | ctx.guardFireStats (a GuardFireStats instance) / ctx.store (the read-only AuditStore — newest-first, limit capped at 500) | guardFireStatsPRECONDITION_FAILED; outcomeDistribution needs only store (always present) | | Kill-switch read-status | governance.killSwitchTimeline | ctx.killSwitchTimeline — the adopter maps emergency.history (GovernanceEvent) → KillSwitchEvent[] and runs the pure analyzeKillSwitchTimeline (@adjudicate/audit) at the route handler, then threads the report | PRECONDITION_FAILED |

The kill-switch view is read-status only: the OBSERVER sees the engage/clear timeline (emergency.state / emergency.history), but the kill-switch WRITE (emergency.update) is structurally absent from the read-only plane — it stays on the operator console. A read-only mount therefore omits replayer, outcomeSink, and approvalPort.resolve while keeping the pure-read ports (turnTrace, guardFireStats, policyDescriptor, policyManifest, killSwitchTimeline). These views render store records verbatim; they make no cryptographic tamper-detection claim (integrity-on-read is the Audit Explorer's byHashVerified verdict), and they must not present byHash as tenant-safe (tenant isolation is host-enforced upstream).

Authentication & actors

Every record-level read and every mutation requires an authenticated actor, resolved by the adopter's createContext via extractActor(req) from the x-adjudicate-actor-id header (plus optional -name / -tenant):

  • audit.query / audit.byHash and the record-level governance drill-downs (piiEvents, commandRiskEvents) throw UNAUTHORIZED with no actor — audit reads are not open.
  • Mutations (emergency.update, replay.run, governance.recordOutcome, approval.resolve, escalate.raise) throw UNAUTHORIZED with no actor. escalate.raise is additionally per-actor rate-limited (TOO_MANY_REQUESTS).
  • Aggregate-only stats (outcomeDistribution, piiClassificationStats, commandRisk) leak no per-record data and do not require an actor.

extractActor does not authenticate — it trusts the headers. The toNextRouteHandler adapter takes a requireAuth gate (REQUIRED in production; the handler throws at construction without it) that runs before every request. Wrap your IdP session check there (see the next.ts JSDoc for Clerk / OIDC recipes).

Implementing AuditStore

The adopter read contract is two methods. Postgres / Memory / Kafka-archive / S3-cold all satisfy the same shape.

import type { AuditStore } from "@adjudicate/admin-sdk";

export const myPostgresStore: AuditStore = {
  async query(filters) {
    const rows = await db.query(
      `SELECT * FROM intent_audit
       WHERE ($1::text IS NULL OR envelope->>'kind' = $1)
         AND ($2::text IS NULL OR decision->>'kind' = $2)
         AND ($3::timestamptz IS NULL OR at >= $3)
       ORDER BY at DESC
       LIMIT $4`,
      [filters.intentKind, filters.decisionKind, filters.since, filters.limit],
    );
    return { records: rows.map(rowToAuditRecord) };
  },
  async getByIntentHash(intentHash) {
    const row = await db.queryOne(
      `SELECT * FROM intent_audit WHERE intent_hash = $1`,
      [intentHash],
    );
    return row ? rowToAuditRecord(row) : null;
  },
};

Implementations MUST:

  • Return records newest-first by at (ISO-8601 string sort = chronological).
  • Honor query.limit exactly. The schema caps it at 500.
  • Apply all provided filter fields with AND semantics.
  • Surface persistence failures by throwing — the SDK converts to a tRPC INTERNAL_SERVER_ERROR with safe message.
  • For multi-tenant stores, honor the optional getByIntentHash tenantScope and never return a record outside it.

Implementations MUST NOT:

  • Mutate records.
  • Re-validate against Zod (the SDK already validated input).
  • Return records that don't match the filter.

Mounting the tRPC router (Next.js)

AdminContext requires store, emergencyStore, and actor (the optional ports — replayer, approvalPort, outcomeSink, aiBom, etc. — are wired in only for the surfaces you expose):

// app/api/admin/[trpc]/route.ts
import {
  adminRouter,
  toNextRouteHandler,
  createInMemoryAuditStore,
  extractActor,
} from "@adjudicate/admin-sdk";

const store = createInMemoryAuditStore({ records: myRecords });

export const { GET, POST } = toNextRouteHandler({
  router: adminRouter,
  endpoint: "/api/admin",
  requireAuth: withClerkAuth, // REQUIRED in production
  createContext: (req) => ({
    store,
    emergencyStore: myEmergencyStore,
    actor: extractActor(req),
  }),
});

For Express/Fastify/Hono, import createAuditQueryHandler directly and wire it into your router. The handler signature is (input: AuditQuery) => Promise<AuditQueryResult> — REST-native by construction.

Schema drift policy

@adjudicate/core defines the canonical TypeScript types. @adjudicate/admin-sdk ships matching Zod schemas. Drift is caught by three independent gates:

  1. Build-time TS assignability — the schemas that mirror a core type carry _coreToSchema / _schemaToCore const guards whose bodies fail to compile if the schema and core type disagree (e.g. src/schemas/envelope.ts, which mirrors core/src/envelope.ts + taint.ts). Most schemas in src/schemas/ are AQI-only (governance, approval, pack, token-budget, …) with no core counterpart to guard.
  2. Runtime fixture roundtriptests/schemas-roundtrip.test.ts parses one fixture per Decision kind through the schemas. Drift fails by name.
  3. CI gate — root pnpm -r test runs both above as part of normal verification. A kernel change that breaks the SDK fails the workspace build.

If you edit a core type that a schema mirrors (packages/core/src/{decision,envelope,audit,refusal,basis-codes,taint}.ts), update the matching file in packages/admin-sdk/src/schemas/. CI will tell you if you forgot.

What's not in this package

  • Auth — adopter-supplied. Pass requireAuth to the route handler / wrap with your auth middleware.
  • Persistence & ports — adopter implements AuditStore and any optional read/mutation ports (replayer, approvalPort, outcomeSink, AI-BOM, drift, token-budget, …).
  • Postgres reference store — separate package @adjudicate/audit-postgres-store (future).
  • Express/Fastify/Hono adapters — community PRs welcome. The handler is framework-agnostic by design.
  • OpenAPI export — possible from Zod via zod-to-openapi if a non-TS consumer ever appears.