@skrr-ai/auth-core 0.1.2

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 (147) hide show
  1. package/README.md +21 -0
  2. package/dist/cjs/aead.d.ts +24 -0
  3. package/dist/cjs/aead.js +65 -0
  4. package/dist/cjs/authExpiredDetector.d.ts +65 -0
  5. package/dist/cjs/authExpiredDetector.js +89 -0
  6. package/dist/cjs/authHelper.d.ts +51 -0
  7. package/dist/cjs/authHelper.js +321 -0
  8. package/dist/cjs/credentialEnvelope.d.ts +85 -0
  9. package/dist/cjs/credentialEnvelope.js +230 -0
  10. package/dist/cjs/credentialEnvelopeBridge.d.ts +116 -0
  11. package/dist/cjs/credentialEnvelopeBridge.js +637 -0
  12. package/dist/cjs/credentialResolver.d.ts +278 -0
  13. package/dist/cjs/credentialResolver.js +423 -0
  14. package/dist/cjs/daemonPair.d.ts +172 -0
  15. package/dist/cjs/daemonPair.js +495 -0
  16. package/dist/cjs/daemonScopes.d.ts +74 -0
  17. package/dist/cjs/daemonScopes.js +84 -0
  18. package/dist/cjs/deviceIdentityBridge.d.ts +113 -0
  19. package/dist/cjs/deviceIdentityBridge.js +591 -0
  20. package/dist/cjs/deviceKey.d.ts +167 -0
  21. package/dist/cjs/deviceKey.js +332 -0
  22. package/dist/cjs/fdToken.d.ts +17 -0
  23. package/dist/cjs/fdToken.js +238 -0
  24. package/dist/cjs/harnessTrust.d.ts +72 -0
  25. package/dist/cjs/harnessTrust.js +103 -0
  26. package/dist/cjs/headers-helper.d.ts +25 -0
  27. package/dist/cjs/headers-helper.js +323 -0
  28. package/dist/cjs/index.d.ts +37 -0
  29. package/dist/cjs/index.js +305 -0
  30. package/dist/cjs/jwtUtils.d.ts +35 -0
  31. package/dist/cjs/jwtUtils.js +61 -0
  32. package/dist/cjs/kek/index.d.ts +89 -0
  33. package/dist/cjs/kek/index.js +208 -0
  34. package/dist/cjs/kek/linux.d.ts +92 -0
  35. package/dist/cjs/kek/linux.js +596 -0
  36. package/dist/cjs/kek/macos.d.ts +112 -0
  37. package/dist/cjs/kek/macos.js +599 -0
  38. package/dist/cjs/kek/types.d.ts +111 -0
  39. package/dist/cjs/kek/types.js +43 -0
  40. package/dist/cjs/kek/windows.d.ts +71 -0
  41. package/dist/cjs/kek/windows.js +350 -0
  42. package/dist/cjs/kek/zeroize-registry.d.ts +44 -0
  43. package/dist/cjs/kek/zeroize-registry.js +63 -0
  44. package/dist/cjs/legacyStatePreflight.d.ts +67 -0
  45. package/dist/cjs/legacyStatePreflight.js +78 -0
  46. package/dist/cjs/localIdentity.d.ts +54 -0
  47. package/dist/cjs/localIdentity.js +57 -0
  48. package/dist/cjs/loginLocalhost.d.ts +115 -0
  49. package/dist/cjs/loginLocalhost.js +368 -0
  50. package/dist/cjs/loginWithLocalhost.d.ts +131 -0
  51. package/dist/cjs/loginWithLocalhost.js +359 -0
  52. package/dist/cjs/machineId.d.ts +35 -0
  53. package/dist/cjs/machineId.js +239 -0
  54. package/dist/cjs/messages.d.ts +9 -0
  55. package/dist/cjs/messages.js +44 -0
  56. package/dist/cjs/package.json +3 -0
  57. package/dist/cjs/pkce.d.ts +62 -0
  58. package/dist/cjs/pkce.js +158 -0
  59. package/dist/cjs/recoveryCode.d.ts +61 -0
  60. package/dist/cjs/recoveryCode.js +213 -0
  61. package/dist/cjs/refresh.d.ts +215 -0
  62. package/dist/cjs/refresh.js +877 -0
  63. package/dist/cjs/refreshClassification.d.ts +53 -0
  64. package/dist/cjs/refreshClassification.js +105 -0
  65. package/dist/cjs/refreshScheduler.d.ts +53 -0
  66. package/dist/cjs/refreshScheduler.js +332 -0
  67. package/dist/cjs/runtime.d.ts +149 -0
  68. package/dist/cjs/runtime.js +136 -0
  69. package/dist/cjs/spawnEnv.d.ts +76 -0
  70. package/dist/cjs/spawnEnv.js +153 -0
  71. package/dist/cjs/ttlParser.d.ts +54 -0
  72. package/dist/cjs/ttlParser.js +87 -0
  73. package/dist/cjs/types.d.ts +91 -0
  74. package/dist/cjs/types.js +26 -0
  75. package/dist/esm/aead.d.ts +24 -0
  76. package/dist/esm/aead.js +57 -0
  77. package/dist/esm/authExpiredDetector.d.ts +65 -0
  78. package/dist/esm/authExpiredDetector.js +85 -0
  79. package/dist/esm/authHelper.d.ts +51 -0
  80. package/dist/esm/authHelper.js +311 -0
  81. package/dist/esm/credentialEnvelope.d.ts +85 -0
  82. package/dist/esm/credentialEnvelope.js +213 -0
  83. package/dist/esm/credentialEnvelopeBridge.d.ts +116 -0
  84. package/dist/esm/credentialEnvelopeBridge.js +620 -0
  85. package/dist/esm/credentialResolver.d.ts +278 -0
  86. package/dist/esm/credentialResolver.js +414 -0
  87. package/dist/esm/daemonPair.d.ts +172 -0
  88. package/dist/esm/daemonPair.js +476 -0
  89. package/dist/esm/daemonScopes.d.ts +74 -0
  90. package/dist/esm/daemonScopes.js +80 -0
  91. package/dist/esm/deviceIdentityBridge.d.ts +113 -0
  92. package/dist/esm/deviceIdentityBridge.js +572 -0
  93. package/dist/esm/deviceKey.d.ts +167 -0
  94. package/dist/esm/deviceKey.js +320 -0
  95. package/dist/esm/fdToken.d.ts +17 -0
  96. package/dist/esm/fdToken.js +231 -0
  97. package/dist/esm/harnessTrust.d.ts +72 -0
  98. package/dist/esm/harnessTrust.js +97 -0
  99. package/dist/esm/headers-helper.d.ts +25 -0
  100. package/dist/esm/headers-helper.js +316 -0
  101. package/dist/esm/index.d.ts +37 -0
  102. package/dist/esm/index.js +144 -0
  103. package/dist/esm/jwtUtils.d.ts +35 -0
  104. package/dist/esm/jwtUtils.js +57 -0
  105. package/dist/esm/kek/index.d.ts +89 -0
  106. package/dist/esm/kek/index.js +162 -0
  107. package/dist/esm/kek/linux.d.ts +92 -0
  108. package/dist/esm/kek/linux.js +585 -0
  109. package/dist/esm/kek/macos.d.ts +112 -0
  110. package/dist/esm/kek/macos.js +586 -0
  111. package/dist/esm/kek/types.d.ts +111 -0
  112. package/dist/esm/kek/types.js +39 -0
  113. package/dist/esm/kek/windows.d.ts +71 -0
  114. package/dist/esm/kek/windows.js +344 -0
  115. package/dist/esm/kek/zeroize-registry.d.ts +44 -0
  116. package/dist/esm/kek/zeroize-registry.js +58 -0
  117. package/dist/esm/legacyStatePreflight.d.ts +67 -0
  118. package/dist/esm/legacyStatePreflight.js +71 -0
  119. package/dist/esm/localIdentity.d.ts +54 -0
  120. package/dist/esm/localIdentity.js +54 -0
  121. package/dist/esm/loginLocalhost.d.ts +115 -0
  122. package/dist/esm/loginLocalhost.js +355 -0
  123. package/dist/esm/loginWithLocalhost.d.ts +131 -0
  124. package/dist/esm/loginWithLocalhost.js +353 -0
  125. package/dist/esm/machineId.d.ts +35 -0
  126. package/dist/esm/machineId.js +231 -0
  127. package/dist/esm/messages.d.ts +9 -0
  128. package/dist/esm/messages.js +40 -0
  129. package/dist/esm/pkce.d.ts +62 -0
  130. package/dist/esm/pkce.js +148 -0
  131. package/dist/esm/recoveryCode.d.ts +61 -0
  132. package/dist/esm/recoveryCode.js +207 -0
  133. package/dist/esm/refresh.d.ts +215 -0
  134. package/dist/esm/refresh.js +863 -0
  135. package/dist/esm/refreshClassification.d.ts +53 -0
  136. package/dist/esm/refreshClassification.js +106 -0
  137. package/dist/esm/refreshScheduler.d.ts +53 -0
  138. package/dist/esm/refreshScheduler.js +329 -0
  139. package/dist/esm/runtime.d.ts +149 -0
  140. package/dist/esm/runtime.js +121 -0
  141. package/dist/esm/spawnEnv.d.ts +76 -0
  142. package/dist/esm/spawnEnv.js +149 -0
  143. package/dist/esm/ttlParser.d.ts +54 -0
  144. package/dist/esm/ttlParser.js +83 -0
  145. package/dist/esm/types.d.ts +91 -0
  146. package/dist/esm/types.js +21 -0
  147. package/package.json +82 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * daemonScopes.ts — daemon-capability scope vocabulary for the
3
+ * non-Mongoose tier.
4
+ *
5
+ * The schema-bound canonical home is
6
+ * `@skrr-ai/data-schemas/common/daemonScopes` — that file owns the
7
+ * Mongoose validators (`VALID_SCOPE_SET`, schema enum allowlists), the
8
+ * consent-screen group metadata (`SCOPE_GROUPS`), and the helper
9
+ * functions that the API server depends on at runtime.
10
+ *
11
+ * This file is the parallel home for tiers that cannot import
12
+ * `@skrr-ai/data-schemas` without dragging Mongoose into their
13
+ * bundle:
14
+ * - `daemon/` (Node CLI / standalone binary, ships via Bun compile)
15
+ * - `desktop/` (Electron main process, lean bundle)
16
+ * - `cli/` (oclif Sky CLI)
17
+ *
18
+ * The two homes are kept byte-equal at CI time by
19
+ * `api/server/services/Auth/__tests__/daemonScopes.parity.spec.js`.
20
+ * A new scope MUST be added in BOTH files; the parity test fails on
21
+ * any drift before merge.
22
+ *
23
+ * # Vocabulary stability
24
+ *
25
+ * The six strings are user-visible (consent screens) and persisted
26
+ * (JWT claims, Mongo column values, Redis hash fields, audit logs).
27
+ * Renaming a scope is a breaking change for every credential already
28
+ * minted with the old value. Add new scopes, deprecate old ones —
29
+ * never rename in place.
30
+ */
31
+ /**
32
+ * The canonical daemon scope vocabulary. Six strings, frozen.
33
+ *
34
+ * - `daemon:tools:bash` — bash tool execution
35
+ * - `daemon:tools:fs:read` — Read tool (file read)
36
+ * - `daemon:tools:fs:write` — Write + Edit tools (file mutation)
37
+ * - `daemon:browser:cdp` — browser automation via CDP (reserved)
38
+ * - `daemon:session:replay` — `daemon:session:replay` socket event
39
+ * - `daemon:offline-queue` — daemon-initiated offline queue
40
+ *
41
+ * Order is the consent-screen render order: tools-first, I/O second,
42
+ * control-flow last.
43
+ */
44
+ export declare const SCOPES: Readonly<{
45
+ readonly TOOLS_BASH: "daemon:tools:bash";
46
+ readonly TOOLS_FS_READ: "daemon:tools:fs:read";
47
+ readonly TOOLS_FS_WRITE: "daemon:tools:fs:write";
48
+ readonly BROWSER_CDP: "daemon:browser:cdp";
49
+ readonly SESSION_REPLAY: "daemon:session:replay";
50
+ readonly OFFLINE_QUEUE: "daemon:offline-queue";
51
+ }>;
52
+ export type DaemonScope = (typeof SCOPES)[keyof typeof SCOPES];
53
+ /**
54
+ * The six daemon scopes in canonical order. Frozen so consumers can
55
+ * pass it directly to OAuth `scope` parameters without defensive
56
+ * copies.
57
+ */
58
+ export declare const ALL_DAEMON_SCOPES: readonly DaemonScope[];
59
+ /**
60
+ * Set form of `ALL_DAEMON_SCOPES` for O(1) membership checks.
61
+ */
62
+ export declare const VALID_DAEMON_SCOPE_SET: ReadonlySet<string>;
63
+ /** Type guard for canonical daemon-scope strings. */
64
+ export declare function isDaemonScope(s: unknown): s is DaemonScope;
65
+ /**
66
+ * `cli` — REST-only sign-in grant for first-party CLI clients. Peer
67
+ * to the six daemon scopes; lives on `OAuthClient.allowedScopes` for
68
+ * the `oversky-cli` client. See the data-schemas canonical for the
69
+ * full reasoning behind keeping this OUT of `ALL_DAEMON_SCOPES` (the
70
+ * grandfather sentinel `expandScopes(undefined)` would over-grant).
71
+ */
72
+ export declare const OAUTH_CLI_SCOPE: "cli";
73
+ export type OAuthCliScope = typeof OAUTH_CLI_SCOPE;
74
+ export type OAuthScope = DaemonScope | OAuthCliScope;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * daemonScopes.ts — daemon-capability scope vocabulary for the
3
+ * non-Mongoose tier.
4
+ *
5
+ * The schema-bound canonical home is
6
+ * `@skrr-ai/data-schemas/common/daemonScopes` — that file owns the
7
+ * Mongoose validators (`VALID_SCOPE_SET`, schema enum allowlists), the
8
+ * consent-screen group metadata (`SCOPE_GROUPS`), and the helper
9
+ * functions that the API server depends on at runtime.
10
+ *
11
+ * This file is the parallel home for tiers that cannot import
12
+ * `@skrr-ai/data-schemas` without dragging Mongoose into their
13
+ * bundle:
14
+ * - `daemon/` (Node CLI / standalone binary, ships via Bun compile)
15
+ * - `desktop/` (Electron main process, lean bundle)
16
+ * - `cli/` (oclif Sky CLI)
17
+ *
18
+ * The two homes are kept byte-equal at CI time by
19
+ * `api/server/services/Auth/__tests__/daemonScopes.parity.spec.js`.
20
+ * A new scope MUST be added in BOTH files; the parity test fails on
21
+ * any drift before merge.
22
+ *
23
+ * # Vocabulary stability
24
+ *
25
+ * The six strings are user-visible (consent screens) and persisted
26
+ * (JWT claims, Mongo column values, Redis hash fields, audit logs).
27
+ * Renaming a scope is a breaking change for every credential already
28
+ * minted with the old value. Add new scopes, deprecate old ones —
29
+ * never rename in place.
30
+ */
31
+ /**
32
+ * The canonical daemon scope vocabulary. Six strings, frozen.
33
+ *
34
+ * - `daemon:tools:bash` — bash tool execution
35
+ * - `daemon:tools:fs:read` — Read tool (file read)
36
+ * - `daemon:tools:fs:write` — Write + Edit tools (file mutation)
37
+ * - `daemon:browser:cdp` — browser automation via CDP (reserved)
38
+ * - `daemon:session:replay` — `daemon:session:replay` socket event
39
+ * - `daemon:offline-queue` — daemon-initiated offline queue
40
+ *
41
+ * Order is the consent-screen render order: tools-first, I/O second,
42
+ * control-flow last.
43
+ */
44
+ export const SCOPES = Object.freeze({
45
+ TOOLS_BASH: 'daemon:tools:bash',
46
+ TOOLS_FS_READ: 'daemon:tools:fs:read',
47
+ TOOLS_FS_WRITE: 'daemon:tools:fs:write',
48
+ BROWSER_CDP: 'daemon:browser:cdp',
49
+ SESSION_REPLAY: 'daemon:session:replay',
50
+ OFFLINE_QUEUE: 'daemon:offline-queue',
51
+ });
52
+ /**
53
+ * The six daemon scopes in canonical order. Frozen so consumers can
54
+ * pass it directly to OAuth `scope` parameters without defensive
55
+ * copies.
56
+ */
57
+ export const ALL_DAEMON_SCOPES = Object.freeze([
58
+ SCOPES.TOOLS_BASH,
59
+ SCOPES.TOOLS_FS_READ,
60
+ SCOPES.TOOLS_FS_WRITE,
61
+ SCOPES.BROWSER_CDP,
62
+ SCOPES.SESSION_REPLAY,
63
+ SCOPES.OFFLINE_QUEUE,
64
+ ]);
65
+ /**
66
+ * Set form of `ALL_DAEMON_SCOPES` for O(1) membership checks.
67
+ */
68
+ export const VALID_DAEMON_SCOPE_SET = new Set(ALL_DAEMON_SCOPES);
69
+ /** Type guard for canonical daemon-scope strings. */
70
+ export function isDaemonScope(s) {
71
+ return typeof s === 'string' && VALID_DAEMON_SCOPE_SET.has(s);
72
+ }
73
+ /**
74
+ * `cli` — REST-only sign-in grant for first-party CLI clients. Peer
75
+ * to the six daemon scopes; lives on `OAuthClient.allowedScopes` for
76
+ * the `oversky-cli` client. See the data-schemas canonical for the
77
+ * full reasoning behind keeping this OUT of `ALL_DAEMON_SCOPES` (the
78
+ * grandfather sentinel `expandScopes(undefined)` would over-grant).
79
+ */
80
+ export const OAUTH_CLI_SCOPE = 'cli';
@@ -0,0 +1,113 @@
1
+ import { type DeviceKeyPair, type Ed25519PublicJwk } from './deviceKey.js';
2
+ type DeviceIdentityState = {
3
+ kind: 'uninit';
4
+ } | {
5
+ kind: 'disabled';
6
+ reason: DisabledReason;
7
+ } | {
8
+ kind: 'active';
9
+ keypair: DeviceKeyPair;
10
+ profile: string;
11
+ envelopeProtected: boolean;
12
+ };
13
+ type DisabledReason = 'init_failed' | 'load_failed' | 'persist_failed';
14
+ /** @internal Test seam — force-set state. */
15
+ export declare function __setStateForTest(next: DeviceIdentityState): DeviceIdentityState;
16
+ /** @internal Test seam — read state. */
17
+ export declare function __getStateForTest(): DeviceIdentityState;
18
+ /**
19
+ * Initialize device identity. Idempotent.
20
+ *
21
+ * Order:
22
+ * 1. Try to load existing keypair from disk.
23
+ * - Success → state = active.
24
+ * - Missing files / corruption / decrypt failure → step 2.
25
+ * 2. Generate fresh keypair and persist. Failure to persist is a hard
26
+ * error landing in disabled+persist_failed.
27
+ */
28
+ export declare function initDeviceIdentity(profile: string): Promise<void>;
29
+ /**
30
+ * Reset state. With `clearOnDisk=true` deletes both keypair files —
31
+ * used by `oversky logout` / `sky logout` so a freshly-logged-in user
32
+ * gets a fresh device identity that the daemon will see on its next start.
33
+ */
34
+ export declare function resetDeviceIdentity(opts?: {
35
+ profile?: string;
36
+ clearOnDisk?: boolean;
37
+ }): Promise<void>;
38
+ /** True iff init has completed and a keypair is in memory. */
39
+ export declare function isDeviceIdentityActive(): boolean;
40
+ /**
41
+ * Export the public key for server enrollment / dashboard display.
42
+ * Returns null when not active so callers know to skip the JWS header
43
+ * on the in-flight request.
44
+ */
45
+ export declare function getDevicePublicKey(): {
46
+ jwk: Ed25519PublicJwk;
47
+ thumbprint: string;
48
+ } | null;
49
+ /**
50
+ * Operator-readable summary of device-identity state. Used by
51
+ * `oversky status` and CLI debug commands. Never includes the private key.
52
+ */
53
+ export declare function describeDeviceIdentityState(): {
54
+ kind: DeviceIdentityState['kind'];
55
+ reason?: DisabledReason;
56
+ thumbprint?: string;
57
+ profile?: string;
58
+ envelopeProtected?: boolean;
59
+ };
60
+ /**
61
+ * Sign an outgoing request with the device key. Returns the JWS Compact
62
+ * Serialization, or null when device identity is not active. NEVER
63
+ * throws — a failed sign returns null and emits a telemetry event so
64
+ * the caller can fall back to bearer-only auth without an outage.
65
+ *
66
+ * Shape matches `DeviceProofSigner` from `./refresh.ts` so the function
67
+ * passes directly into `refreshDaemonToken`'s `signRequestProof` slot.
68
+ */
69
+ export declare function signServerRequest(opts: {
70
+ method: string;
71
+ url: string;
72
+ refreshToken?: string;
73
+ accessToken?: string;
74
+ }): string | null;
75
+ /** @internal Test seams — file path resolvers. */
76
+ export declare function __publicKeyPathForTest(profile: string): string;
77
+ export declare function __privateKeyPathForTest(profile: string): string;
78
+ export declare function __enrollmentMarkerPathForTest(profile: string): string;
79
+ export declare function __enrollmentBackoffPathForTest(profile: string): string;
80
+ /** Remove the enrollment marker so re-login gets a fresh enrollment. */
81
+ export declare function clearEnrollmentMarker(profile: string): void;
82
+ export type EnrollmentResult = {
83
+ enrolled: true;
84
+ thumbprint: string;
85
+ } | {
86
+ enrolled: false;
87
+ reason: 'not_active' | 'already_persisted' | 'backoff_active' | 'http_error' | 'network_error';
88
+ status?: number;
89
+ body?: string;
90
+ message?: string;
91
+ };
92
+ /**
93
+ * POST the device public key to the server for enrollment.
94
+ *
95
+ * Idempotent across boots — the marker file short-circuits subsequent
96
+ * calls. The marker stores serverUrl + thumbprint so a URL change
97
+ * (staging → prod swap) forces fresh enrollment.
98
+ *
99
+ * Fire-and-forget contract — callers should `.catch()` so a network
100
+ * partition at startup cannot stall the consumer's command path.
101
+ *
102
+ * NOTE: Both `sky` and `oversky` may race to enroll the same shared
103
+ * keypair. The server's `enroll-device-key` route is idempotent on
104
+ * `(machineUuid, publicJwkX)` so a duplicate POST is safe; whichever
105
+ * binary writes its marker file first short-circuits the other.
106
+ */
107
+ export declare function enrollWithServer(opts: {
108
+ serverUrl: string;
109
+ accessToken: string;
110
+ machineUuid: string;
111
+ signal?: AbortSignal;
112
+ }): Promise<EnrollmentResult>;
113
+ export {};