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

@metadium-did/platform-agent-js

v0.4.0

Published

METADIUM AI-agent holder client + CLI — did:jwk key, PoP JWT, SD-JWT VC presentation (KB-JWT), and the Briefick agent-auth delegation flow. Node/TS (ES256/P-256 only), wire-compatible with platform-java.

Readme

@metadium-did/platform-agent-js

AI 에이전트(예: Claude Code)가 위임 VC로 서비스에 인증하기 위한 Node/TypeScript 홀더 클라이언트 + CLI. 정적 API 키를 스코프드·기한부·철회가능 위임으로 대체한다([[samples/docs/22]] 시나리오 #8).

  • did:jwk 키(ES256/P-256) 생성·보관
  • PoP JWT(소유 증명) — 등록/회수/세션 교환
  • SD-JWT VC 제시 + KB-JWT(홀더 바인딩) — 위임 VP 생성
  • Briefick 위임 인증 계약(등록 → 회수 → 세션 교환) 클라이언트
  • bearer 자동 갱신 — 짧은 TTL 세션 토큰을 만료 전 재교환(MCP 고정 헤더 대응)

왜 Node에 암호가 있나: 에이전트는 위임 VC의 홀더라 자기 개인키로 KB-JWT/PoP를 로컬 서명해야 한다(원격 위임 시 홀더 바인딩이 깨짐). 검증자(RP)와 달리 홀더 암호는 오프로드할 수 없어, 에이전트가 도는 런타임(Node/MCP)에 있어야 한다. 홀더 제시 경로만·ES256 전용으로 표면을 최소화했고, 와이어 포맷은 platform-java와 크로스검증된다(아래).

CLI (레포 clone 없이 npx 한 줄)

# 등록 (최초 1회 — Briefick /publish 페어링 코드)
npx @metadium-did/platform-agent-js register --url <BRIEFICK_URL> --code <PAIRING_CODE>

npx @metadium-did/platform-agent-js did                        # 이 에이전트 did:jwk 출력
npx @metadium-did/platform-agent-js session --url <BRIEFICK_URL>   # 위임 세션 bearer 1회 발급(stdout)
npx @metadium-did/platform-agent-js credentials clear --url <BRIEFICK_URL>  # 캐시된 위임 VC 삭제(철회 후 재발급 대기 전환)

서버-로컬 상태 불일치 복구(0.2.4) — RP가 등록을 회수했거나 사용자가 위임을 철회한 뒤에도 CLI가 원인 있는 안내로 복구를 돕는다: ① register--code가 주어지면 로컬 "이미 등록됨" 기록과 무관하게 서버에 등록(회수 후 재등록) ② 세션 401은 "새 페어링 코드로 register --force" 안내로 실패 ③ 세션이 위임 무효 사유로 거부되면 캐시를 자동 폐기하고 지갑 재발급 승인 대기로 전환 후 1회 재시도 ④ 세션 pending 타임아웃 시 credentials clear 안내.

만료 요청 구분(0.2.5) — 재발급 대기 중 요청이 만료되면(RP status:"expired" 또는 lastRequest.expiresAt 경과, 하위호환) "승인 대기" 대신 "요청이 만료됐습니다 — /publish에서 위임을 다시 발급하세요" 를 표시한다(대기 중 만료로 전환되는 순간도 감지). 401 안내에는 RP가 내려주는 서버 사유(error)를 함께 표기한다.

--url/--code는 환경변수 BRIEFICK_URL/PAIRING_CODE로도 대체 가능.

did/register/proxy는 에이전트 지문(sha256(did:jwk) hex 앞 10자리)을 함께 출력한다 — 모든 did:jwk는 앞자리가 같아 육안 구분이 안 되므로, Briefick /publish가 표시하는 지문과 1:1 대조해 어느 에이전트로 발급하는지 확인한다. 위임 회수 대기 중에는 RP의 세분화 신호로 안내를 분기한다: no_request(이 에이전트로 발급된 위임 없음 — /publish에서 지문 확인) / pending+lastRequest(요청 있음 — 지갑 승인·전달 대기, 타임아웃 시 지갑 callback 전달 실패 의심 안내).

키 영속(최초 1회만 등록, 이후 재사용) — 키는 ~/.metapass-agent/key.json(파일 0600, 디렉터리 0700)에 저장된다. 재실행 시 같은 did:jwk를 재사용하므로 매번 새 에이전트로 등록되지 않는다. register는 이미 등록된 URL이면 자동으로 재등록을 건너뛴다(다시 하려면 --force). 경로 변경: --key-file <PATH> 또는 METAPASS_AGENT_KEY_FILE. 개인키는 이 저장소에만 있고 네트워크로 나가지 않는다.

키 저장 보안 — 로드 시 파일 권한을 검사해 소유자 외 접근 가능(0600 아님)이면 ssh처럼 거부한다 (chmod 600 안내). 평문 파일을 원치 않으면 OS 키체인 백엔드를 쓴다:

npx @metadium-did/platform-agent-js did --key-backend keychain   # 또는 env METAPASS_AGENT_KEY_BACKEND=keychain

macOS는 Keychain(security), Linux는 libsecret(secret-tool)에 저장하며 평문 파일이 남지 않는다. 기존 key.json이 있으면 최초 1회 자동으로 키체인에 이관한다(이관 후 파일 삭제 권장). 키가 유출돼도 에이전트가 얻는 것은 위임된 scope 안의 짧은 TTL 세션뿐이고, 지갑에서 위임을 철회하면 즉시 무효다 — 위임 발급 시 scope·기한을 최소로 잡는 것이 가장 효과적인 방어다.

로컬 프록시 모드 — Claude Code 연동 (방식 b)

Claude Code(MCP 클라이언트)는 고정 Authorization 헤더만 지원하는데 위임 bearer는 짧은 TTL로 갱신된다. 로컬 프록시를 띄우면 "고정 헤더 → 최신 bearer 주입"으로 궁합을 맞춘다.

Claude Code ──(고정 헤더, localhost)──▶ 프록시 ──(최신 bearer 주입)──▶ https://…/api/mcp
# 1) 프록시 실행(포그라운드) — 저장된 위임 VC로 세션 bearer 자동 갱신·주입
npx @metadium-did/platform-agent-js proxy --url <BRIEFICK_URL> [--port 8787]

# 2) Claude Code에 그 로컬 프록시를 MCP로 등록(다른 터미널)
claude mcp add --transport http briefick http://127.0.0.1:8787/mcp
  • 127.0.0.1 전용(로컬), 기본 포트 8787(--port), 대상 MCP 경로 기본 /api/mcp(--mcp-path).
  • 투명 포워딩: 메서드·본문·헤더·응답 스트림(SSE 포함) 그대로, Authorization만 최신 bearer로 덮어쓴다.
  • 만료/철회: RP가 401/거부를 내면 프록시는 그대로 전달(자체 판단 안 함). bearer는 계속 갱신되므로 다음 요청은 새 토큰.
  • 포그라운드 실행(Ctrl+C 종료). 상시 데몬은 launchd/pm2 등으로 감싸면 됨. 첫 실행 시 위임 VC 회수(지갑 승인) 후 ~/.metapass-agent/key.json에 저장 → 재기동 시 재회수 불필요.

설치 (라이브러리)

npm install @metadium-did/platform-agent-js

빠른 시작

import { AgentKey, BriefickAgentClient, AgentAuth } from "@metadium-did/platform-agent-js";

// 1) 에이전트 키(최초 1회 생성 후 파일로 영속 — 같은 did:jwk 유지)
const key = await AgentKey.generate();
console.log("이 에이전트 DID:", key.did);        // did:jwk:...  (Briefick UI에 등록)
// fs.writeFileSync("agent-key.json", JSON.stringify(key.exportPrivateJwk()));
// const key = await AgentKey.fromPrivateJwk(JSON.parse(fs.readFileSync("agent-key.json","utf8")));

const client = new BriefickAgentClient({ baseUrl: process.env.BRIEFICK_URL!, key });

// 2) 등록 — 사용자가 Briefick /publish 에서 발급한 페어링 코드로 바인딩(PoP)
await client.register(process.env.PAIRING_CODE!);

// 3) 사용자가 지갑에서 위임을 승인하면, 위임 VC를 회수(폴링)
const credential = await client.waitForDelegation();

// 4) 세션 bearer 교환 + 만료 전 자동 갱신
const auth = new AgentAuth({
  client,
  credential,
  onRefresh: (bearer) => console.log("새 세션 bearer:", bearer), // MCP 고정 헤더에 반영
});
await auth.start();

// 5) 이후 MCP 호출은 항상 유효한 bearer로
await fetch(process.env.BRIEFICK_URL + "/api/mcp", { headers: auth.authHeader() });

라이브러리 API — import해서 bearer 받기

프로그램적 진입점: ESM dist/index.js + 타입 dist/index.d.ts. bearer는 AgentAuth(자동 갱신) 또는 AgentClient.exchange(1회)로 받는다.

import { AgentKey, AgentClient, AgentAuth, loadStore, defaultKeyFile } from "@metadium-did/platform-agent-js";

// CLI가 저장한 키/위임 VC 재사용
const store = loadStore(defaultKeyFile())!;
const key = await AgentKey.fromPrivateJwk(store.privateJwk);
const client = new AgentClient({ baseUrl: "https://briefick.cplabs.io", key });
const credential = store.credentials!["https://briefick.cplabs.io"]; // 회수·저장된 위임 VC

// (a) 자동 갱신 — bearer()/authHeader()
const auth = new AgentAuth({ client, credential });
await auth.start();
auth.bearer();        // string  — 현재 세션 bearer
auth.authHeader();    // { Authorization: "Bearer …" }
auth.stop();

// (b) 1회 교환
const r = await client.exchange(credential);  // { status:"issued", bearer, expiresAt, scope }

서비스 중립 (다른 RP)

AgentClient는 엔드포인트 경로·PoP aud설정으로 받는다(기본값 = Briefick 계약). 다른 서비스는 service만 지정:

new AgentClient({ baseUrl, key, service: {
  registerPath: "/v2/agents/enroll",
  retrievePath: "/v2/agents/delegation",
  sessionStartPath: "/v2/agents/session/start",
  sessionCompletePath: "/v2/agents/session/complete",
  popAudience: { register: "acme-enroll", retrieve: "acme-retrieve", session: "acme-session" },
  mcpPath: "/v2/mcp",
}});

BriefickAgentClient는 기본값 프리셋 별칭(=== AgentClient)이라 하위호환된다. 홀더 암호(AgentKey·presentVpTokenAgentAuth·startProxy는 서비스와 무관한 범용 코어다.

흐름 (Briefick 기본 계약)

등록   POST /api/agent/register          {didJwk, code, pop(aud=briefick-agent-register)}
회수   POST /api/agent/delegation/retrieve {didJwk, pop(aud=briefick-agent-retrieve)}  → {credential}
세션   POST /api/agent/session/start      {didJwk, pop(aud=briefick-agent-session)}    → {state, nonce, responseUri}
       (위임 VP를 sso responseUri에 제시)  POST {vpToken}
       POST /api/agent/session/complete   {state, didJwk, pop}                          → {bearer, expiresAt, scope}

PoP는 등록할 did:jwk 개인키로 서명한 ES256 JWT(aud 스코핑 + iat). 세션 bearer는 짧은 TTL이라 AgentAuth가 만료 전 재교환한다. MCP 클라이언트는 고정 헤더 하나만 두고, onRefresh로 값만 갱신.

배포 측 값 (Briefick env)

  • METAPASS_DELEGATION_VCT = https://sso.cplabs.io/creds/delegation/worklog/v1 (등록된 위임 vct)
  • METAPASS_DELEGATION_ADMIN_KEY = sso.cplabs.io 배포 시 설정한 PLATFORM_SECURITY_API_KEY (New-Platform이 "발급"하는 값이 아니라 그 검증자 인스턴스의 env 비밀).

와이어 포맷 패리티

did:jwk(정준 JWK 순서), SD-JWT VC 제시(core = issuerJwt~disc~…~, sd_hash = base64url(SHA-256(ASCII(core)))), KB-JWT(typ=kb+jwt, {iat,aud,nonce,sd_hash})는 platform-java와 바이트 일치해야 한다.

  • 자체 검증: npm test
  • 크로스검증: platform-java AgentJsParityTest — Java가 발급한 위임 VC를 이 클라이언트가 제시하고 VerifierCore.verify가 수락함을 확인(홀더 제시 경로 3-런타임 불변식). node 설치 시 자동 실행.

범위

ES256/P-256, 홀더 제시 경로 전용(발급·검증은 플랫폼 몫). 다른 곡선·발급 로직은 미지원.