@auths-dev/sdk 0.0.1 → 0.1.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.
Files changed (60) hide show
  1. package/Cargo.toml +45 -0
  2. package/README.md +163 -4
  3. package/__test__/client.spec.ts +78 -0
  4. package/__test__/exports.spec.ts +57 -0
  5. package/__test__/integration.spec.ts +407 -0
  6. package/__test__/policy.spec.ts +202 -0
  7. package/__test__/verify.spec.ts +88 -0
  8. package/build.rs +5 -0
  9. package/index.d.ts +259 -0
  10. package/index.js +622 -1
  11. package/lib/artifacts.ts +124 -0
  12. package/lib/attestations.ts +126 -0
  13. package/lib/audit.ts +189 -0
  14. package/lib/client.ts +293 -0
  15. package/lib/commits.ts +70 -0
  16. package/lib/devices.ts +178 -0
  17. package/lib/errors.ts +306 -0
  18. package/lib/identity.ts +280 -0
  19. package/lib/index.ts +125 -0
  20. package/lib/native.ts +255 -0
  21. package/lib/org.ts +235 -0
  22. package/lib/pairing.ts +271 -0
  23. package/lib/policy.ts +669 -0
  24. package/lib/signing.ts +204 -0
  25. package/lib/trust.ts +152 -0
  26. package/lib/types.ts +179 -0
  27. package/lib/verify.ts +241 -0
  28. package/lib/witness.ts +91 -0
  29. package/npm/darwin-arm64/README.md +3 -0
  30. package/npm/darwin-arm64/package.json +23 -0
  31. package/npm/linux-arm64-gnu/README.md +3 -0
  32. package/npm/linux-arm64-gnu/package.json +26 -0
  33. package/npm/linux-x64-gnu/README.md +3 -0
  34. package/npm/linux-x64-gnu/package.json +26 -0
  35. package/npm/win32-arm64-msvc/README.md +3 -0
  36. package/npm/win32-arm64-msvc/package.json +23 -0
  37. package/npm/win32-x64-msvc/README.md +3 -0
  38. package/npm/win32-x64-msvc/package.json +23 -0
  39. package/package.json +51 -16
  40. package/src/artifact.rs +217 -0
  41. package/src/attestation_query.rs +104 -0
  42. package/src/audit.rs +128 -0
  43. package/src/commit_sign.rs +63 -0
  44. package/src/device.rs +212 -0
  45. package/src/diagnostics.rs +106 -0
  46. package/src/error.rs +5 -0
  47. package/src/helpers.rs +60 -0
  48. package/src/identity.rs +467 -0
  49. package/src/lib.rs +26 -0
  50. package/src/org.rs +430 -0
  51. package/src/pairing.rs +454 -0
  52. package/src/policy.rs +147 -0
  53. package/src/sign.rs +215 -0
  54. package/src/trust.rs +189 -0
  55. package/src/types.rs +205 -0
  56. package/src/verify.rs +447 -0
  57. package/src/witness.rs +138 -0
  58. package/tsconfig.json +19 -0
  59. package/typedoc.json +18 -0
  60. package/vitest.config.ts +12 -0
package/lib/client.ts ADDED
@@ -0,0 +1,293 @@
1
+ import { IdentityService, type GetPublicKeyOptions } from './identity'
2
+ import { DeviceService } from './devices'
3
+ import {
4
+ SigningService,
5
+ type SignResult,
6
+ type ActionEnvelope,
7
+ type SignAsIdentityOptions,
8
+ type SignActionAsIdentityOptions,
9
+ type SignAsAgentOptions,
10
+ type SignActionAsAgentOptions,
11
+ } from './signing'
12
+ import { OrgService } from './org'
13
+ import { TrustService } from './trust'
14
+ import { WitnessService } from './witness'
15
+ import { AttestationService } from './attestations'
16
+ import { ArtifactService } from './artifacts'
17
+ import { CommitService } from './commits'
18
+ import { AuditService } from './audit'
19
+ import { PairingService } from './pairing'
20
+ import { mapNativeError, CryptoError, VerificationError } from './errors'
21
+ import {
22
+ verifyAttestation,
23
+ verifyAttestationWithCapability,
24
+ verifyAtTime,
25
+ verifyAtTimeWithCapability,
26
+ verifyChain as verifyChainFn,
27
+ verifyChainWithCapability,
28
+ verifyChainWithWitnesses,
29
+ type VerificationResult,
30
+ type VerificationReport,
31
+ type WitnessConfig,
32
+ } from './verify'
33
+ import native from './native'
34
+
35
+ /** Configuration for the {@link Auths} client. */
36
+ export interface ClientConfig {
37
+ /** Path to the Auths Git registry. Defaults to `'~/.auths'`. */
38
+ repoPath?: string
39
+ /** Passphrase for key encryption. Can also be set via `AUTHS_PASSPHRASE` env var. */
40
+ passphrase?: string
41
+ }
42
+
43
+ /** Options for {@link Auths.verify}. */
44
+ export interface VerifyOptions {
45
+ /** JSON-serialized attestation to verify. */
46
+ attestationJson: string
47
+ /** Hex-encoded Ed25519 public key of the issuer. */
48
+ issuerKey: string
49
+ /** Optional capability the attestation must grant. */
50
+ requiredCapability?: string
51
+ /** Optional RFC 3339 timestamp to verify at. */
52
+ at?: string
53
+ }
54
+
55
+ /** Options for {@link Auths.verifyChain}. */
56
+ export interface VerifyChainOptions {
57
+ /** Array of JSON-serialized attestations (leaf to root). */
58
+ attestations: string[]
59
+ /** Hex-encoded Ed25519 public key of the root identity. */
60
+ rootKey: string
61
+ /** Optional capability the leaf attestation must grant. */
62
+ requiredCapability?: string
63
+ /** Optional witness configuration for receipt-based verification. */
64
+ witnesses?: WitnessConfig
65
+ }
66
+
67
+ /**
68
+ * Primary entry point for all Auths SDK operations.
69
+ *
70
+ * Provides access to identity management, device authorization, signing,
71
+ * verification, policy evaluation, organizations, and more through
72
+ * service properties.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * import { Auths } from '@auths-dev/sdk'
77
+ *
78
+ * const auths = new Auths()
79
+ *
80
+ * // Create an identity
81
+ * const identity = auths.identities.create({ label: 'laptop' })
82
+ *
83
+ * // Sign a message
84
+ * const sig = auths.signAs({
85
+ * message: Buffer.from('hello world'),
86
+ * identityDid: identity.did,
87
+ * })
88
+ * console.log(sig.signature) // hex-encoded Ed25519 signature
89
+ * ```
90
+ */
91
+ export class Auths {
92
+ /** Path to the Auths Git registry. */
93
+ readonly repoPath: string
94
+ /** Passphrase for key operations, if set. */
95
+ readonly passphrase: string | undefined
96
+
97
+ /** Identity management (create, rotate, delegate agents). */
98
+ readonly identities: IdentityService
99
+ /** Device authorization (link, revoke, extend). */
100
+ readonly devices: DeviceService
101
+ /** Message and action signing. */
102
+ readonly signing: SigningService
103
+ /** Organization management. */
104
+ readonly orgs: OrgService
105
+ /** Trust store for pinned identities. */
106
+ readonly trust: TrustService
107
+ /** Witness node management. */
108
+ readonly witnesses: WitnessService
109
+ /** Attestation queries. */
110
+ readonly attestations: AttestationService
111
+ /** Artifact signing. */
112
+ readonly artifacts: ArtifactService
113
+ /** Git commit signing. */
114
+ readonly commits: CommitService
115
+ /** Repository audit reports. */
116
+ readonly audit: AuditService
117
+ /** Cross-device pairing. */
118
+ readonly pairing: PairingService
119
+
120
+ /**
121
+ * Creates a new Auths client.
122
+ *
123
+ * @param config - Client configuration.
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * // Auto-discover (~/.auths)
128
+ * const auths = new Auths()
129
+ *
130
+ * // Explicit configuration
131
+ * const auths = new Auths({
132
+ * repoPath: '/path/to/identity-repo',
133
+ * passphrase: 'my-secret',
134
+ * })
135
+ * ```
136
+ */
137
+ constructor(config: ClientConfig = {}) {
138
+ this.repoPath = config.repoPath ?? '~/.auths'
139
+ this.passphrase = config.passphrase
140
+
141
+ this.identities = new IdentityService(this)
142
+ this.devices = new DeviceService(this)
143
+ this.signing = new SigningService(this)
144
+ this.orgs = new OrgService(this)
145
+ this.trust = new TrustService(this)
146
+ this.witnesses = new WitnessService(this)
147
+ this.attestations = new AttestationService(this)
148
+ this.artifacts = new ArtifactService(this)
149
+ this.commits = new CommitService(this)
150
+ this.audit = new AuditService(this)
151
+ this.pairing = new PairingService(this)
152
+ }
153
+
154
+ /**
155
+ * Verifies a single attestation with optional capability and time constraints.
156
+ *
157
+ * @param opts - Verification options.
158
+ * @returns The verification result.
159
+ * @throws {@link VerificationError} if verification encounters an error.
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const result = await auths.verify({
164
+ * attestationJson: json,
165
+ * issuerKey: publicKeyHex,
166
+ * })
167
+ * console.log(result.valid)
168
+ * ```
169
+ */
170
+ async verify(opts: VerifyOptions): Promise<VerificationResult> {
171
+ if (opts.at && opts.requiredCapability) {
172
+ return verifyAtTimeWithCapability(opts.attestationJson, opts.issuerKey, opts.at, opts.requiredCapability)
173
+ }
174
+ if (opts.at) {
175
+ return verifyAtTime(opts.attestationJson, opts.issuerKey, opts.at)
176
+ }
177
+ if (opts.requiredCapability) {
178
+ return verifyAttestationWithCapability(opts.attestationJson, opts.issuerKey, opts.requiredCapability)
179
+ }
180
+ return verifyAttestation(opts.attestationJson, opts.issuerKey)
181
+ }
182
+
183
+ /**
184
+ * Verifies an attestation chain with optional capability and witness constraints.
185
+ *
186
+ * @param opts - Chain verification options.
187
+ * @returns The verification report.
188
+ * @throws {@link VerificationError} if verification encounters an error.
189
+ */
190
+ async verifyChain(opts: VerifyChainOptions): Promise<VerificationReport> {
191
+ if (opts.witnesses) {
192
+ return verifyChainWithWitnesses(opts.attestations, opts.rootKey, opts.witnesses)
193
+ }
194
+ if (opts.requiredCapability) {
195
+ return verifyChainWithCapability(opts.attestations, opts.rootKey, opts.requiredCapability)
196
+ }
197
+ return verifyChainFn(opts.attestations, opts.rootKey)
198
+ }
199
+
200
+ /**
201
+ * Convenience method to sign a message as an identity.
202
+ *
203
+ * @param opts - Signing options.
204
+ * @returns The signature and signer DID.
205
+ * @throws {@link CryptoError} if signing fails.
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const result = auths.signAs({
210
+ * message: Buffer.from('hello world'),
211
+ * identityDid: identity.did,
212
+ * })
213
+ * ```
214
+ */
215
+ signAs(opts: SignAsIdentityOptions): SignResult {
216
+ return this.signing.signAsIdentity({
217
+ message: opts.message,
218
+ identityDid: opts.identityDid,
219
+ passphrase: opts.passphrase,
220
+ })
221
+ }
222
+
223
+ /**
224
+ * Convenience method to sign an action as an identity.
225
+ *
226
+ * @param opts - Action signing options.
227
+ * @returns The signed action envelope.
228
+ * @throws {@link CryptoError} if signing fails.
229
+ */
230
+ signActionAs(opts: SignActionAsIdentityOptions): ActionEnvelope {
231
+ return this.signing.signActionAsIdentity({
232
+ actionType: opts.actionType,
233
+ payloadJson: opts.payloadJson,
234
+ identityDid: opts.identityDid,
235
+ passphrase: opts.passphrase,
236
+ })
237
+ }
238
+
239
+ /**
240
+ * Convenience method to sign a message as an agent.
241
+ *
242
+ * @param opts - Agent signing options.
243
+ * @returns The signature and signer DID.
244
+ * @throws {@link CryptoError} if signing fails.
245
+ */
246
+ signAsAgent(opts: SignAsAgentOptions): SignResult {
247
+ return this.signing.signAsAgent({
248
+ message: opts.message,
249
+ keyAlias: opts.keyAlias,
250
+ passphrase: opts.passphrase,
251
+ })
252
+ }
253
+
254
+ /**
255
+ * Convenience method to sign an action as an agent.
256
+ *
257
+ * @param opts - Agent action signing options.
258
+ * @returns The signed action envelope.
259
+ * @throws {@link CryptoError} if signing fails.
260
+ */
261
+ signActionAsAgent(opts: SignActionAsAgentOptions): ActionEnvelope {
262
+ return this.signing.signActionAsAgent(opts)
263
+ }
264
+
265
+ /**
266
+ * Convenience method to get an identity's public key.
267
+ *
268
+ * @param opts - Lookup options.
269
+ * @returns Hex-encoded Ed25519 public key.
270
+ * @throws {@link CryptoError} if the key cannot be found.
271
+ */
272
+ getPublicKey(opts: GetPublicKeyOptions): string {
273
+ return this.identities.getPublicKey(opts)
274
+ }
275
+
276
+ /**
277
+ * Runs diagnostics on the Auths installation and returns a report.
278
+ *
279
+ * @returns A human-readable diagnostics string.
280
+ */
281
+ doctor(): string {
282
+ return native.runDiagnostics(this.repoPath, this.passphrase)
283
+ }
284
+
285
+ /**
286
+ * Returns the list of known diagnostic check names.
287
+ *
288
+ * @returns Array of check name strings.
289
+ */
290
+ static availableChecks(): string[] {
291
+ return ['git_version', 'ssh_keygen', 'git_signing_config']
292
+ }
293
+ }
package/lib/commits.ts ADDED
@@ -0,0 +1,70 @@
1
+ import native from './native'
2
+ import { mapNativeError, CryptoError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /** Result of signing a Git commit. */
6
+ export interface CommitSignResult {
7
+ /** PEM-encoded signature for the commit. */
8
+ signaturePem: string
9
+ /** Signing method identifier. */
10
+ method: string
11
+ /** Namespace for the signature (e.g. `'auths'`). */
12
+ namespace: string
13
+ }
14
+
15
+ /** Options for {@link CommitService.sign}. */
16
+ export interface SignCommitOptions {
17
+ /** Raw commit data to sign. */
18
+ data: Buffer
19
+ /** DID of the identity to sign with. */
20
+ identityDid: string
21
+ /** Override the client's passphrase. */
22
+ passphrase?: string
23
+ }
24
+
25
+ /**
26
+ * Signs Git commits using Auths identities.
27
+ *
28
+ * Access via {@link Auths.commits}.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const result = auths.commits.sign({
33
+ * data: commitBuffer,
34
+ * identityDid: identity.did,
35
+ * })
36
+ * console.log(result.signaturePem) // PEM-encoded signature
37
+ * ```
38
+ */
39
+ export class CommitService {
40
+ constructor(private client: Auths) {}
41
+
42
+ /**
43
+ * Signs raw Git commit data, producing a PEM-encoded signature.
44
+ *
45
+ * @param opts - Signing options.
46
+ * @returns The commit signature with method and namespace metadata.
47
+ * @throws {@link CryptoError} if the key is missing or signing fails.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const result = auths.commits.sign({
52
+ * data: Buffer.from(commitContent),
53
+ * identityDid: identity.did,
54
+ * })
55
+ * ```
56
+ */
57
+ sign(opts: SignCommitOptions): CommitSignResult {
58
+ const pp = opts.passphrase ?? this.client.passphrase
59
+ try {
60
+ return native.signCommit(
61
+ opts.data,
62
+ opts.identityDid,
63
+ this.client.repoPath,
64
+ pp,
65
+ )
66
+ } catch (err) {
67
+ throw mapNativeError(err, CryptoError)
68
+ }
69
+ }
70
+ }
package/lib/devices.ts ADDED
@@ -0,0 +1,178 @@
1
+ import native from './native'
2
+ import { mapNativeError, IdentityError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /** Result of linking a device to an identity. */
6
+ export interface Device {
7
+ /** The device's DID (typically `did:key:z...`). */
8
+ did: string
9
+ /** Unique identifier of the attestation granting device authorization. */
10
+ attestationId: string
11
+ }
12
+
13
+ /** Result of extending a device's authorization period. */
14
+ export interface DeviceExtension {
15
+ /** The device's DID. */
16
+ deviceDid: string
17
+ /** New expiration timestamp (RFC 3339). */
18
+ newExpiresAt: string
19
+ /** Previous expiration timestamp, or `null` if there was none. */
20
+ previousExpiresAt: string | null
21
+ }
22
+
23
+ /** Options for {@link DeviceService.link}. */
24
+ export interface LinkDeviceOptions {
25
+ /** DID of the identity to link the device under. */
26
+ identityDid: string
27
+ /** Capabilities to grant the device (e.g. `['sign']`). */
28
+ capabilities?: string[]
29
+ /** Optional expiration in days. */
30
+ expiresInDays?: number
31
+ /** Override the client's passphrase. */
32
+ passphrase?: string
33
+ }
34
+
35
+ /** Options for {@link DeviceService.revoke}. */
36
+ export interface RevokeDeviceOptions {
37
+ /** DID of the device to revoke. */
38
+ deviceDid: string
39
+ /** DID of the identity that authorized the device. */
40
+ identityDid: string
41
+ /** Optional revocation note. */
42
+ note?: string
43
+ /** Override the client's passphrase. */
44
+ passphrase?: string
45
+ }
46
+
47
+ /** Options for {@link DeviceService.extend}. */
48
+ export interface ExtendDeviceOptions {
49
+ /** DID of the device to extend. */
50
+ deviceDid: string
51
+ /** DID of the authorizing identity. */
52
+ identityDid: string
53
+ /** Number of days to extend by. Defaults to 90. */
54
+ days?: number
55
+ /** Override the client's passphrase. */
56
+ passphrase?: string
57
+ }
58
+
59
+ /**
60
+ * Manages device authorization lifecycle: link, revoke, and extend.
61
+ *
62
+ * Access via {@link Auths.devices}.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const device = auths.devices.link({
67
+ * identityDid: identity.did,
68
+ * capabilities: ['sign'],
69
+ * expiresInDays: 90,
70
+ * })
71
+ * ```
72
+ */
73
+ export class DeviceService {
74
+ constructor(private client: Auths) {}
75
+
76
+ /**
77
+ * Links a new device to an identity with scoped capabilities.
78
+ *
79
+ * @param opts - Link options.
80
+ * @returns The linked device with its DID and attestation ID.
81
+ * @throws {@link IdentityError} if linking fails.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const device = auths.devices.link({
86
+ * identityDid: identity.did,
87
+ * capabilities: ['sign'],
88
+ * expiresInDays: 90,
89
+ * })
90
+ * console.log(device.did) // did:key:z...
91
+ * ```
92
+ */
93
+ link(opts: LinkDeviceOptions): Device {
94
+ const pp = opts.passphrase ?? this.client.passphrase
95
+ try {
96
+ const result = native.linkDeviceToIdentity(
97
+ opts.identityDid,
98
+ opts.capabilities ?? [],
99
+ this.client.repoPath,
100
+ pp,
101
+ opts.expiresInDays ?? null,
102
+ )
103
+ return {
104
+ did: result.deviceDid,
105
+ attestationId: result.attestationId,
106
+ }
107
+ } catch (err) {
108
+ throw mapNativeError(err, IdentityError)
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Revokes a device's authorization under an identity.
114
+ *
115
+ * @param opts - Revocation options.
116
+ * @throws {@link IdentityError} if revocation fails.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * auths.devices.revoke({
121
+ * deviceDid: device.did,
122
+ * identityDid: identity.did,
123
+ * note: 'replaced',
124
+ * })
125
+ * ```
126
+ */
127
+ revoke(opts: RevokeDeviceOptions): void {
128
+ const pp = opts.passphrase ?? this.client.passphrase
129
+ try {
130
+ native.revokeDeviceFromIdentity(
131
+ opts.deviceDid,
132
+ opts.identityDid,
133
+ this.client.repoPath,
134
+ pp,
135
+ opts.note ?? null,
136
+ )
137
+ } catch (err) {
138
+ throw mapNativeError(err, IdentityError)
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Extends a device's authorization period.
144
+ *
145
+ * @param opts - Extension options.
146
+ * @returns The extension result with new and previous expiration times.
147
+ * @throws {@link IdentityError} if extension fails.
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const ext = auths.devices.extend({
152
+ * deviceDid: device.did,
153
+ * identityDid: identity.did,
154
+ * days: 60,
155
+ * })
156
+ * console.log(ext.newExpiresAt) // RFC 3339 timestamp
157
+ * ```
158
+ */
159
+ extend(opts: ExtendDeviceOptions): DeviceExtension {
160
+ const pp = opts.passphrase ?? this.client.passphrase
161
+ try {
162
+ const result = native.extendDeviceAuthorization(
163
+ opts.deviceDid,
164
+ opts.identityDid,
165
+ opts.days ?? 90,
166
+ this.client.repoPath,
167
+ pp,
168
+ )
169
+ return {
170
+ deviceDid: result.deviceDid,
171
+ newExpiresAt: result.newExpiresAt,
172
+ previousExpiresAt: result.previousExpiresAt ?? null,
173
+ }
174
+ } catch (err) {
175
+ throw mapNativeError(err, IdentityError)
176
+ }
177
+ }
178
+ }