@agentic-passport/next 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/dist/clerk.d.ts +137 -0
- package/dist/clerk.d.ts.map +1 -0
- package/dist/clerk.js +110 -0
- package/dist/clerk.js.map +1 -0
- package/dist/handler.d.ts +71 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +516 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/is-agent-request.d.ts +17 -0
- package/dist/is-agent-request.d.ts.map +1 -0
- package/dist/is-agent-request.js +28 -0
- package/dist/is-agent-request.js.map +1 -0
- package/dist/next-adapter.d.ts +230 -0
- package/dist/next-adapter.d.ts.map +1 -0
- package/dist/next-adapter.js +270 -0
- package/dist/next-adapter.js.map +1 -0
- package/dist/stores.d.ts +35 -0
- package/dist/stores.d.ts.map +1 -0
- package/dist/stores.js +175 -0
- package/dist/stores.js.map +1 -0
- package/dist/types.d.ts +159 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
package/dist/stores.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State store implementations.
|
|
3
|
+
* - inMemoryStore() — default; per-instance Map-backed; fine for tests + single-isolate dev
|
|
4
|
+
* - kvStore(kv) — Cloudflare Workers KV-backed; works across isolates
|
|
5
|
+
*/
|
|
6
|
+
import { publicKeyFromJwk } from '@agentic-passport/core';
|
|
7
|
+
// ---------- in-memory ----------
|
|
8
|
+
export function inMemoryStore() {
|
|
9
|
+
const keys = new Map();
|
|
10
|
+
const revoked = new Set();
|
|
11
|
+
const nonces = new Map(); // key|nonce -> expiresAt
|
|
12
|
+
const mandateJtis = new Map();
|
|
13
|
+
const dpopJtis = new Map();
|
|
14
|
+
const agents = new Map();
|
|
15
|
+
const rateLimitTimestamps = new Map();
|
|
16
|
+
const NONCE_TTL_MS = 300_000;
|
|
17
|
+
const sweep = (m) => {
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
for (const [k, v] of m)
|
|
20
|
+
if (v <= now)
|
|
21
|
+
m.delete(k);
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
async registerKey(keyId, jwk) {
|
|
25
|
+
keys.set(keyId, publicKeyFromJwk(jwk));
|
|
26
|
+
},
|
|
27
|
+
async resolveKey(keyId) {
|
|
28
|
+
return keys.get(keyId) ?? null;
|
|
29
|
+
},
|
|
30
|
+
async isKeyRevoked(keyId) {
|
|
31
|
+
return revoked.has(keyId);
|
|
32
|
+
},
|
|
33
|
+
async revokeKey(keyId) {
|
|
34
|
+
revoked.add(keyId);
|
|
35
|
+
},
|
|
36
|
+
async putAgent(agentId, value) {
|
|
37
|
+
agents.set(agentId, value);
|
|
38
|
+
},
|
|
39
|
+
async getAgent(agentId) {
|
|
40
|
+
return agents.get(agentId) ?? null;
|
|
41
|
+
},
|
|
42
|
+
async isNonceSeen(keyId, nonce) {
|
|
43
|
+
sweep(nonces);
|
|
44
|
+
return nonces.has(`${keyId}\x00${nonce}`);
|
|
45
|
+
},
|
|
46
|
+
async rememberNonce(keyId, nonce) {
|
|
47
|
+
nonces.set(`${keyId}\x00${nonce}`, Date.now() + NONCE_TTL_MS);
|
|
48
|
+
},
|
|
49
|
+
async isMandateJtiUsed(jti) {
|
|
50
|
+
sweep(mandateJtis);
|
|
51
|
+
return mandateJtis.has(jti);
|
|
52
|
+
},
|
|
53
|
+
async rememberMandateJti(jti, expSec) {
|
|
54
|
+
mandateJtis.set(jti, expSec * 1000);
|
|
55
|
+
},
|
|
56
|
+
async isDpopJtiSeen(jti) {
|
|
57
|
+
sweep(dpopJtis);
|
|
58
|
+
return dpopJtis.has(jti);
|
|
59
|
+
},
|
|
60
|
+
async rememberDpopJti(jti, expSec) {
|
|
61
|
+
dpopJtis.set(jti, expSec * 1000);
|
|
62
|
+
},
|
|
63
|
+
async recordRegisterAttempt(keyId) {
|
|
64
|
+
const cutoff = Date.now() - 60_000;
|
|
65
|
+
const arr = (rateLimitTimestamps.get(keyId) ?? []).filter((t) => t > cutoff);
|
|
66
|
+
arr.push(Date.now());
|
|
67
|
+
rateLimitTimestamps.set(keyId, arr);
|
|
68
|
+
return arr.length;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const KEY_PREFIX = 'k:'; // agent public JWK by keyId
|
|
73
|
+
const REVOKED_PREFIX = 'r:'; // revocation list
|
|
74
|
+
const AGENT_PREFIX = 'a:'; // agent record by agent_id
|
|
75
|
+
const NONCE_PREFIX = 'n:'; // seen nonces
|
|
76
|
+
const MJTI_PREFIX = 'm:'; // consumed mandate jtis
|
|
77
|
+
const DJTI_PREFIX = 'd:'; // seen dpop jtis
|
|
78
|
+
const RL_PREFIX = 'rl:'; // rate-limit counters
|
|
79
|
+
const NONCE_TTL_SEC = 300;
|
|
80
|
+
/**
|
|
81
|
+
* KV-backed state store. Use on Cloudflare Workers / Pages.
|
|
82
|
+
*
|
|
83
|
+
* Two namespaces are recommended:
|
|
84
|
+
* - state: persistent (keys, agents, revocation)
|
|
85
|
+
* - cache: ephemeral (nonces, jtis, rate-limit) — falls back to `state` if omitted
|
|
86
|
+
*
|
|
87
|
+
* Limits to be aware of:
|
|
88
|
+
* - KV writes are eventually consistent (≤60s globally). v0 demo: same-region requests
|
|
89
|
+
* usually see fresh writes within ~1s. For multi-region production, consider Durable Objects.
|
|
90
|
+
* - Each operation = 1 KV op = real cost / rate limit.
|
|
91
|
+
*/
|
|
92
|
+
export function kvStore(opts) {
|
|
93
|
+
const state = opts.state;
|
|
94
|
+
const cache = opts.cache ?? opts.state;
|
|
95
|
+
return {
|
|
96
|
+
async registerKey(keyId, jwk) {
|
|
97
|
+
await state.put(`${KEY_PREFIX}${keyId}`, JSON.stringify(jwk));
|
|
98
|
+
},
|
|
99
|
+
async resolveKey(keyId) {
|
|
100
|
+
const raw = await state.get(`${KEY_PREFIX}${keyId}`);
|
|
101
|
+
if (!raw)
|
|
102
|
+
return null;
|
|
103
|
+
try {
|
|
104
|
+
return publicKeyFromJwk(JSON.parse(raw));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
async isKeyRevoked(keyId) {
|
|
111
|
+
const raw = await state.get(`${REVOKED_PREFIX}${keyId}`);
|
|
112
|
+
return raw === '1';
|
|
113
|
+
},
|
|
114
|
+
async revokeKey(keyId) {
|
|
115
|
+
await state.put(`${REVOKED_PREFIX}${keyId}`, '1');
|
|
116
|
+
},
|
|
117
|
+
async putAgent(agentId, value) {
|
|
118
|
+
await state.put(`${AGENT_PREFIX}${agentId}`, JSON.stringify(value));
|
|
119
|
+
},
|
|
120
|
+
async getAgent(agentId) {
|
|
121
|
+
const raw = await state.get(`${AGENT_PREFIX}${agentId}`);
|
|
122
|
+
if (!raw)
|
|
123
|
+
return null;
|
|
124
|
+
try {
|
|
125
|
+
return JSON.parse(raw);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
async isNonceSeen(keyId, nonce) {
|
|
132
|
+
const v = await cache.get(`${NONCE_PREFIX}${keyId}:${nonce}`);
|
|
133
|
+
return v !== null;
|
|
134
|
+
},
|
|
135
|
+
async rememberNonce(keyId, nonce) {
|
|
136
|
+
await cache.put(`${NONCE_PREFIX}${keyId}:${nonce}`, '1', { expirationTtl: NONCE_TTL_SEC });
|
|
137
|
+
},
|
|
138
|
+
async isMandateJtiUsed(jti) {
|
|
139
|
+
const v = await cache.get(`${MJTI_PREFIX}${jti}`);
|
|
140
|
+
return v !== null;
|
|
141
|
+
},
|
|
142
|
+
async rememberMandateJti(jti, expSec) {
|
|
143
|
+
const ttl = Math.max(60, expSec - Math.floor(Date.now() / 1000));
|
|
144
|
+
await cache.put(`${MJTI_PREFIX}${jti}`, '1', { expirationTtl: ttl });
|
|
145
|
+
},
|
|
146
|
+
async isDpopJtiSeen(jti) {
|
|
147
|
+
const v = await cache.get(`${DJTI_PREFIX}${jti}`);
|
|
148
|
+
return v !== null;
|
|
149
|
+
},
|
|
150
|
+
async rememberDpopJti(jti, expSec) {
|
|
151
|
+
const ttl = Math.max(60, expSec - Math.floor(Date.now() / 1000));
|
|
152
|
+
await cache.put(`${DJTI_PREFIX}${jti}`, '1', { expirationTtl: ttl });
|
|
153
|
+
},
|
|
154
|
+
async recordRegisterAttempt(keyId) {
|
|
155
|
+
// KV doesn't support atomic increments. Read-modify-write here is best-effort:
|
|
156
|
+
// multiple concurrent calls may under-count. For v0 + per-key rate limits that's
|
|
157
|
+
// acceptable; for production, use Durable Objects or Workers Rate Limiting API.
|
|
158
|
+
const raw = (await cache.get(`${RL_PREFIX}${keyId}`)) ?? '[]';
|
|
159
|
+
let arr;
|
|
160
|
+
try {
|
|
161
|
+
arr = JSON.parse(raw);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
arr = [];
|
|
165
|
+
}
|
|
166
|
+
const cutoff = Date.now() - 60_000;
|
|
167
|
+
const filtered = arr.filter((t) => t > cutoff);
|
|
168
|
+
filtered.push(Date.now());
|
|
169
|
+
await cache.put(`${RL_PREFIX}${keyId}`, JSON.stringify(filtered), { expirationTtl: 120 });
|
|
170
|
+
return filtered.length;
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
void null;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=stores.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../src/stores.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { JSONWebKeySet, JWK } from 'jose';
|
|
2
|
+
import type { KeyObject } from 'node:crypto';
|
|
3
|
+
import type { ErrorCode, MandateClaims } from '@agentic-passport/protocol';
|
|
4
|
+
export type AgentSignupContext = {
|
|
5
|
+
agentId: string;
|
|
6
|
+
mandate: MandateClaims;
|
|
7
|
+
request: {
|
|
8
|
+
method: string;
|
|
9
|
+
url: string;
|
|
10
|
+
headers: Readonly<Record<string, string | undefined>>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export type AgentSignupResult = {
|
|
14
|
+
allow: boolean;
|
|
15
|
+
principal?: {
|
|
16
|
+
userId: string;
|
|
17
|
+
grantedScopes: string[];
|
|
18
|
+
};
|
|
19
|
+
reason?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Context passed to onAgentSessionMint. Includes the verified agent record
|
|
23
|
+
* (after AgentPassport signature + mandate checks have passed) and the user
|
|
24
|
+
* the vendor mapped them to in onAgentSignup. The vendor uses `userId` to
|
|
25
|
+
* mint a session in their own auth system.
|
|
26
|
+
*/
|
|
27
|
+
export type AgentSessionMintContext = {
|
|
28
|
+
agentId: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
scopes: readonly string[];
|
|
31
|
+
mandateJti: string;
|
|
32
|
+
actor?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Browser-handoff result. The agent's browser navigates to `bootstrap_url`;
|
|
36
|
+
* the vendor's auth provider mints its session cookie in that browser
|
|
37
|
+
* context. From that point on, the browser is signed in to the vendor
|
|
38
|
+
* exactly as a human would be after going through the equivalent flow.
|
|
39
|
+
*
|
|
40
|
+
* `bootstrap_url` should be one-time-use and short-lived (≤5 min). Vendor
|
|
41
|
+
* is responsible for revoking unused tokens.
|
|
42
|
+
*
|
|
43
|
+
* Optional `final_url` lets the vendor tell the agent where to land
|
|
44
|
+
* after the bootstrap completes — defaults to the vendor origin.
|
|
45
|
+
*/
|
|
46
|
+
export type AgentSessionMintResult = {
|
|
47
|
+
bootstrap_url: string;
|
|
48
|
+
final_url?: string;
|
|
49
|
+
};
|
|
50
|
+
export type PaymentChallenge = {
|
|
51
|
+
rail: 'free';
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Storage backend for cross-request gate state.
|
|
55
|
+
*
|
|
56
|
+
* v0 default: inMemoryStore() — fine for single-instance dev / tests.
|
|
57
|
+
* Production / serverless: provide a KV-backed implementation. Each isolate
|
|
58
|
+
* sees the same state via the store, eliminating module-scope state issues.
|
|
59
|
+
*/
|
|
60
|
+
export interface AgentStateStore {
|
|
61
|
+
registerKey(keyId: string, jwk: JWK): Promise<void>;
|
|
62
|
+
resolveKey(keyId: string): Promise<KeyObject | null>;
|
|
63
|
+
isKeyRevoked(keyId: string): Promise<boolean>;
|
|
64
|
+
revokeKey(keyId: string): Promise<void>;
|
|
65
|
+
putAgent(agentId: string, value: AgentRecord): Promise<void>;
|
|
66
|
+
getAgent(agentId: string): Promise<AgentRecord | null>;
|
|
67
|
+
isNonceSeen(keyId: string, nonce: string): Promise<boolean>;
|
|
68
|
+
rememberNonce(keyId: string, nonce: string): Promise<void>;
|
|
69
|
+
isMandateJtiUsed(jti: string): Promise<boolean>;
|
|
70
|
+
rememberMandateJti(jti: string, exp: number): Promise<void>;
|
|
71
|
+
isDpopJtiSeen(jti: string): Promise<boolean>;
|
|
72
|
+
rememberDpopJti(jti: string, exp: number): Promise<void>;
|
|
73
|
+
recordRegisterAttempt(keyId: string): Promise<number>;
|
|
74
|
+
}
|
|
75
|
+
export type AgentRecord = {
|
|
76
|
+
granted_scopes: string[];
|
|
77
|
+
mandate_jti: string;
|
|
78
|
+
user_id: string;
|
|
79
|
+
actor?: string;
|
|
80
|
+
};
|
|
81
|
+
export type AgentPassportConfig = {
|
|
82
|
+
/** Vendor's origin (used as JWT aud, signature URL canonicalisation). */
|
|
83
|
+
vendorOrigin: string;
|
|
84
|
+
/** Issuer URLs whose mandate signatures we trust. SDK fetches their JWKS automatically. */
|
|
85
|
+
trustedIssuers: string[];
|
|
86
|
+
/** Scope vocabulary the vendor exposes (advertised in discovery doc). */
|
|
87
|
+
scopes: string[];
|
|
88
|
+
/** Optional human-readable vendor name (discovery doc). */
|
|
89
|
+
vendorName?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Pre-loaded JWKS by issuer URL. Optional — if omitted, the SDK fetches
|
|
92
|
+
* each issuer's `/.well-known/jwks.json` on first use and caches it.
|
|
93
|
+
* Provide explicitly for air-gapped deployments or when you want to
|
|
94
|
+
* pin a JWKS snapshot.
|
|
95
|
+
*/
|
|
96
|
+
jwksByIssuer?: Map<string, JSONWebKeySet>;
|
|
97
|
+
/** Hooks the vendor implements (the "agent UX" surface). */
|
|
98
|
+
hooks: {
|
|
99
|
+
onAgentSignup: (ctx: AgentSignupContext) => Promise<AgentSignupResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Browser-handoff: produce a one-time URL that, when navigated to by
|
|
102
|
+
* a real browser context (Playwright, Puppeteer), causes the vendor's
|
|
103
|
+
* auth provider to mint its own session in that browser. After
|
|
104
|
+
* navigation, the browser has a legitimate provider session — same
|
|
105
|
+
* mechanism a human would acquire via their own sign-in flow.
|
|
106
|
+
*
|
|
107
|
+
* Why a URL and not a cookie value: auth providers (Clerk, Auth.js,
|
|
108
|
+
* WorkOS, Auth0) mint session cookies only as the result of a
|
|
109
|
+
* sign-in event in *their* frontend. They expose this surface via a
|
|
110
|
+
* one-time sign-in token + redirect URL — designed for password-
|
|
111
|
+
* reset, magic-link, and impersonation flows. We use exactly that
|
|
112
|
+
* primitive: the agent's browser visits the URL, the provider
|
|
113
|
+
* recognises the token, mints the session cookie, and lands the
|
|
114
|
+
* browser on the requested destination.
|
|
115
|
+
*
|
|
116
|
+
* This hook is ONLY meaningful for browser-based agents (run via
|
|
117
|
+
* @agentic-passport/agent-browser). HTTP-only agents ignore it and use the
|
|
118
|
+
* vendor's getSession()-aware API routes directly.
|
|
119
|
+
*
|
|
120
|
+
* For Clerk:
|
|
121
|
+
*
|
|
122
|
+
* onAgentSessionMint: async ({ userId }) => {
|
|
123
|
+
* const client = await clerkClient();
|
|
124
|
+
* const t = await client.signInTokens.createSignInToken({ userId, expiresInSeconds: 300 });
|
|
125
|
+
* return { bootstrap_url: t.url };
|
|
126
|
+
* }
|
|
127
|
+
*/
|
|
128
|
+
onAgentSessionMint?: (ctx: AgentSessionMintContext) => Promise<AgentSessionMintResult>;
|
|
129
|
+
onPaymentRequired?: () => PaymentChallenge;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Optional pre-built state store. Defaults to inMemoryStore().
|
|
133
|
+
* Provide kvStore(env) when running on Cloudflare Workers.
|
|
134
|
+
*/
|
|
135
|
+
store?: AgentStateStore;
|
|
136
|
+
/**
|
|
137
|
+
* Optional PKCS8 PEM (or base64-encoded PKCS8 PEM) for the gate's token
|
|
138
|
+
* signing key. If omitted, a fresh keypair is generated per agentPassport()
|
|
139
|
+
* call — which is fine for tests but BROKEN on multi-isolate deployments
|
|
140
|
+
* because each isolate would sign with a different key.
|
|
141
|
+
*/
|
|
142
|
+
tokenSigningKeyPem?: string;
|
|
143
|
+
};
|
|
144
|
+
export type AgentPrincipal = {
|
|
145
|
+
type: 'agent';
|
|
146
|
+
agentId: string;
|
|
147
|
+
scopes: readonly string[];
|
|
148
|
+
mandateJti: string;
|
|
149
|
+
};
|
|
150
|
+
export type HumanPrincipal = {
|
|
151
|
+
type: 'human';
|
|
152
|
+
userId: string;
|
|
153
|
+
scopes?: readonly string[];
|
|
154
|
+
};
|
|
155
|
+
export type Session = AgentPrincipal | HumanPrincipal;
|
|
156
|
+
export type { ErrorCode };
|
|
157
|
+
/** @deprecated Use {@link AgentPassportConfig}. */
|
|
158
|
+
export type AgentGateConfig = AgentPassportConfig;
|
|
159
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentic-passport/next",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "AgentAuth adapter for Next.js — sidecar middleware + route handler factories.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./edge": {
|
|
15
|
+
"types": "./dist/is-agent-request.d.ts",
|
|
16
|
+
"import": "./dist/is-agent-request.js"
|
|
17
|
+
},
|
|
18
|
+
"./clerk": {
|
|
19
|
+
"types": "./dist/clerk.d.ts",
|
|
20
|
+
"import": "./dist/clerk.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"typesVersions": {
|
|
24
|
+
"*": {
|
|
25
|
+
"edge": [
|
|
26
|
+
"dist/is-agent-request.d.ts"
|
|
27
|
+
],
|
|
28
|
+
"clerk": [
|
|
29
|
+
"dist/clerk.d.ts"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"next": ">=14.0.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"next": {
|
|
42
|
+
"optional": false
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"jose": "^6.2.3",
|
|
47
|
+
"@agentic-passport/protocol": "0.3.0",
|
|
48
|
+
"@agentic-passport/core": "0.3.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"next": "^16.2.6",
|
|
52
|
+
"react": "^19.2.0",
|
|
53
|
+
"typescript": "^5.7.3",
|
|
54
|
+
"vitest": "^4.1.6"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc -p tsconfig.json",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"test:unit": "vitest run",
|
|
60
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
61
|
+
"clean": "rm -rf dist .turbo"
|
|
62
|
+
}
|
|
63
|
+
}
|