vestauth 0.11.2 → 0.12.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/CHANGELOG.md CHANGED
@@ -2,9 +2,16 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- [Unreleased](https://github.com/vestauth/vestauth/compare/v0.11.1...main)
5
+ [Unreleased](https://github.com/vestauth/vestauth/compare/v0.12.0...main)
6
6
 
7
- ## [0.11.1](https://github.com/vestauth/vestauth/compare/v0.11.0...v0.11.1) (2026-02-17)
7
+ ## [0.12.0](https://github.com/vestauth/vestauth/compare/v0.11.2...v0.12.0) (2026-02-17)
8
+
9
+ ### Added
10
+
11
+ * Add `--hostname` flag for `agent init` ([#17](https://github.com/vestauth/vestauth/pull/17) & [#18](https://github.com/vestauth/vestauth/pull/18))
12
+ * Add types file ([#16](https://github.com/vestauth/vestauth/pull/16))
13
+
14
+ ## [0.11.2](https://github.com/vestauth/vestauth/compare/v0.11.0...v0.11.2) (2026-02-17)
8
15
 
9
16
  ### Removed
10
17
 
package/README.md CHANGED
@@ -208,6 +208,17 @@ $ vestauth agent init
208
208
  ⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]
209
209
  ```
210
210
 
211
+ </details>
212
+ <details><summary>`agent init --hostname`</summary><br>
213
+
214
+ Use `--hostname` to override the agent API hostname (defaults to `AGENT_HOSTNAME`, then `api.vestauth.com`):
215
+
216
+ ```sh
217
+ $ vestauth agent init --hostname https://vestauth.yoursite.com
218
+ ✔ agent created (.env/AGENT_UID=agent-609a4fd2ebf4e6347108c517)
219
+ ⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]
220
+ ```
221
+
211
222
  </details>
212
223
  <details><summary>`agent curl`</summary><br>
213
224
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vestauth",
3
- "version": "0.11.2",
3
+ "version": "0.12.0",
4
4
  "description": "auth for agents–from the creator of dotenvx",
5
5
  "keywords": [
6
6
  "vestauth",
@@ -23,8 +23,10 @@
23
23
  ],
24
24
  "license": "BSD-3-Clause",
25
25
  "main": "src/lib/main.js",
26
+ "types": "./src/lib/main.d.ts",
26
27
  "exports": {
27
28
  ".": {
29
+ "types": "./src/lib/main.d.ts",
28
30
  "require": "./src/lib/main.js",
29
31
  "default": "./src/lib/main.js"
30
32
  },
@@ -8,7 +8,7 @@ async function init () {
8
8
  const options = this.opts()
9
9
  logger.debug(`options: ${JSON.stringify(options)}`)
10
10
 
11
- const output = await agent.init()
11
+ const output = await agent.init(options.hostname)
12
12
 
13
13
  if (output.isNew) {
14
14
  logger.success(`✔ agent created (${output.path}/AGENT_UID=${output.AGENT_UID})`)
@@ -10,7 +10,7 @@ async function rotate () {
10
10
  logger.debug(`options: ${JSON.stringify(options)}`)
11
11
 
12
12
  const uid = options.uid || options.id || env('AGENT_UID') || env('AGENT_ID')
13
- const output = await agent.rotate(uid, options.privateJwk, options.tag, options.nonce)
13
+ const output = await agent.rotate(uid, options.privateJwk, options.tag, options.nonce, options.hostname)
14
14
 
15
15
  logger.success(`✔ agent keys rotated (${output.path}/AGENT_UID=${output.AGENT_UID})`)
16
16
  logger.help('⮕ next run: [vestauth agent curl https://api.vestauth.com/whoami]')
@@ -11,6 +11,7 @@ agent
11
11
  const initAction = require('./../actions/agent/init')
12
12
  agent.command('init')
13
13
  .description('create agent')
14
+ .option('--hostname <hostname>', 'agent API hostname')
14
15
  .action(initAction)
15
16
 
16
17
  // vestauth agent curl
@@ -42,6 +43,7 @@ agent.command('rotate')
42
43
  .description('rotate keypair')
43
44
  .option('--uid, --id <uid>', 'uid (string)', env('AGENT_UID') || env('AGENT_ID'))
44
45
  .option('--private-jwk <privateJwk>', 'AGENT_PRIVATE_JWK (default)', env('AGENT_PRIVATE_JWK'))
46
+ .option('--hostname <hostname>', 'agent API hostname')
45
47
  .option('--tag <tag>', 'web-bot-auth (default) | web-bot-auth', 'web-bot-auth')
46
48
  .option('--nonce <nonce>', 'null (default)')
47
49
  .option('--pp, --pretty-print', 'pretty print output')
@@ -2,10 +2,13 @@ const dotenvx = require('@dotenvx/dotenvx')
2
2
  const identity = require('./identity')
3
3
  const keypair = require('./keypair')
4
4
  const touch = require('./touch')
5
+ const normalizeAgentHostname = require('./normalizeAgentHostname')
5
6
  const PostRegister = require('../api/postRegister')
6
7
 
7
- async function agentInit () {
8
+ async function agentInit (hostname = null) {
8
9
  const envPath = '.env'
10
+ const normalizedHostname = normalizeAgentHostname(hostname)
11
+ const shouldPersistHostname = Boolean(hostname && String(hostname).trim())
9
12
 
10
13
  // keypair
11
14
  const currentPrivateJwk = identity(false).privateJwk
@@ -16,9 +19,12 @@ async function agentInit () {
16
19
  // must come before registration so that registration can send headers
17
20
  dotenvx.set('AGENT_PUBLIC_JWK', JSON.stringify(kp.publicJwk), { path: envPath, plain: true, quiet: true })
18
21
  dotenvx.set('AGENT_PRIVATE_JWK', JSON.stringify(kp.privateJwk), { path: envPath, plain: true, quiet: true })
22
+ if (shouldPersistHostname) {
23
+ dotenvx.set('AGENT_HOSTNAME', new URL(normalizedHostname).host, { path: envPath, plain: true, quiet: true })
24
+ }
19
25
 
20
26
  // register agent
21
- const agent = await new PostRegister(null, kp.publicJwk).run()
27
+ const agent = await new PostRegister(normalizedHostname, kp.publicJwk).run()
22
28
  dotenvx.set('AGENT_UID', agent.uid, { path: envPath, plain: true, quiet: true })
23
29
 
24
30
  return {
@@ -1,15 +1,17 @@
1
1
  const dotenvx = require('@dotenvx/dotenvx')
2
2
  const keypair = require('./keypair')
3
+ const normalizeAgentHostname = require('./normalizeAgentHostname')
3
4
  const PostRotate = require('../api/postRotate')
4
5
 
5
- async function agentRotate (uid, privateJwk, tag = 'web-bot-auth', nonce = null) {
6
+ async function agentRotate (uid, privateJwk, tag = 'web-bot-auth', nonce = null, hostname = null) {
6
7
  const envPath = '.env'
8
+ const rotateUrl = normalizeAgentHostname(hostname)
7
9
 
8
10
  // new keypair
9
11
  const newKp = keypair()
10
12
 
11
13
  // rotate jwk
12
- const agent = await new PostRotate(null, newKp.publicJwk, uid, privateJwk).run()
14
+ const agent = await new PostRotate(rotateUrl, newKp.publicJwk, uid, privateJwk).run()
13
15
 
14
16
  dotenvx.set('AGENT_PUBLIC_JWK', JSON.stringify(newKp.publicJwk), { path: envPath, plain: true, quiet: true })
15
17
  dotenvx.set('AGENT_PRIVATE_JWK', JSON.stringify(newKp.privateJwk), { path: envPath, plain: true, quiet: true })
@@ -0,0 +1,13 @@
1
+ function normalizeAgentHostname (hostname = null) {
2
+ const value = (hostname || process.env.AGENT_HOSTNAME || 'api.vestauth.com').trim()
3
+ const candidate = /^https?:\/\//i.test(value) ? value : `https://${value}`
4
+ const url = new URL(candidate)
5
+
6
+ if (url.pathname !== '/' || url.search || url.hash) {
7
+ throw new Error('invalid --hostname. path/query/hash are not allowed')
8
+ }
9
+
10
+ return url.origin
11
+ }
12
+
13
+ module.exports = normalizeAgentHostname
@@ -0,0 +1,138 @@
1
+ export type HttpMethod =
2
+ | 'GET'
3
+ | 'POST'
4
+ | 'PUT'
5
+ | 'PATCH'
6
+ | 'DELETE'
7
+ | 'OPTIONS'
8
+ | 'HEAD'
9
+ | (string & {})
10
+
11
+ export type HeaderValue = string | string[]
12
+ export type HeaderBag = Record<string, HeaderValue | undefined>
13
+
14
+ /** Minimal JWK shape used by Vestauth (Ed25519 OKP). */
15
+ export interface OkpEd25519PublicJwk {
16
+ kty: 'OKP'
17
+ crv: 'Ed25519'
18
+ x: string
19
+ kid?: string
20
+ [prop: string]: unknown
21
+ }
22
+
23
+ /** Minimal private JWK shape used by Vestauth (Ed25519 OKP). */
24
+ export interface OkpEd25519PrivateJwk extends OkpEd25519PublicJwk {
25
+ d: string
26
+ }
27
+
28
+ export type PublicJwk = OkpEd25519PublicJwk
29
+ export type PrivateJwk = OkpEd25519PrivateJwk
30
+
31
+ export interface Keypair {
32
+ publicJwk: PublicJwk
33
+ privateJwk: PrivateJwk
34
+ }
35
+
36
+ export interface SignatureHeaders {
37
+ Signature: string
38
+ 'Signature-Input': string
39
+ 'Signature-Agent': string
40
+ }
41
+
42
+ export interface VerifyResult {
43
+ uid?: string
44
+ kid?: string
45
+ public_jwk?: PublicJwk
46
+ well_known_url?: string
47
+ }
48
+
49
+ export interface AgentApi {
50
+ /**
51
+ * Creates (or reuses) an Ed25519 keypair, registers the agent, and writes to `.env`.
52
+ */
53
+ init(): Promise<{
54
+ AGENT_PUBLIC_JWK: PublicJwk
55
+ AGENT_UID: string
56
+ path: string
57
+ isNew: boolean
58
+ }>
59
+
60
+ /**
61
+ * Generates RFC 9421 request signature headers.
62
+ *
63
+ * When `uid` / `privateJwk` are omitted, Vestauth reads them from `.env`.
64
+ */
65
+ headers(
66
+ httpMethod: HttpMethod,
67
+ uri: string,
68
+ uid?: string | null,
69
+ privateJwk?: string | null,
70
+ tag?: string,
71
+ nonce?: string | null
72
+ ): Promise<SignatureHeaders>
73
+
74
+ /**
75
+ * Rotates the agent keypair and writes the new keys to `.env`.
76
+ */
77
+ rotate(
78
+ uid: string,
79
+ privateJwk: string,
80
+ tag?: string,
81
+ nonce?: string | null
82
+ ): Promise<{
83
+ AGENT_PUBLIC_JWK: PublicJwk
84
+ AGENT_UID: string
85
+ path: string
86
+ }>
87
+ }
88
+
89
+ export interface ProviderApi {
90
+ /**
91
+ * Verifies a signed request (fetching the agent's discovery keys when needed).
92
+ */
93
+ verify(httpMethod: HttpMethod, uri: string, headers?: HeaderBag): Promise<VerifyResult>
94
+ }
95
+
96
+ export interface PrimitivesApi {
97
+ /**
98
+ * Creates an Ed25519 keypair. If `existingPrivateJwk` is provided, it is reused.
99
+ */
100
+ keypair(existingPrivateJwk?: string, prefix?: string): Keypair
101
+
102
+ /**
103
+ * Generates RFC 9421 request signature headers.
104
+ */
105
+ headers(
106
+ httpMethod: HttpMethod,
107
+ uri: string,
108
+ uid: string,
109
+ privateJwk: string,
110
+ tag?: string,
111
+ nonce?: string | null
112
+ ): Promise<SignatureHeaders>
113
+
114
+ /**
115
+ * Verifies a signed request.
116
+ *
117
+ * When `publicJwk` is not provided, Vestauth will attempt to resolve it via
118
+ * `Signature-Agent` discovery.
119
+ */
120
+ verify(
121
+ httpMethod: HttpMethod,
122
+ uri: string,
123
+ headers?: HeaderBag,
124
+ publicJwk?: PublicJwk
125
+ ): Promise<VerifyResult>
126
+ }
127
+
128
+ export const agent: AgentApi
129
+ export const provider: ProviderApi
130
+ export const primitives: PrimitivesApi
131
+
132
+ declare const _default: {
133
+ agent: AgentApi
134
+ provider: ProviderApi
135
+ primitives: PrimitivesApi
136
+ }
137
+
138
+ export default _default