@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/signing.ts ADDED
@@ -0,0 +1,204 @@
1
+ import native from './native'
2
+ import { mapNativeError, CryptoError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /** Result of a signing operation. */
6
+ export interface SignResult {
7
+ /** Hex-encoded Ed25519 signature. */
8
+ signature: string
9
+ /** DID of the signer. */
10
+ signerDid: string
11
+ }
12
+
13
+ /** A signed action envelope containing the payload and its signature. */
14
+ export interface ActionEnvelope {
15
+ /** JSON-serialized envelope with action metadata. */
16
+ envelopeJson: string
17
+ /** Hex-encoded signature over the envelope. */
18
+ signatureHex: string
19
+ /** DID of the signer. */
20
+ signerDid: string
21
+ }
22
+
23
+ /** Options for {@link SigningService.signAsIdentity}. */
24
+ export interface SignAsIdentityOptions {
25
+ /** The message bytes to sign. */
26
+ message: Buffer
27
+ /** DID of the identity to sign with. */
28
+ identityDid: string
29
+ /** Override the client's passphrase. */
30
+ passphrase?: string
31
+ }
32
+
33
+ /** Options for {@link SigningService.signActionAsIdentity}. */
34
+ export interface SignActionAsIdentityOptions {
35
+ /** Action type label (e.g. `'tool_call'`). */
36
+ actionType: string
37
+ /** JSON-serialized action payload. */
38
+ payloadJson: string
39
+ /** DID of the identity to sign with. */
40
+ identityDid: string
41
+ /** Override the client's passphrase. */
42
+ passphrase?: string
43
+ }
44
+
45
+ /** Options for {@link SigningService.signAsAgent}. */
46
+ export interface SignAsAgentOptions {
47
+ /** The message bytes to sign. */
48
+ message: Buffer
49
+ /** Keychain alias of the agent key. */
50
+ keyAlias: string
51
+ /** Override the client's passphrase. */
52
+ passphrase?: string
53
+ }
54
+
55
+ /** Options for {@link SigningService.signActionAsAgent}. */
56
+ export interface SignActionAsAgentOptions {
57
+ /** Action type label (e.g. `'tool_call'`). */
58
+ actionType: string
59
+ /** JSON-serialized action payload. */
60
+ payloadJson: string
61
+ /** Keychain alias of the agent key. */
62
+ keyAlias: string
63
+ /** DID of the agent identity. */
64
+ agentDid: string
65
+ /** Override the client's passphrase. */
66
+ passphrase?: string
67
+ }
68
+
69
+ /**
70
+ * Signs messages and actions using identity or agent keys.
71
+ *
72
+ * Access via {@link Auths.signing}.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const result = auths.signing.signAsIdentity({
77
+ * message: Buffer.from('hello world'),
78
+ * identityDid: identity.did,
79
+ * })
80
+ * console.log(result.signature) // hex-encoded Ed25519 signature
81
+ * ```
82
+ */
83
+ export class SigningService {
84
+ constructor(private client: Auths) {}
85
+
86
+ /**
87
+ * Signs a message as an identity.
88
+ *
89
+ * @param opts - Signing options.
90
+ * @returns The signature and signer DID.
91
+ * @throws {@link CryptoError} if the key is missing or signing fails.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const result = auths.signing.signAsIdentity({
96
+ * message: Buffer.from('hello'),
97
+ * identityDid: identity.did,
98
+ * })
99
+ * ```
100
+ */
101
+ signAsIdentity(opts: SignAsIdentityOptions): SignResult {
102
+ const pp = opts.passphrase ?? this.client.passphrase
103
+ try {
104
+ const result = native.signAsIdentity(
105
+ opts.message,
106
+ opts.identityDid,
107
+ this.client.repoPath,
108
+ pp,
109
+ )
110
+ return { signature: result.signature, signerDid: result.signerDid }
111
+ } catch (err) {
112
+ throw mapNativeError(err, CryptoError)
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Signs a structured action as an identity, producing a verifiable envelope.
118
+ *
119
+ * @param opts - Action signing options.
120
+ * @returns The signed action envelope.
121
+ * @throws {@link CryptoError} if signing fails.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const envelope = auths.signing.signActionAsIdentity({
126
+ * actionType: 'tool_call',
127
+ * payloadJson: '{"tool":"read_file"}',
128
+ * identityDid: identity.did,
129
+ * })
130
+ * ```
131
+ */
132
+ signActionAsIdentity(opts: SignActionAsIdentityOptions): ActionEnvelope {
133
+ const pp = opts.passphrase ?? this.client.passphrase
134
+ try {
135
+ return native.signActionAsIdentity(
136
+ opts.actionType,
137
+ opts.payloadJson,
138
+ opts.identityDid,
139
+ this.client.repoPath,
140
+ pp,
141
+ )
142
+ } catch (err) {
143
+ throw mapNativeError(err, CryptoError)
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Signs a message as an agent using its keychain alias.
149
+ *
150
+ * @param opts - Agent signing options.
151
+ * @returns The signature and signer DID.
152
+ * @throws {@link CryptoError} if the key is missing or signing fails.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const result = auths.signing.signAsAgent({
157
+ * message: Buffer.from('payload'),
158
+ * keyAlias: agent.keyAlias,
159
+ * })
160
+ * ```
161
+ */
162
+ signAsAgent(opts: SignAsAgentOptions): SignResult {
163
+ const pp = opts.passphrase ?? this.client.passphrase
164
+ try {
165
+ const result = native.signAsAgent(opts.message, opts.keyAlias, this.client.repoPath, pp)
166
+ return { signature: result.signature, signerDid: result.signerDid }
167
+ } catch (err) {
168
+ throw mapNativeError(err, CryptoError)
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Signs a structured action as an agent.
174
+ *
175
+ * @param opts - Agent action signing options.
176
+ * @returns The signed action envelope.
177
+ * @throws {@link CryptoError} if signing fails.
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const envelope = auths.signing.signActionAsAgent({
182
+ * actionType: 'tool_call',
183
+ * payloadJson: '{"tool":"execute"}',
184
+ * keyAlias: agent.keyAlias,
185
+ * agentDid: agent.did,
186
+ * })
187
+ * ```
188
+ */
189
+ signActionAsAgent(opts: SignActionAsAgentOptions): ActionEnvelope {
190
+ const pp = opts.passphrase ?? this.client.passphrase
191
+ try {
192
+ return native.signActionAsAgent(
193
+ opts.actionType,
194
+ opts.payloadJson,
195
+ opts.keyAlias,
196
+ opts.agentDid,
197
+ this.client.repoPath,
198
+ pp,
199
+ )
200
+ } catch (err) {
201
+ throw mapNativeError(err, CryptoError)
202
+ }
203
+ }
204
+ }
package/lib/trust.ts ADDED
@@ -0,0 +1,152 @@
1
+ import native from './native'
2
+ import { mapNativeError, StorageError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /**
6
+ * Trust level for a pinned identity.
7
+ *
8
+ * Values match the Rust `TrustLevel` enum in `auths-core/src/trust/pinned.rs`.
9
+ */
10
+ export const TrustLevel = {
11
+ /** Accepted on first use (interactive prompt). */
12
+ Tofu: 'tofu',
13
+ /** Manually pinned via CLI or `--issuer-pk`. */
14
+ Manual: 'manual',
15
+ /** Loaded from roots.json org policy file. */
16
+ OrgPolicy: 'org_policy',
17
+ } as const
18
+ export type TrustLevel = (typeof TrustLevel)[keyof typeof TrustLevel]
19
+
20
+ /** A pinned (trusted) identity in the local trust store. */
21
+ export interface PinnedIdentity {
22
+ /** The pinned identity's DID. */
23
+ did: string
24
+ /** Optional label for the pinned identity. */
25
+ label: string | null
26
+ /** Trust level: `'tofu'`, `'manual'`, or `'org_policy'`. */
27
+ trustLevel: string
28
+ /** ISO 8601 timestamp when this identity was first seen. */
29
+ firstSeen: string
30
+ /** KERI event log sequence number at time of pinning, or `null`. */
31
+ kelSequence: number | null
32
+ /** ISO 8601 timestamp when this identity was pinned. */
33
+ pinnedAt: string
34
+ }
35
+
36
+ /** Options for {@link TrustService.pin}. */
37
+ export interface PinIdentityOptions {
38
+ /** DID of the identity to pin. */
39
+ did: string
40
+ /** Optional label for the pinned identity. */
41
+ label?: string
42
+ /** Trust level to assign. Defaults to `'tofu'`. */
43
+ trustLevel?: 'tofu' | 'manual' | 'org_policy'
44
+ }
45
+
46
+ /**
47
+ * Manages the local trust store for pinning and querying trusted identities.
48
+ *
49
+ * Access via {@link Auths.trust}.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * auths.trust.pin({ did: peer.did, label: 'alice' })
54
+ * const entries = auths.trust.list()
55
+ * ```
56
+ */
57
+ export class TrustService {
58
+ constructor(private client: Auths) {}
59
+
60
+ /**
61
+ * Pins an identity as trusted in the local store.
62
+ *
63
+ * @param opts - Pin options.
64
+ * @returns The pinned identity entry.
65
+ * @throws {@link StorageError} if the pin operation fails.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const entry = auths.trust.pin({ did: identity.did, label: 'my-peer' })
70
+ * console.log(entry.trustLevel) // 'tofu'
71
+ * ```
72
+ */
73
+ pin(opts: PinIdentityOptions): PinnedIdentity {
74
+ try {
75
+ const result = native.pinIdentity(
76
+ opts.did,
77
+ this.client.repoPath,
78
+ opts.label ?? null,
79
+ opts.trustLevel ?? null,
80
+ )
81
+ return {
82
+ did: result.did,
83
+ label: result.label ?? null,
84
+ trustLevel: result.trustLevel,
85
+ firstSeen: result.firstSeen,
86
+ kelSequence: result.kelSequence ?? null,
87
+ pinnedAt: result.pinnedAt,
88
+ }
89
+ } catch (err) {
90
+ throw mapNativeError(err, StorageError)
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Removes a pinned identity from the local trust store.
96
+ *
97
+ * @param did - DID of the identity to unpin.
98
+ * @throws {@link StorageError} if the operation fails.
99
+ */
100
+ remove(did: string): void {
101
+ try {
102
+ native.removePinnedIdentity(did, this.client.repoPath)
103
+ } catch (err) {
104
+ throw mapNativeError(err, StorageError)
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Lists all pinned identities in the local trust store.
110
+ *
111
+ * @returns Array of pinned identity entries.
112
+ * @throws {@link StorageError} if the operation fails.
113
+ */
114
+ list(): PinnedIdentity[] {
115
+ try {
116
+ const json = native.listPinnedIdentities(this.client.repoPath)
117
+ return JSON.parse(json)
118
+ } catch (err) {
119
+ throw mapNativeError(err, StorageError)
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Looks up a specific pinned identity by DID.
125
+ *
126
+ * @param did - DID to look up.
127
+ * @returns The pinned identity entry, or `null` if not found.
128
+ * @throws {@link StorageError} if the operation fails.
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const entry = auths.trust.get('did:keri:EBfd...')
133
+ * if (entry) console.log(entry.label)
134
+ * ```
135
+ */
136
+ get(did: string): PinnedIdentity | null {
137
+ try {
138
+ const result = native.getPinnedIdentity(did, this.client.repoPath)
139
+ if (!result) return null
140
+ return {
141
+ did: result.did,
142
+ label: result.label ?? null,
143
+ trustLevel: result.trustLevel,
144
+ firstSeen: result.firstSeen,
145
+ kelSequence: result.kelSequence ?? null,
146
+ pinnedAt: result.pinnedAt,
147
+ }
148
+ } catch (err) {
149
+ throw mapNativeError(err, StorageError)
150
+ }
151
+ }
152
+ }
package/lib/types.ts ADDED
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Branded DID types and identity bundle type definitions.
3
+ *
4
+ * These types mirror the JSON schema at `auths/schemas/identity-bundle-v1.json`
5
+ * and the Rust DID type system in `auths-verifier/src/types.rs`.
6
+ *
7
+ * @module
8
+ */
9
+
10
+ // ── Branded DID Types ─────────────────────────────────────────────────
11
+
12
+ declare const __brand: unique symbol
13
+ type Brand<T, B extends string> = T & { readonly [__brand]: B }
14
+
15
+ /**
16
+ * Identity DID — always `did:keri:...` format.
17
+ *
18
+ * Represents a KERI-based decentralized identity. Used for organizations
19
+ * and individual identities. Parse with {@link parseIdentityDid}.
20
+ */
21
+ export type IdentityDID = Brand<string, 'IdentityDID'>
22
+
23
+ /**
24
+ * Device DID — always `did:key:z...` format.
25
+ *
26
+ * Represents a device's ephemeral key-based identity. Used for device
27
+ * attestations and signing keys. Parse with {@link parseDeviceDid}.
28
+ */
29
+ export type DeviceDID = Brand<string, 'DeviceDID'>
30
+
31
+ /**
32
+ * Parse and validate an identity DID string.
33
+ *
34
+ * @param raw - A DID string that should start with `did:keri:`.
35
+ * @returns The validated DID as an `IdentityDID` branded type.
36
+ * @throws Error if the string does not start with `did:keri:`.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const did = parseIdentityDid('did:keri:EOrg123')
41
+ * // did is typed as IdentityDID
42
+ * ```
43
+ */
44
+ export function parseIdentityDid(raw: string): IdentityDID {
45
+ if (!raw.startsWith('did:keri:')) {
46
+ throw new Error(`Expected did:keri: prefix, got: ${raw.slice(0, 20)}`)
47
+ }
48
+ return raw as IdentityDID
49
+ }
50
+
51
+ /**
52
+ * Parse and validate a device DID string.
53
+ *
54
+ * @param raw - A DID string that should start with `did:key:z`.
55
+ * @returns The validated DID as a `DeviceDID` branded type.
56
+ * @throws Error if the string does not start with `did:key:z`.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const did = parseDeviceDid('did:key:z6MkDevice...')
61
+ * // did is typed as DeviceDID
62
+ * ```
63
+ */
64
+ export function parseDeviceDid(raw: string): DeviceDID {
65
+ if (!raw.startsWith('did:key:z')) {
66
+ throw new Error(`Expected did:key:z prefix, got: ${raw.slice(0, 20)}`)
67
+ }
68
+ return raw as DeviceDID
69
+ }
70
+
71
+ // ── Signer Type ───────────────────────────────────────────────────────
72
+
73
+ /** The type of entity that produced a signature. */
74
+ export const SignerType = {
75
+ Human: 'Human',
76
+ Agent: 'Agent',
77
+ Workload: 'Workload',
78
+ } as const
79
+ export type SignerType = (typeof SignerType)[keyof typeof SignerType]
80
+
81
+ // ── Role ──────────────────────────────────────────────────────────────
82
+
83
+ /** Organization member role. */
84
+ export const Role = {
85
+ Admin: 'admin',
86
+ Member: 'member',
87
+ Readonly: 'readonly',
88
+ } as const
89
+ export type Role = (typeof Role)[keyof typeof Role]
90
+
91
+ // ── Capability ────────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * Well-known capability identifiers.
95
+ *
96
+ * Custom capabilities can be any valid string (alphanumeric + `:` + `-` + `_`, max 64 chars).
97
+ * The `auths:` prefix is reserved.
98
+ */
99
+ export const WellKnownCapability = {
100
+ SignCommit: 'sign_commit',
101
+ SignRelease: 'sign_release',
102
+ ManageMembers: 'manage_members',
103
+ RotateKeys: 'rotate_keys',
104
+ } as const
105
+
106
+ // ── Identity Bundle ───────────────────────────────────────────────────
107
+
108
+ /**
109
+ * An attestation in the identity bundle's chain.
110
+ *
111
+ * Represents a 2-way key attestation between a primary identity and a device key.
112
+ * Matches `auths/schemas/attestation-v1.json`.
113
+ */
114
+ export interface BundleAttestation {
115
+ /** Record identifier linking this attestation to its storage ref. */
116
+ rid: string
117
+ /** Schema version. */
118
+ version: number
119
+ /** DID of the issuing identity (`did:keri:...`). */
120
+ issuer: string
121
+ /** DID of the device being attested (`did:key:z...`). */
122
+ subject: string
123
+ /** Ed25519 public key of the device (32 bytes, hex-encoded). */
124
+ device_public_key: string
125
+ /** Device's Ed25519 signature over the canonical attestation data (hex-encoded). */
126
+ device_signature: string
127
+ /** Issuer's Ed25519 signature over the canonical attestation data (hex-encoded). */
128
+ identity_signature?: string
129
+ /** Capabilities this attestation grants. */
130
+ capabilities?: string[]
131
+ /** Role for org membership attestations. */
132
+ role?: Role | null
133
+ /** The type of entity that produced this signature. */
134
+ signer_type?: SignerType | null
135
+ /** DID of the attestation that delegated authority. */
136
+ delegated_by?: string | null
137
+ /** Creation timestamp (ISO 8601). */
138
+ timestamp?: string | null
139
+ /** Expiration timestamp (ISO 8601). */
140
+ expires_at?: string | null
141
+ /** Timestamp when the attestation was revoked (ISO 8601). */
142
+ revoked_at?: string | null
143
+ /** Optional human-readable note. */
144
+ note?: string | null
145
+ /** Optional arbitrary JSON payload. */
146
+ payload?: unknown
147
+ }
148
+
149
+ /**
150
+ * Identity bundle for stateless verification in CI/CD environments.
151
+ *
152
+ * Contains all the information needed to verify commit signatures without
153
+ * requiring access to the identity repository or daemon.
154
+ *
155
+ * Matches `auths/schemas/identity-bundle-v1.json`.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * import { readFileSync } from 'node:fs'
160
+ * import type { IdentityBundle } from '@auths-dev/sdk'
161
+ *
162
+ * const bundle: IdentityBundle = JSON.parse(
163
+ * readFileSync('.auths/identity-bundle.json', 'utf-8')
164
+ * )
165
+ * console.log(bundle.identity_did) // did:keri:E...
166
+ * ```
167
+ */
168
+ export interface IdentityBundle {
169
+ /** The DID of the identity (`did:keri:...`). */
170
+ identity_did: string
171
+ /** The public key in hex format for signature verification (32 bytes, hex). */
172
+ public_key_hex: string
173
+ /** Chain of attestations linking the signing key to the identity. */
174
+ attestation_chain: BundleAttestation[]
175
+ /** UTC timestamp when this bundle was created (ISO 8601). */
176
+ bundle_timestamp: string
177
+ /** Maximum age in seconds before this bundle is considered stale. */
178
+ max_valid_for_secs: number
179
+ }