@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
@@ -0,0 +1,124 @@
1
+ import native from './native'
2
+ import { mapNativeError, CryptoError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /** Result of signing an artifact. */
6
+ export interface ArtifactResult {
7
+ /** JSON-serialized attestation for the signed artifact. */
8
+ attestationJson: string
9
+ /** Unique resource identifier of the attestation. */
10
+ rid: string
11
+ /** Content digest (hash) of the artifact. */
12
+ digest: string
13
+ /** Size of the artifact in bytes. */
14
+ fileSize: number
15
+ }
16
+
17
+ /** Options for {@link ArtifactService.sign}. */
18
+ export interface SignArtifactOptions {
19
+ /** Path to the file to sign. */
20
+ filePath: string
21
+ /** DID of the identity to sign with. */
22
+ identityDid: string
23
+ /** Optional expiration in days. */
24
+ expiresInDays?: number
25
+ /** Optional note attached to the attestation. */
26
+ note?: string
27
+ /** Override the client's passphrase. */
28
+ passphrase?: string
29
+ }
30
+
31
+ /** Options for {@link ArtifactService.signBytes}. */
32
+ export interface SignArtifactBytesOptions {
33
+ /** Raw bytes to sign. */
34
+ data: Buffer
35
+ /** DID of the identity to sign with. */
36
+ identityDid: string
37
+ /** Optional expiration in days. */
38
+ expiresInDays?: number
39
+ /** Optional note attached to the attestation. */
40
+ note?: string
41
+ /** Override the client's passphrase. */
42
+ passphrase?: string
43
+ }
44
+
45
+ /**
46
+ * Signs artifacts (files or raw bytes) to produce verifiable attestations.
47
+ *
48
+ * Access via {@link Auths.artifacts}.
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const result = auths.artifacts.sign({
53
+ * filePath: './release.tar.gz',
54
+ * identityDid: identity.did,
55
+ * })
56
+ * console.log(result.digest) // content hash
57
+ * ```
58
+ */
59
+ export class ArtifactService {
60
+ constructor(private client: Auths) {}
61
+
62
+ /**
63
+ * Signs a file at the given path.
64
+ *
65
+ * @param opts - Signing options.
66
+ * @returns The artifact attestation with digest and metadata.
67
+ * @throws {@link CryptoError} if signing fails.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const result = auths.artifacts.sign({
72
+ * filePath: './build/app.wasm',
73
+ * identityDid: identity.did,
74
+ * expiresInDays: 365,
75
+ * })
76
+ * ```
77
+ */
78
+ sign(opts: SignArtifactOptions): ArtifactResult {
79
+ const pp = opts.passphrase ?? this.client.passphrase
80
+ try {
81
+ return native.signArtifact(
82
+ opts.filePath,
83
+ opts.identityDid,
84
+ this.client.repoPath,
85
+ pp,
86
+ opts.expiresInDays ?? null,
87
+ opts.note ?? null,
88
+ )
89
+ } catch (err) {
90
+ throw mapNativeError(err, CryptoError)
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Signs raw bytes (e.g. an in-memory buffer).
96
+ *
97
+ * @param opts - Signing options.
98
+ * @returns The artifact attestation with digest and metadata.
99
+ * @throws {@link CryptoError} if signing fails.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const result = auths.artifacts.signBytes({
104
+ * data: Buffer.from('binary content'),
105
+ * identityDid: identity.did,
106
+ * })
107
+ * ```
108
+ */
109
+ signBytes(opts: SignArtifactBytesOptions): ArtifactResult {
110
+ const pp = opts.passphrase ?? this.client.passphrase
111
+ try {
112
+ return native.signArtifactBytes(
113
+ opts.data,
114
+ opts.identityDid,
115
+ this.client.repoPath,
116
+ pp,
117
+ opts.expiresInDays ?? null,
118
+ opts.note ?? null,
119
+ )
120
+ } catch (err) {
121
+ throw mapNativeError(err, CryptoError)
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,126 @@
1
+ import native from './native'
2
+ import { mapNativeError, StorageError } from './errors'
3
+ import type { Auths } from './client'
4
+
5
+ /** An attestation record from the local registry. */
6
+ export interface AttestationInfo {
7
+ /** Unique resource identifier of the attestation. */
8
+ rid: string
9
+ /** DID of the issuer (identity that signed the attestation). */
10
+ issuer: string
11
+ /** DID of the subject (device or agent being attested). */
12
+ subject: string
13
+ /** DID of the device this attestation applies to. */
14
+ deviceDid: string
15
+ /** List of capabilities granted (e.g. `['sign']`). */
16
+ capabilities: string[]
17
+ /** Signer type: `'human'`, `'agent'`, or `'workload'`, or `null`. */
18
+ signerType: string | null
19
+ /** Expiration timestamp (RFC 3339), or `null` if no expiry. */
20
+ expiresAt: string | null
21
+ /** Revocation timestamp (RFC 3339), or `null` if not revoked. */
22
+ revokedAt: string | null
23
+ /** Creation timestamp (RFC 3339), or `null`. */
24
+ createdAt: string | null
25
+ /** DID of the identity that delegated this attestation, or `null`. */
26
+ delegatedBy: string | null
27
+ /** Raw JSON-serialized attestation. */
28
+ json: string
29
+ }
30
+
31
+ /**
32
+ * Queries attestations stored in the local registry.
33
+ *
34
+ * Access via {@link Auths.attestations}.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const atts = auths.attestations.list()
39
+ * const latest = auths.attestations.getLatest(device.did)
40
+ * ```
41
+ */
42
+ export class AttestationService {
43
+ constructor(private client: Auths) {}
44
+
45
+ /**
46
+ * Lists all attestations in the local registry.
47
+ *
48
+ * @returns Array of attestation records.
49
+ * @throws {@link StorageError} if the operation fails.
50
+ */
51
+ list(): AttestationInfo[] {
52
+ try {
53
+ return native.listAttestations(this.client.repoPath).map(a => ({
54
+ rid: a.rid,
55
+ issuer: a.issuer,
56
+ subject: a.subject,
57
+ deviceDid: a.deviceDid,
58
+ capabilities: a.capabilities,
59
+ signerType: a.signerType ?? null,
60
+ expiresAt: a.expiresAt ?? null,
61
+ revokedAt: a.revokedAt ?? null,
62
+ createdAt: a.createdAt ?? null,
63
+ delegatedBy: a.delegatedBy ?? null,
64
+ json: a.json,
65
+ }))
66
+ } catch (err) {
67
+ throw mapNativeError(err, StorageError)
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Lists attestations for a specific device.
73
+ *
74
+ * @param deviceDid - DID of the device to filter by.
75
+ * @returns Array of attestation records for the device.
76
+ * @throws {@link StorageError} if the operation fails.
77
+ */
78
+ listByDevice(deviceDid: string): AttestationInfo[] {
79
+ try {
80
+ return native.listAttestationsByDevice(this.client.repoPath, deviceDid).map(a => ({
81
+ rid: a.rid,
82
+ issuer: a.issuer,
83
+ subject: a.subject,
84
+ deviceDid: a.deviceDid,
85
+ capabilities: a.capabilities,
86
+ signerType: a.signerType ?? null,
87
+ expiresAt: a.expiresAt ?? null,
88
+ revokedAt: a.revokedAt ?? null,
89
+ createdAt: a.createdAt ?? null,
90
+ delegatedBy: a.delegatedBy ?? null,
91
+ json: a.json,
92
+ }))
93
+ } catch (err) {
94
+ throw mapNativeError(err, StorageError)
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Retrieves the latest attestation for a device.
100
+ *
101
+ * @param deviceDid - DID of the device.
102
+ * @returns The latest attestation, or `null` if none found.
103
+ * @throws {@link StorageError} if the operation fails.
104
+ */
105
+ getLatest(deviceDid: string): AttestationInfo | null {
106
+ try {
107
+ const a = native.getLatestAttestation(this.client.repoPath, deviceDid)
108
+ if (!a) return null
109
+ return {
110
+ rid: a.rid,
111
+ issuer: a.issuer,
112
+ subject: a.subject,
113
+ deviceDid: a.deviceDid,
114
+ capabilities: a.capabilities,
115
+ signerType: a.signerType ?? null,
116
+ expiresAt: a.expiresAt ?? null,
117
+ revokedAt: a.revokedAt ?? null,
118
+ createdAt: a.createdAt ?? null,
119
+ delegatedBy: a.delegatedBy ?? null,
120
+ json: a.json,
121
+ }
122
+ } catch (err) {
123
+ throw mapNativeError(err, StorageError)
124
+ }
125
+ }
126
+ }
package/lib/audit.ts ADDED
@@ -0,0 +1,189 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import native from './native'
3
+ import { mapNativeError, VerificationError } from './errors'
4
+ import type { Auths } from './client'
5
+
6
+ /** Full audit report for a Git repository's commit signatures. */
7
+ export interface AuditReport {
8
+ /** Individual commit audit entries. */
9
+ commits: AuditCommit[]
10
+ /** Aggregate signature statistics. */
11
+ summary: AuditSummary
12
+ }
13
+
14
+ /** Audit information for a single Git commit. */
15
+ export interface AuditCommit {
16
+ /** Git object ID (SHA). */
17
+ oid: string
18
+ /** Commit author name. */
19
+ author_name: string
20
+ /** Commit author email. */
21
+ author_email: string
22
+ /** Commit date (ISO 8601). */
23
+ date: string
24
+ /** Commit message (first line). */
25
+ message: string
26
+ /** Signature type (`'auths'`, `'gpg'`, `'ssh'`), or `null` if unsigned. */
27
+ signature_type: string | null
28
+ /** DID of the signer, or `null` if not an Auths signature. */
29
+ signer_did: string | null
30
+ /** Whether the signature verified successfully, or `null` if unsigned. */
31
+ verified: boolean | null
32
+ }
33
+
34
+ /** Aggregate statistics from an audit report. */
35
+ export interface AuditSummary {
36
+ /** Total number of commits analyzed. */
37
+ total_commits: number
38
+ /** Number of signed commits (any method). */
39
+ signed_commits: number
40
+ /** Number of unsigned commits. */
41
+ unsigned_commits: number
42
+ /** Number of Auths-signed commits. */
43
+ auths_signed: number
44
+ /** Number of GPG-signed commits. */
45
+ gpg_signed: number
46
+ /** Number of SSH-signed commits. */
47
+ ssh_signed: number
48
+ /** Number of signatures that passed verification. */
49
+ verification_passed: number
50
+ /** Number of signatures that failed verification. */
51
+ verification_failed: number
52
+ }
53
+
54
+ /** Options for {@link AuditService.report}. */
55
+ export interface AuditReportOptions {
56
+ /** Path to the Git repository to audit. */
57
+ targetRepoPath: string
58
+ /** Only include commits after this date (ISO 8601). */
59
+ since?: string
60
+ /** Only include commits before this date (ISO 8601). */
61
+ until?: string
62
+ /** Only include commits by this author. */
63
+ author?: string
64
+ /** Maximum number of commits to analyze. */
65
+ limit?: number
66
+ /** Path to an Auths identity-bundle JSON file for signer DID resolution. */
67
+ identityBundlePath?: string
68
+ }
69
+
70
+ /** Parsed identity bundle metadata. */
71
+ export interface IdentityBundleInfo {
72
+ /** Identity DID (`did:keri:...`). */
73
+ did: string
74
+ /** Hex-encoded Ed25519 public key. */
75
+ publicKeyHex: string
76
+ /** Human-readable identity label. */
77
+ label: string | null
78
+ /** Number of device attestations in the chain. */
79
+ deviceCount: number
80
+ }
81
+
82
+ /**
83
+ * Parse an Auths identity-bundle JSON file.
84
+ *
85
+ * @param path - Path to the identity-bundle JSON file.
86
+ * @returns The parsed bundle object.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const bundle = parseIdentityBundle('.auths/identity-bundle.json')
91
+ * console.log(bundle.did)
92
+ * ```
93
+ */
94
+ export function parseIdentityBundle(path: string): Record<string, unknown> {
95
+ const content = readFileSync(path, 'utf-8')
96
+ return JSON.parse(content) as Record<string, unknown>
97
+ }
98
+
99
+ /**
100
+ * Parse an identity bundle into a typed {@link IdentityBundleInfo}.
101
+ *
102
+ * @param path - Path to the identity-bundle JSON file.
103
+ * @returns Typed bundle metadata.
104
+ */
105
+ export function parseIdentityBundleInfo(path: string): IdentityBundleInfo {
106
+ const bundle = parseIdentityBundle(path)
107
+ const pkHex = (bundle.public_key_hex ?? bundle.publicKeyHex ?? '') as string
108
+ const chain = (bundle.attestation_chain ?? []) as unknown[]
109
+ return {
110
+ did: (bundle.did ?? '') as string,
111
+ publicKeyHex: pkHex,
112
+ label: (bundle.label ?? null) as string | null,
113
+ deviceCount: chain.length,
114
+ }
115
+ }
116
+
117
+ /** Options for {@link AuditService.isCompliant}. */
118
+ export interface AuditComplianceOptions {
119
+ /** Path to the Git repository to audit. */
120
+ targetRepoPath: string
121
+ /** Only include commits after this date (ISO 8601). */
122
+ since?: string
123
+ /** Only include commits before this date (ISO 8601). */
124
+ until?: string
125
+ /** Only include commits by this author. */
126
+ author?: string
127
+ }
128
+
129
+ /**
130
+ * Audits Git repositories for commit signature compliance.
131
+ *
132
+ * Access via {@link Auths.audit}.
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const report = auths.audit.report({ targetRepoPath: '/path/to/repo' })
137
+ * console.log(report.summary.unsigned_commits)
138
+ * ```
139
+ */
140
+ export class AuditService {
141
+ constructor(private client: Auths) {}
142
+
143
+ /**
144
+ * Generates an audit report for a Git repository's commit signatures.
145
+ *
146
+ * @param opts - Audit options.
147
+ * @returns The audit report with per-commit details and summary statistics.
148
+ * @throws {@link VerificationError} if the audit fails.
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const report = auths.audit.report({ targetRepoPath: '/path/to/repo' })
153
+ * console.log(report.summary.total_commits)
154
+ * ```
155
+ */
156
+ report(opts: AuditReportOptions): AuditReport {
157
+ try {
158
+ const json = native.generateAuditReport(
159
+ opts.targetRepoPath,
160
+ this.client.repoPath,
161
+ opts.since ?? null,
162
+ opts.until ?? null,
163
+ opts.author ?? null,
164
+ opts.limit ?? null,
165
+ )
166
+ return JSON.parse(json)
167
+ } catch (err) {
168
+ throw mapNativeError(err, VerificationError)
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Checks whether all commits in a repository are signed.
174
+ *
175
+ * @param opts - Compliance check options.
176
+ * @returns `true` if every commit is signed, `false` otherwise.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * if (auths.audit.isCompliant({ targetRepoPath: '/path/to/repo' })) {
181
+ * console.log('All commits signed')
182
+ * }
183
+ * ```
184
+ */
185
+ isCompliant(opts: AuditComplianceOptions): boolean {
186
+ const report = this.report(opts)
187
+ return report.summary.unsigned_commits === 0
188
+ }
189
+ }