@arcanea/auth 1.0.3

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 (54) hide show
  1. package/README.md +43 -0
  2. package/dist/adapters/claude.d.ts +13 -0
  3. package/dist/adapters/claude.d.ts.map +1 -0
  4. package/dist/adapters/claude.js +38 -0
  5. package/dist/adapters/claude.js.map +1 -0
  6. package/dist/adapters/copilot.d.ts +13 -0
  7. package/dist/adapters/copilot.d.ts.map +1 -0
  8. package/dist/adapters/copilot.js +41 -0
  9. package/dist/adapters/copilot.js.map +1 -0
  10. package/dist/adapters/cursor.d.ts +14 -0
  11. package/dist/adapters/cursor.d.ts.map +1 -0
  12. package/dist/adapters/cursor.js +32 -0
  13. package/dist/adapters/cursor.js.map +1 -0
  14. package/dist/adapters/gemini.d.ts +13 -0
  15. package/dist/adapters/gemini.d.ts.map +1 -0
  16. package/dist/adapters/gemini.js +35 -0
  17. package/dist/adapters/gemini.js.map +1 -0
  18. package/dist/adapters/index.d.ts +13 -0
  19. package/dist/adapters/index.d.ts.map +1 -0
  20. package/dist/adapters/index.js +30 -0
  21. package/dist/adapters/index.js.map +1 -0
  22. package/dist/adapters/openai.d.ts +13 -0
  23. package/dist/adapters/openai.d.ts.map +1 -0
  24. package/dist/adapters/openai.js +37 -0
  25. package/dist/adapters/openai.js.map +1 -0
  26. package/dist/adapters/opencode.d.ts +14 -0
  27. package/dist/adapters/opencode.d.ts.map +1 -0
  28. package/dist/adapters/opencode.js +32 -0
  29. package/dist/adapters/opencode.js.map +1 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +13 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/keystore/encrypted-file.d.ts +12 -0
  35. package/dist/keystore/encrypted-file.d.ts.map +1 -0
  36. package/dist/keystore/encrypted-file.js +74 -0
  37. package/dist/keystore/encrypted-file.js.map +1 -0
  38. package/dist/keystore/env.d.ts +12 -0
  39. package/dist/keystore/env.d.ts.map +1 -0
  40. package/dist/keystore/env.js +32 -0
  41. package/dist/keystore/env.js.map +1 -0
  42. package/dist/keystore/index.d.ts +23 -0
  43. package/dist/keystore/index.d.ts.map +1 -0
  44. package/dist/keystore/index.js +47 -0
  45. package/dist/keystore/index.js.map +1 -0
  46. package/dist/types.d.ts +23 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +6 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/validate.d.ts +10 -0
  51. package/dist/validate.d.ts.map +1 -0
  52. package/dist/validate.js +34 -0
  53. package/dist/validate.js.map +1 -0
  54. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @arcanea/auth
2
+
3
+ > **Universal AI provider authentication for the Arcanea ecosystem.**
4
+
5
+ Manages API keys and credentials across AI providers — Anthropic, OpenAI, Google, GitHub Copilot, and more.
6
+
7
+ ## Features
8
+
9
+ - Secure keystore with platform-native credential storage
10
+ - Provider adapters for Claude, ChatGPT, Gemini, Copilot, OpenCode
11
+ - Key validation before storage
12
+ - Unified authentication interface for `@arcanea/cli`
13
+
14
+ ## Usage
15
+
16
+ ```typescript
17
+ import { AuthManager, validateKey } from '@arcanea/auth';
18
+
19
+ const auth = new AuthManager();
20
+
21
+ // Store a key
22
+ await auth.set('anthropic', process.env.ANTHROPIC_API_KEY);
23
+
24
+ // Retrieve a key
25
+ const key = await auth.get('anthropic');
26
+
27
+ // Validate before storing
28
+ const valid = await validateKey('anthropic', key);
29
+ ```
30
+
31
+ ## Supported Providers
32
+
33
+ | Provider | Adapter | Key Format |
34
+ |----------|---------|------------|
35
+ | Anthropic (Claude) | `anthropic` | `sk-ant-*` |
36
+ | OpenAI (ChatGPT) | `openai` | `sk-*` |
37
+ | Google (Gemini) | `google` | API key |
38
+ | GitHub (Copilot) | `github` | `gho_*` / `ghp_*` |
39
+ | OpenCode | `opencode` | Various |
40
+
41
+ ## License
42
+
43
+ MIT
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Claude/Anthropic Auth Adapter
3
+ */
4
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
5
+ export declare class ClaudeAuthAdapter implements AuthAdapter {
6
+ provider: ProviderType;
7
+ displayName: string;
8
+ validate(credential: string): Promise<AuthSession>;
9
+ detectFromEnv(): Promise<AuthSession | null>;
10
+ envVarNames(): string[];
11
+ getSetupUrl(): string;
12
+ }
13
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,EAAE,YAAY,CAAY;IAClC,WAAW,SAAwB;IAE7B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqBlD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAMlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Claude/Anthropic Auth Adapter
3
+ */
4
+ import { httpValidate } from '../validate.js';
5
+ export class ClaudeAuthAdapter {
6
+ provider = 'claude';
7
+ displayName = 'Claude (Anthropic)';
8
+ async validate(credential) {
9
+ const result = await httpValidate('https://api.anthropic.com/v1/models', {
10
+ 'x-api-key': credential,
11
+ 'anthropic-version': '2023-06-01',
12
+ });
13
+ if (!result.ok) {
14
+ return { provider: 'claude', validated: false, models: [], capabilities: [] };
15
+ }
16
+ const data = result.body;
17
+ const models = data?.data?.map((m) => m.id) || [];
18
+ return {
19
+ provider: 'claude',
20
+ validated: true,
21
+ models,
22
+ capabilities: ['chat', 'vision', 'tools', 'computer-use'],
23
+ };
24
+ }
25
+ async detectFromEnv() {
26
+ const key = process.env.ANTHROPIC_API_KEY;
27
+ if (!key)
28
+ return null;
29
+ return this.validate(key);
30
+ }
31
+ envVarNames() {
32
+ return ['ANTHROPIC_API_KEY'];
33
+ }
34
+ getSetupUrl() {
35
+ return 'https://console.anthropic.com/settings/keys';
36
+ }
37
+ }
38
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,GAAiB,QAAQ,CAAC;IAClC,WAAW,GAAG,oBAAoB,CAAC;IAEnC,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC/B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,qCAAqC,EAAE;YACvE,WAAW,EAAE,UAAU;YACvB,mBAAmB,EAAE,YAAY;SAClC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAChF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAwC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAElD,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,MAAM;YACN,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC;SAC1D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC1C,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC/B,CAAC;IAED,WAAW;QACT,OAAO,6CAA6C,CAAC;IACvD,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * GitHub Copilot Auth Adapter
3
+ */
4
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
5
+ export declare class CopilotAuthAdapter implements AuthAdapter {
6
+ provider: ProviderType;
7
+ displayName: string;
8
+ validate(_credential: string): Promise<AuthSession>;
9
+ detectFromEnv(): Promise<AuthSession | null>;
10
+ envVarNames(): string[];
11
+ getSetupUrl(): string;
12
+ }
13
+ //# sourceMappingURL=copilot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/adapters/copilot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,qBAAa,kBAAmB,YAAW,WAAW;IACpD,QAAQ,EAAE,YAAY,CAAa;IACnC,WAAW,SAAoB;IAEzB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAMnD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAuBlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * GitHub Copilot Auth Adapter
3
+ */
4
+ import { execSync } from 'node:child_process';
5
+ export class CopilotAuthAdapter {
6
+ provider = 'copilot';
7
+ displayName = 'GitHub Copilot';
8
+ async validate(_credential) {
9
+ // Copilot auth is via gh CLI, not API key
10
+ const session = await this.detectFromEnv();
11
+ return session ?? { provider: 'copilot', validated: false, models: [], capabilities: [] };
12
+ }
13
+ async detectFromEnv() {
14
+ try {
15
+ const output = execSync('gh auth status 2>&1', { encoding: 'utf-8', stdio: 'pipe' });
16
+ const isLoggedIn = output.includes('Logged in');
17
+ if (!isLoggedIn)
18
+ return null;
19
+ // Extract account info
20
+ const accountMatch = output.match(/account\s+(\S+)/);
21
+ const accountName = accountMatch?.[1];
22
+ return {
23
+ provider: 'copilot',
24
+ validated: true,
25
+ accountName,
26
+ models: ['copilot'],
27
+ capabilities: ['code-completion', 'chat', 'workspace-context'],
28
+ };
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ envVarNames() {
35
+ return ['GITHUB_TOKEN'];
36
+ }
37
+ getSetupUrl() {
38
+ return 'https://github.com/features/copilot';
39
+ }
40
+ }
41
+ //# sourceMappingURL=copilot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/adapters/copilot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,OAAO,kBAAkB;IAC7B,QAAQ,GAAiB,SAAS,CAAC;IACnC,WAAW,GAAG,gBAAgB,CAAC;IAE/B,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,0CAA0C;QAC1C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3C,OAAO,OAAO,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACrF,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAEhD,IAAI,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAC;YAE7B,uBAAuB;YACvB,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrD,MAAM,WAAW,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YAEtC,OAAO;gBACL,QAAQ,EAAE,SAAS;gBACnB,SAAS,EAAE,IAAI;gBACf,WAAW;gBACX,MAAM,EAAE,CAAC,SAAS,CAAC;gBACnB,YAAY,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,mBAAmB,CAAC;aAC/D,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,WAAW;QACT,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1B,CAAC;IAED,WAAW;QACT,OAAO,qCAAqC,CAAC;IAC/C,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Cursor IDE Auth Adapter
3
+ * Cursor is local-first — no authentication required.
4
+ */
5
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
6
+ export declare class CursorAuthAdapter implements AuthAdapter {
7
+ provider: ProviderType;
8
+ displayName: string;
9
+ validate(_credential: string): Promise<AuthSession>;
10
+ detectFromEnv(): Promise<AuthSession | null>;
11
+ envVarNames(): string[];
12
+ getSetupUrl(): string;
13
+ }
14
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,EAAE,YAAY,CAAY;IAClC,WAAW,SAAgB;IAErB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASnD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Cursor IDE Auth Adapter
3
+ * Cursor is local-first — no authentication required.
4
+ */
5
+ export class CursorAuthAdapter {
6
+ provider = 'cursor';
7
+ displayName = 'Cursor IDE';
8
+ async validate(_credential) {
9
+ return {
10
+ provider: 'cursor',
11
+ validated: true,
12
+ models: ['local'],
13
+ capabilities: ['chat', 'plugins', 'hooks'],
14
+ };
15
+ }
16
+ async detectFromEnv() {
17
+ // Always valid — no auth needed
18
+ return {
19
+ provider: 'cursor',
20
+ validated: true,
21
+ models: ['local'],
22
+ capabilities: ['chat', 'plugins', 'hooks'],
23
+ };
24
+ }
25
+ envVarNames() {
26
+ return [];
27
+ }
28
+ getSetupUrl() {
29
+ return 'https://cursor.com';
30
+ }
31
+ }
32
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/adapters/cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,GAAiB,QAAQ,CAAC;IAClC,WAAW,GAAG,YAAY,CAAC;IAE3B,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,OAAO,CAAC;YACjB,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,gCAAgC;QAChC,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,OAAO,CAAC;YACjB,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,WAAW;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,WAAW;QACT,OAAO,oBAAoB,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Google Gemini Auth Adapter
3
+ */
4
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
5
+ export declare class GeminiAuthAdapter implements AuthAdapter {
6
+ provider: ProviderType;
7
+ displayName: string;
8
+ validate(credential: string): Promise<AuthSession>;
9
+ detectFromEnv(): Promise<AuthSession | null>;
10
+ envVarNames(): string[];
11
+ getSetupUrl(): string;
12
+ }
13
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,EAAE,YAAY,CAAY;IAClC,WAAW,SAAqB;IAE1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqBlD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAMlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Google Gemini Auth Adapter
3
+ */
4
+ import { httpValidate } from '../validate.js';
5
+ export class GeminiAuthAdapter {
6
+ provider = 'gemini';
7
+ displayName = 'Gemini (Google)';
8
+ async validate(credential) {
9
+ const result = await httpValidate(`https://generativelanguage.googleapis.com/v1beta/models?key=${credential}`, {});
10
+ if (!result.ok) {
11
+ return { provider: 'gemini', validated: false, models: [], capabilities: [] };
12
+ }
13
+ const data = result.body;
14
+ const models = data?.models?.map((m) => m.name.replace('models/', '')).slice(0, 10) || [];
15
+ return {
16
+ provider: 'gemini',
17
+ validated: true,
18
+ models,
19
+ capabilities: ['chat', 'vision', 'image-generation', 'grounding'],
20
+ };
21
+ }
22
+ async detectFromEnv() {
23
+ const key = process.env.GEMINI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
24
+ if (!key)
25
+ return null;
26
+ return this.validate(key);
27
+ }
28
+ envVarNames() {
29
+ return ['GEMINI_API_KEY', 'GOOGLE_GENERATIVE_AI_API_KEY'];
30
+ }
31
+ getSetupUrl() {
32
+ return 'https://aistudio.google.com/app/apikey';
33
+ }
34
+ }
35
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,GAAiB,QAAQ,CAAC;IAClC,WAAW,GAAG,iBAAiB,CAAC;IAEhC,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC/B,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,+DAA+D,UAAU,EAAE,EAC3E,EAAE,CACH,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAChF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAA4C,CAAC;QACjE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;QAE1F,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,MAAM;YACN,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,CAAC;SAClE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;QACnF,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,OAAO,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,CAAC;IAC5D,CAAC;IAED,WAAW;QACT,OAAO,wCAAwC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Auth Adapter Registry
3
+ */
4
+ import type { AuthAdapter, ProviderType } from '@arcanea/os';
5
+ export declare function getAuthAdapter(provider: ProviderType): AuthAdapter;
6
+ export declare function getAllAdapters(): AuthAdapter[];
7
+ export declare function getAdapterByEnvVar(envVar: string): AuthAdapter | undefined;
8
+ export { ClaudeAuthAdapter } from './claude.js';
9
+ export { OpenAIAuthAdapter } from './openai.js';
10
+ export { GeminiAuthAdapter } from './gemini.js';
11
+ export { CopilotAuthAdapter } from './copilot.js';
12
+ export { CursorAuthAdapter } from './cursor.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe7D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAElE;AAED,wBAAgB,cAAc,IAAI,WAAW,EAAE,CAE9C;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE1E;AAED,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auth Adapter Registry
3
+ */
4
+ import { ClaudeAuthAdapter } from './claude.js';
5
+ import { OpenAIAuthAdapter } from './openai.js';
6
+ import { GeminiAuthAdapter } from './gemini.js';
7
+ import { CopilotAuthAdapter } from './copilot.js';
8
+ import { CursorAuthAdapter } from './cursor.js';
9
+ const adapters = {
10
+ claude: new ClaudeAuthAdapter(),
11
+ openai: new OpenAIAuthAdapter(),
12
+ gemini: new GeminiAuthAdapter(),
13
+ copilot: new CopilotAuthAdapter(),
14
+ cursor: new CursorAuthAdapter(),
15
+ };
16
+ export function getAuthAdapter(provider) {
17
+ return adapters[provider];
18
+ }
19
+ export function getAllAdapters() {
20
+ return Object.values(adapters);
21
+ }
22
+ export function getAdapterByEnvVar(envVar) {
23
+ return Object.values(adapters).find((a) => a.envVarNames().includes(envVar));
24
+ }
25
+ export { ClaudeAuthAdapter } from './claude.js';
26
+ export { OpenAIAuthAdapter } from './openai.js';
27
+ export { GeminiAuthAdapter } from './gemini.js';
28
+ export { CopilotAuthAdapter } from './copilot.js';
29
+ export { CursorAuthAdapter } from './cursor.js';
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,QAAQ,GAAsC;IAClD,MAAM,EAAE,IAAI,iBAAiB,EAAE;IAC/B,MAAM,EAAE,IAAI,iBAAiB,EAAE;IAC/B,MAAM,EAAE,IAAI,iBAAiB,EAAE;IAC/B,OAAO,EAAE,IAAI,kBAAkB,EAAE;IACjC,MAAM,EAAE,IAAI,iBAAiB,EAAE;CAChC,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAsB;IACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OpenAI/ChatGPT Auth Adapter
3
+ */
4
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
5
+ export declare class OpenAIAuthAdapter implements AuthAdapter {
6
+ provider: ProviderType;
7
+ displayName: string;
8
+ validate(credential: string): Promise<AuthSession>;
9
+ detectFromEnv(): Promise<AuthSession | null>;
10
+ envVarNames(): string[];
11
+ getSetupUrl(): string;
12
+ }
13
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,EAAE,YAAY,CAAY;IAClC,WAAW,SAAsB;IAE3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAoBlD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAMlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * OpenAI/ChatGPT Auth Adapter
3
+ */
4
+ import { httpValidate } from '../validate.js';
5
+ export class OpenAIAuthAdapter {
6
+ provider = 'openai';
7
+ displayName = 'ChatGPT (OpenAI)';
8
+ async validate(credential) {
9
+ const result = await httpValidate('https://api.openai.com/v1/models', {
10
+ Authorization: `Bearer ${credential}`,
11
+ });
12
+ if (!result.ok) {
13
+ return { provider: 'openai', validated: false, models: [], capabilities: [] };
14
+ }
15
+ const data = result.body;
16
+ const models = data?.data?.map((m) => m.id).filter((id) => id.startsWith('gpt')).slice(0, 10) || [];
17
+ return {
18
+ provider: 'openai',
19
+ validated: true,
20
+ models,
21
+ capabilities: ['chat', 'vision', 'tools', 'assistants', 'custom-gpt'],
22
+ };
23
+ }
24
+ async detectFromEnv() {
25
+ const key = process.env.OPENAI_API_KEY;
26
+ if (!key)
27
+ return null;
28
+ return this.validate(key);
29
+ }
30
+ envVarNames() {
31
+ return ['OPENAI_API_KEY'];
32
+ }
33
+ getSetupUrl() {
34
+ return 'https://platform.openai.com/api-keys';
35
+ }
36
+ }
37
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,GAAiB,QAAQ,CAAC;IAClC,WAAW,GAAG,kBAAkB,CAAC;IAEjC,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC/B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,kCAAkC,EAAE;YACpE,aAAa,EAAE,UAAU,UAAU,EAAE;SACtC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAChF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAwC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;QAEpG,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,MAAM;YACN,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC;SACtE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,OAAO,sCAAsC,CAAC;IAChD,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * OpenCode Auth Adapter
3
+ * OpenCode is open-source — no authentication required.
4
+ */
5
+ import type { AuthSession, AuthAdapter, ProviderType } from '@arcanea/os';
6
+ export declare class OpenCodeAuthAdapter implements AuthAdapter {
7
+ provider: ProviderType;
8
+ displayName: string;
9
+ validate(_credential: string): Promise<AuthSession>;
10
+ detectFromEnv(): Promise<AuthSession | null>;
11
+ envVarNames(): string[];
12
+ getSetupUrl(): string;
13
+ }
14
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1E,qBAAa,mBAAoB,YAAW,WAAW;IACrD,QAAQ,EAAE,YAAY,CAAc;IACpC,WAAW,SAAgB;IAErB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASnD,aAAa,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUlD,WAAW,IAAI,MAAM,EAAE;IAIvB,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * OpenCode Auth Adapter
3
+ * OpenCode is open-source — no authentication required.
4
+ */
5
+ export class OpenCodeAuthAdapter {
6
+ provider = 'opencode';
7
+ displayName = 'Cursor IDE';
8
+ async validate(_credential) {
9
+ return {
10
+ provider: 'opencode',
11
+ validated: true,
12
+ models: ['local'],
13
+ capabilities: ['chat', 'plugins', 'hooks'],
14
+ };
15
+ }
16
+ async detectFromEnv() {
17
+ // Always valid — no auth needed
18
+ return {
19
+ provider: 'opencode',
20
+ validated: true,
21
+ models: ['local'],
22
+ capabilities: ['chat', 'plugins', 'hooks'],
23
+ };
24
+ }
25
+ envVarNames() {
26
+ return [];
27
+ }
28
+ getSetupUrl() {
29
+ return 'https://opencode.ai';
30
+ }
31
+ }
32
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,OAAO,mBAAmB;IAC9B,QAAQ,GAAiB,UAAU,CAAC;IACpC,WAAW,GAAG,YAAY,CAAC;IAE3B,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,OAAO;YACL,QAAQ,EAAE,UAAU;YACpB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,OAAO,CAAC;YACjB,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,gCAAgC;QAChC,OAAO;YACL,QAAQ,EAAE,UAAU;YACpB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,OAAO,CAAC;YACjB,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,WAAW;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,WAAW;QACT,OAAO,qBAAqB,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @arcanea/auth
3
+ * Universal AI provider authentication for the Arcanea ecosystem.
4
+ */
5
+ export { getAuthAdapter, getAllAdapters, getAdapterByEnvVar, ClaudeAuthAdapter, OpenAIAuthAdapter, GeminiAuthAdapter, CopilotAuthAdapter, CursorAuthAdapter, } from './adapters/index.js';
6
+ export { createKeystore, CascadingKeystore, EncryptedFileKeystore, EnvKeystore, } from './keystore/index.js';
7
+ export type { KeystoreBackend } from './keystore/index.js';
8
+ export type { AuthConfig, ValidationResult, KeystoreEntry } from './types.js';
9
+ export { httpValidate, maskCredential } from './validate.js';
10
+ export type { AuthSession, AuthAdapter, Keystore, ProviderType } from '@arcanea/os';
11
+ export declare const VERSION = "1.0.0";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG7D,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGpF,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @arcanea/auth
3
+ * Universal AI provider authentication for the Arcanea ecosystem.
4
+ */
5
+ // Adapters
6
+ export { getAuthAdapter, getAllAdapters, getAdapterByEnvVar, ClaudeAuthAdapter, OpenAIAuthAdapter, GeminiAuthAdapter, CopilotAuthAdapter, CursorAuthAdapter, } from './adapters/index.js';
7
+ // Keystore
8
+ export { createKeystore, CascadingKeystore, EncryptedFileKeystore, EnvKeystore, } from './keystore/index.js';
9
+ // Utilities
10
+ export { httpValidate, maskCredential } from './validate.js';
11
+ // Version
12
+ export const VERSION = '1.0.0';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,WAAW;AACX,OAAO,EACL,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,WAAW;AACX,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAM7B,YAAY;AACZ,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAK7D,UAAU;AACV,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Encrypted File Keystore
3
+ * Stores credentials in an encrypted JSON file at ~/.arcanea/credentials.enc
4
+ */
5
+ import type { Keystore, ProviderType } from '@arcanea/os';
6
+ export declare class EncryptedFileKeystore implements Keystore {
7
+ save(provider: ProviderType, credential: string): Promise<void>;
8
+ load(provider: ProviderType): Promise<string | null>;
9
+ delete(provider: ProviderType): Promise<void>;
10
+ list(): Promise<ProviderType[]>;
11
+ }
12
+ //# sourceMappingURL=encrypted-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypted-file.d.ts","sourceRoot":"","sources":["../../src/keystore/encrypted-file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAqD1D,qBAAa,qBAAsB,YAAW,QAAQ;IAC9C,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKpD,MAAM,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;CAItC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Encrypted File Keystore
3
+ * Stores credentials in an encrypted JSON file at ~/.arcanea/credentials.enc
4
+ */
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'node:crypto';
9
+ const ARCANEA_DIR = join(homedir(), '.arcanea');
10
+ const CREDS_FILE = join(ARCANEA_DIR, 'credentials.enc');
11
+ const ALGORITHM = 'aes-256-gcm';
12
+ function getMachineKey() {
13
+ // Derive key from machine-specific data (hostname + homedir)
14
+ const seed = `arcanea-${homedir()}-${process.env.USER || process.env.USERNAME || 'default'}`;
15
+ return createHash('sha256').update(seed).digest();
16
+ }
17
+ function encrypt(plaintext) {
18
+ const key = getMachineKey();
19
+ const iv = randomBytes(16);
20
+ const cipher = createCipheriv(ALGORITHM, key, iv);
21
+ let encrypted = cipher.update(plaintext, 'utf8', 'hex');
22
+ encrypted += cipher.final('hex');
23
+ const authTag = cipher.getAuthTag().toString('hex');
24
+ return `${iv.toString('hex')}:${authTag}:${encrypted}`;
25
+ }
26
+ function decrypt(ciphertext) {
27
+ const [ivHex, authTagHex, encrypted] = ciphertext.split(':');
28
+ const key = getMachineKey();
29
+ const iv = Buffer.from(ivHex, 'hex');
30
+ const authTag = Buffer.from(authTagHex, 'hex');
31
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
32
+ decipher.setAuthTag(authTag);
33
+ let decrypted = decipher.update(encrypted, 'hex', 'utf8');
34
+ decrypted += decipher.final('utf8');
35
+ return decrypted;
36
+ }
37
+ function readStore() {
38
+ if (!existsSync(CREDS_FILE))
39
+ return {};
40
+ try {
41
+ const raw = readFileSync(CREDS_FILE, 'utf-8');
42
+ return JSON.parse(decrypt(raw));
43
+ }
44
+ catch {
45
+ return {};
46
+ }
47
+ }
48
+ function writeStore(store) {
49
+ if (!existsSync(ARCANEA_DIR)) {
50
+ mkdirSync(ARCANEA_DIR, { recursive: true, mode: 0o700 });
51
+ }
52
+ writeFileSync(CREDS_FILE, encrypt(JSON.stringify(store)), { mode: 0o600 });
53
+ }
54
+ export class EncryptedFileKeystore {
55
+ async save(provider, credential) {
56
+ const store = readStore();
57
+ store[provider] = { credential, savedAt: new Date().toISOString() };
58
+ writeStore(store);
59
+ }
60
+ async load(provider) {
61
+ const store = readStore();
62
+ return store[provider]?.credential || null;
63
+ }
64
+ async delete(provider) {
65
+ const store = readStore();
66
+ delete store[provider];
67
+ writeStore(store);
68
+ }
69
+ async list() {
70
+ const store = readStore();
71
+ return Object.keys(store);
72
+ }
73
+ }
74
+ //# sourceMappingURL=encrypted-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypted-file.js","sourceRoot":"","sources":["../../src/keystore/encrypted-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Environment Variable Keystore
3
+ * Reads credentials from environment variables.
4
+ */
5
+ import type { Keystore, ProviderType } from '@arcanea/os';
6
+ export declare class EnvKeystore implements Keystore {
7
+ save(_provider: ProviderType, _credential: string): Promise<void>;
8
+ load(provider: ProviderType): Promise<string | null>;
9
+ delete(_provider: ProviderType): Promise<void>;
10
+ list(): Promise<ProviderType[]>;
11
+ }
12
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/keystore/env.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1D,qBAAa,WAAY,YAAW,QAAQ;IACpC,IAAI,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASpD,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;CAQtC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Environment Variable Keystore
3
+ * Reads credentials from environment variables.
4
+ */
5
+ import { getAuthAdapter } from '../adapters/index.js';
6
+ export class EnvKeystore {
7
+ async save(_provider, _credential) {
8
+ throw new Error('Cannot save to environment variables. Set them in your shell profile.');
9
+ }
10
+ async load(provider) {
11
+ const adapter = getAuthAdapter(provider);
12
+ for (const envVar of adapter.envVarNames()) {
13
+ const value = process.env[envVar];
14
+ if (value)
15
+ return value;
16
+ }
17
+ return null;
18
+ }
19
+ async delete(_provider) {
20
+ throw new Error('Cannot delete environment variables from here.');
21
+ }
22
+ async list() {
23
+ const providers = ['claude', 'openai', 'gemini', 'copilot', 'cursor'];
24
+ const found = [];
25
+ for (const p of providers) {
26
+ if (await this.load(p))
27
+ found.push(p);
28
+ }
29
+ return found;
30
+ }
31
+ }
32
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/keystore/env.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,IAAI,CAAC,SAAuB,EAAE,WAAmB;QACrD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAsB;QAC/B,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAuB;QAClC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,SAAS,GAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtF,MAAM,KAAK,GAAmB,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Keystore Factory
3
+ * Creates the appropriate keystore based on platform capabilities.
4
+ */
5
+ import type { Keystore, ProviderType } from '@arcanea/os';
6
+ export type KeystoreBackend = 'encrypted-file' | 'env-only';
7
+ /**
8
+ * Cascading keystore that checks multiple backends in order:
9
+ * 1. Environment variables (always checked first)
10
+ * 2. Encrypted file store (for saved credentials)
11
+ */
12
+ export declare class CascadingKeystore implements Keystore {
13
+ private envStore;
14
+ private fileStore;
15
+ save(provider: ProviderType, credential: string): Promise<void>;
16
+ load(provider: ProviderType): Promise<string | null>;
17
+ delete(provider: ProviderType): Promise<void>;
18
+ list(): Promise<ProviderType[]>;
19
+ }
20
+ export declare function createKeystore(backend?: KeystoreBackend): Keystore;
21
+ export { EncryptedFileKeystore } from './encrypted-file.js';
22
+ export { EnvKeystore } from './env.js';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keystore/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI1D,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,UAAU,CAAC;AAE5D;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,SAAS,CAA+B;IAE1C,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASpD,MAAM,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;CAKtC;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CASlE;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Keystore Factory
3
+ * Creates the appropriate keystore based on platform capabilities.
4
+ */
5
+ import { EncryptedFileKeystore } from './encrypted-file.js';
6
+ import { EnvKeystore } from './env.js';
7
+ /**
8
+ * Cascading keystore that checks multiple backends in order:
9
+ * 1. Environment variables (always checked first)
10
+ * 2. Encrypted file store (for saved credentials)
11
+ */
12
+ export class CascadingKeystore {
13
+ envStore = new EnvKeystore();
14
+ fileStore = new EncryptedFileKeystore();
15
+ async save(provider, credential) {
16
+ return this.fileStore.save(provider, credential);
17
+ }
18
+ async load(provider) {
19
+ // Env vars take priority
20
+ const envCred = await this.envStore.load(provider);
21
+ if (envCred)
22
+ return envCred;
23
+ // Fall back to encrypted file
24
+ return this.fileStore.load(provider);
25
+ }
26
+ async delete(provider) {
27
+ return this.fileStore.delete(provider);
28
+ }
29
+ async list() {
30
+ const envProviders = await this.envStore.list();
31
+ const fileProviders = await this.fileStore.list();
32
+ return [...new Set([...envProviders, ...fileProviders])];
33
+ }
34
+ }
35
+ export function createKeystore(backend) {
36
+ switch (backend) {
37
+ case 'env-only':
38
+ return new EnvKeystore();
39
+ case 'encrypted-file':
40
+ return new EncryptedFileKeystore();
41
+ default:
42
+ return new CascadingKeystore();
43
+ }
44
+ }
45
+ export { EncryptedFileKeystore } from './encrypted-file.js';
46
+ export { EnvKeystore } from './env.js';
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keystore/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAIvC;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IACpB,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;IAC7B,SAAS,GAAG,IAAI,qBAAqB,EAAE,CAAC;IAEhD,KAAK,CAAC,IAAI,CAAC,QAAsB,EAAE,UAAkB;QACnD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAsB;QAC/B,yBAAyB;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAE5B,8BAA8B;QAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAsB;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACtD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,IAAI,WAAW,EAAE,CAAC;QAC3B,KAAK,gBAAgB;YACnB,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACrC;YACE,OAAO,IAAI,iBAAiB,EAAE,CAAC;IACnC,CAAC;AACH,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @arcanea/auth - Types
3
+ * Re-exports core overlay types + auth-specific types.
4
+ */
5
+ import type { ProviderType, AuthSession } from '@arcanea/os';
6
+ export type { ProviderType, AuthSession, AuthAdapter, Keystore, } from '@arcanea/os';
7
+ export interface AuthConfig {
8
+ providers: ProviderType[];
9
+ keystoreBackend?: 'system' | 'encrypted-file' | 'env-only';
10
+ encryptionKey?: string;
11
+ }
12
+ export interface ValidationResult {
13
+ valid: boolean;
14
+ session?: AuthSession;
15
+ error?: string;
16
+ }
17
+ export interface KeystoreEntry {
18
+ provider: ProviderType;
19
+ credential: string;
20
+ savedAt: string;
21
+ lastValidated?: string;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,GACT,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,QAAQ,GAAG,gBAAgB,GAAG,UAAU,CAAC;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @arcanea/auth - Types
3
+ * Re-exports core overlay types + auth-specific types.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * HTTP validation helpers for provider API keys.
3
+ */
4
+ export declare function httpValidate(url: string, headers: Record<string, string>): Promise<{
5
+ ok: boolean;
6
+ status: number;
7
+ body: unknown;
8
+ }>;
9
+ export declare function maskCredential(credential: string): string;
10
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAsBzD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKzD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * HTTP validation helpers for provider API keys.
3
+ */
4
+ export async function httpValidate(url, headers) {
5
+ try {
6
+ const response = await fetch(url, {
7
+ method: 'GET',
8
+ headers: {
9
+ ...headers,
10
+ 'User-Agent': 'Arcanea-Auth/1.0',
11
+ },
12
+ signal: AbortSignal.timeout(10000),
13
+ });
14
+ let body;
15
+ try {
16
+ body = await response.json();
17
+ }
18
+ catch {
19
+ body = await response.text();
20
+ }
21
+ return { ok: response.ok, status: response.status, body };
22
+ }
23
+ catch (error) {
24
+ return { ok: false, status: 0, body: String(error) };
25
+ }
26
+ }
27
+ export function maskCredential(credential) {
28
+ if (credential.length <= 8)
29
+ return '••••••••';
30
+ const prefix = credential.slice(0, 7);
31
+ const suffix = credential.slice(-4);
32
+ return `${prefix}•••${suffix}`;
33
+ }
34
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,OAA+B;IAE/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,GAAG,OAAO;gBACV,YAAY,EAAE,kBAAkB;aACjC;YACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACvD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,GAAG,MAAM,MAAM,MAAM,EAAE,CAAC;AACjC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@arcanea/auth",
3
+ "version": "1.0.3",
4
+ "description": "Universal AI provider authentication for the Arcanea ecosystem",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./adapters": {
14
+ "types": "./dist/adapters/index.d.ts",
15
+ "import": "./dist/adapters/index.js"
16
+ },
17
+ "./keystore": {
18
+ "types": "./dist/keystore/index.d.ts",
19
+ "import": "./dist/keystore/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "dev": "tsc --watch",
29
+ "clean": "rm -rf dist",
30
+ "prepublishOnly": "npm run build",
31
+ "test": "node --test tests/*.test.mjs",
32
+ "type-check": "tsc --noEmit"
33
+ },
34
+ "keywords": [
35
+ "arcanea",
36
+ "auth",
37
+ "ai",
38
+ "claude",
39
+ "openai",
40
+ "gemini",
41
+ "copilot"
42
+ ],
43
+ "author": "FrankX <frank@frankx.ai>",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/frankxai/arcanea.git",
48
+ "directory": "packages/auth"
49
+ },
50
+ "dependencies": {
51
+ "@arcanea/os": "workspace:*"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^20.10.0",
55
+ "typescript": "^5.3.0"
56
+ },
57
+ "engines": {
58
+ "node": ">=18.0.0"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ }
63
+ }