@atps/ztnp
v0.1.0-alpha.0
Published
Official TypeScript library for ZTNP (Zero-Trust Negotiation Protocol): posture assertions, permits, and trust policy evaluation.
Downloads
34
Maintainers
Readme
@atps/ztnp
Official TypeScript library for ZTNP (Zero-Trust Negotiation Protocol), tracking draft-miller-ztnp-00.
Pre-1.0 alpha. APIs may change before the stable release. Pin an exact version if you depend on this in non-experimental code.
Part of the Agent Trust Protocol Stack. Depends on @atps/core.
What this package provides
- Posture Assertion verification —
verifyPostureAssertion: JWS verification, freshness,bind.nonce,scope.targetmatching, structured reason codes. - Permit creation and validation —
createPermit(signed, takes aPermitSigner),validatePermit, plus the unsigned demo pathcreateUnsignedDemoPermit/verifyUnsignedDemoPermitused by the Local Agent Trust Lab. - Trust policy evaluation —
evaluateTrustPolicy: combines permit, agent identity, tool identity, posture claim, and policy into a singleZtnpDecision.
What this package does NOT do
- Sign Posture Assertions (use a signing library directly).
- Provide a built-in
PermitSigner(callers wire their own JOSE-backed signer). - Handle
nonce_sigbinding (optional per spec §5.5). - Handle revocation.
- Validate
framework_idagainst the IANA registry (caller MUST check). - Verify TLS channel binding (caller MUST check using the live TLS exporter).
Install and test
# from repo root, npm workspaces handles installation
npm install
# run package tests
npm test --workspace packages/ztnpMinimal usage
Verify a Posture Assertion
import { verifyPostureAssertion } from "@atps/ztnp";
const result = await verifyPostureAssertion({
postureAssertionJws: "<signed PA>",
challengeNonce: "<the nonce R sent>",
ctx: "mcp",
aud: "agent:requester-test",
intendedTarget: "https://api.test-corp.example/agents/data-processor",
iks: { /* Issuer Key Set */ },
now: Math.floor(Date.now() / 1000),
skewSeconds: 300,
});
if (result.valid) {
// feed result.payload into evaluateTrustPolicy
} else {
console.log("Rejected:", result.reasonCodes);
}Create and evaluate a permit (demo path)
import { createUnsignedDemoPermit, evaluateTrustPolicy } from "@atps/ztnp";
const permit = createUnsignedDemoPermit({
iss: "requester:demo",
sub: "agent:summarizer",
ttlSeconds: 300,
constraints: {
actions: ["read", "summarize"],
tools: ["clinicalNotes.read"],
data: ["internal"],
},
});
const decision = evaluateTrustPolicy({
permit,
agent: { id: "agent:summarizer" },
tool: { name: "clinicalNotes.read" },
posture: {
framework_id: "https://doi.org/10.6028/NIST.AI.100-1",
tier: 3,
flags: { critical_open: false },
},
policy: {
required_tier_min: 2,
allowed_tools: ["clinicalNotes.read"],
},
});decision.allow is true / false; decision.reason is one of the ZTNP_* reason codes.
Channel binding (Section 8.2 of the spec) is mandatory when transport is TLS but is enforced in the calling layer where TLS exporter material is available — ch_binding.method defaults to "none" with a local-demo rationale in the unsigned demo path.
