@ecmaos/coreutils 0.1.3 → 0.1.4
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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +8 -0
- package/dist/commands/passkey.d.ts +4 -0
- package/dist/commands/passkey.d.ts.map +1 -0
- package/dist/commands/passkey.js +184 -0
- package/dist/commands/passkey.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/passkey.ts +208 -0
- package/src/index.ts +2 -0
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Kernel, Shell, Terminal } from '@ecmaos/types';
|
|
2
|
+
import { TerminalCommand } from '../shared/terminal-command.js';
|
|
3
|
+
export declare function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal): TerminalCommand;
|
|
4
|
+
//# sourceMappingURL=passkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkey.d.ts","sourceRoot":"","sources":["../../src/commands/passkey.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAW,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAG/D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,eAAe,CAyM/F"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { TerminalCommand } from '../shared/terminal-command.js';
|
|
3
|
+
import { writelnStdout, writelnStderr } from '../shared/helpers.js';
|
|
4
|
+
export function createCommand(kernel, shell, terminal) {
|
|
5
|
+
return new TerminalCommand({
|
|
6
|
+
command: 'passkey',
|
|
7
|
+
description: 'Manage passkey credentials for WebAuthn authentication',
|
|
8
|
+
kernel,
|
|
9
|
+
shell,
|
|
10
|
+
terminal,
|
|
11
|
+
options: [
|
|
12
|
+
{ name: 'help', type: Boolean, description: kernel.i18n.t('Display help') },
|
|
13
|
+
{ name: 'subcommand', type: String, defaultOption: true, description: 'Subcommand: register, list, remove, remove-all' },
|
|
14
|
+
{ name: 'name', type: String, description: 'Name/description for the passkey (used with register)' },
|
|
15
|
+
{ name: 'id', type: String, description: 'Passkey ID to remove (used with remove)' }
|
|
16
|
+
],
|
|
17
|
+
run: async (argv, process) => {
|
|
18
|
+
if (!process)
|
|
19
|
+
return 1;
|
|
20
|
+
const currentUid = shell.credentials.uid;
|
|
21
|
+
const user = kernel.users.get(currentUid);
|
|
22
|
+
if (!user) {
|
|
23
|
+
await writelnStderr(process, terminal, chalk.red('Error: Current user not found'));
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
const subcommand = argv.subcommand?.toLowerCase();
|
|
27
|
+
if (!subcommand || subcommand === 'help' || argv.help) {
|
|
28
|
+
await writelnStdout(process, terminal, 'Usage: passkey <subcommand> [options]');
|
|
29
|
+
await writelnStdout(process, terminal, '');
|
|
30
|
+
await writelnStdout(process, terminal, 'Subcommands:');
|
|
31
|
+
await writelnStdout(process, terminal, ' register [--name <name>] Register a new passkey');
|
|
32
|
+
await writelnStdout(process, terminal, ' list List all registered passkeys');
|
|
33
|
+
await writelnStdout(process, terminal, ' remove --id <id> Remove a specific passkey');
|
|
34
|
+
await writelnStdout(process, terminal, ' remove-all Remove all passkeys');
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
switch (subcommand) {
|
|
39
|
+
case 'register': {
|
|
40
|
+
if (!kernel.auth.passkey.isSupported()) {
|
|
41
|
+
await writelnStderr(process, terminal, chalk.red('Error: WebAuthn is not supported in this browser'));
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
const name = argv.name || undefined;
|
|
45
|
+
const username = user.username;
|
|
46
|
+
const userId = new TextEncoder().encode(username);
|
|
47
|
+
const challenge = crypto.getRandomValues(new Uint8Array(32));
|
|
48
|
+
const rpId = globalThis.location.hostname || 'localhost';
|
|
49
|
+
const createOptions = {
|
|
50
|
+
challenge,
|
|
51
|
+
rp: {
|
|
52
|
+
name: kernel.name || 'ecmaOS',
|
|
53
|
+
id: rpId
|
|
54
|
+
},
|
|
55
|
+
user: {
|
|
56
|
+
id: userId,
|
|
57
|
+
name: username,
|
|
58
|
+
displayName: username
|
|
59
|
+
},
|
|
60
|
+
pubKeyCredParams: [
|
|
61
|
+
{ type: 'public-key', alg: -7 },
|
|
62
|
+
{ type: 'public-key', alg: -257 }
|
|
63
|
+
],
|
|
64
|
+
authenticatorSelection: {
|
|
65
|
+
userVerification: 'preferred'
|
|
66
|
+
},
|
|
67
|
+
timeout: 60000
|
|
68
|
+
};
|
|
69
|
+
await writelnStdout(process, terminal, chalk.yellow('Please interact with your authenticator to register a passkey...'));
|
|
70
|
+
const credential = await kernel.auth.passkey.create(createOptions);
|
|
71
|
+
if (!credential || !(credential instanceof PublicKeyCredential)) {
|
|
72
|
+
await writelnStderr(process, terminal, chalk.red('Error: Failed to create passkey. Registration cancelled or failed.'));
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
const publicKeyCredential = credential;
|
|
76
|
+
const response = publicKeyCredential.response;
|
|
77
|
+
const credentialId = btoa(String.fromCharCode(...new Uint8Array(publicKeyCredential.rawId)));
|
|
78
|
+
let publicKeyArray;
|
|
79
|
+
try {
|
|
80
|
+
if (typeof response.getPublicKey === 'function') {
|
|
81
|
+
try {
|
|
82
|
+
const publicKeyCrypto = response.getPublicKey();
|
|
83
|
+
if (publicKeyCrypto && publicKeyCrypto instanceof CryptoKey) {
|
|
84
|
+
const publicKeyJwk = await crypto.subtle.exportKey('jwk', publicKeyCrypto);
|
|
85
|
+
publicKeyArray = new TextEncoder().encode(JSON.stringify(publicKeyJwk));
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
throw new Error('getPublicKey() did not return a valid CryptoKey');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (exportError) {
|
|
92
|
+
await writelnStderr(process, terminal, chalk.yellow(`Warning: Could not extract public key via getPublicKey(): ${exportError instanceof Error ? exportError.message : String(exportError)}. Using attestationObject instead.`));
|
|
93
|
+
const attestationObject = response.attestationObject;
|
|
94
|
+
publicKeyArray = new Uint8Array(attestationObject);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const attestationObject = response.attestationObject;
|
|
99
|
+
publicKeyArray = new Uint8Array(attestationObject);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
await writelnStderr(process, terminal, chalk.red(`Error processing credential data: ${error instanceof Error ? error.message : String(error)}`));
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
const passkey = {
|
|
107
|
+
id: crypto.randomUUID(),
|
|
108
|
+
credentialId,
|
|
109
|
+
publicKey: publicKeyArray,
|
|
110
|
+
createdAt: Date.now(),
|
|
111
|
+
name
|
|
112
|
+
};
|
|
113
|
+
await kernel.users.addPasskey(currentUid, passkey);
|
|
114
|
+
await writelnStdout(process, terminal, chalk.green(`Passkey registered successfully${name ? `: ${name}` : ''}`));
|
|
115
|
+
await writelnStdout(process, terminal, `Passkey ID: ${passkey.id}`);
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
case 'list': {
|
|
119
|
+
const passkeys = await kernel.users.getPasskeys(currentUid);
|
|
120
|
+
if (passkeys.length === 0) {
|
|
121
|
+
await writelnStdout(process, terminal, 'No passkeys registered for this user.');
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
await writelnStdout(process, terminal, `Registered passkeys (${passkeys.length}):`);
|
|
125
|
+
await writelnStdout(process, terminal, '');
|
|
126
|
+
for (const pk of passkeys) {
|
|
127
|
+
const createdDate = new Date(pk.createdAt).toLocaleString();
|
|
128
|
+
const lastUsedDate = pk.lastUsed ? new Date(pk.lastUsed).toLocaleString() : 'Never';
|
|
129
|
+
await writelnStdout(process, terminal, ` ID: ${pk.id}`);
|
|
130
|
+
if (pk.name) {
|
|
131
|
+
await writelnStdout(process, terminal, ` Name: ${pk.name}`);
|
|
132
|
+
}
|
|
133
|
+
await writelnStdout(process, terminal, ` Created: ${createdDate}`);
|
|
134
|
+
await writelnStdout(process, terminal, ` Last used: ${lastUsedDate}`);
|
|
135
|
+
await writelnStdout(process, terminal, '');
|
|
136
|
+
}
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
case 'remove': {
|
|
140
|
+
const id = argv.id;
|
|
141
|
+
if (!id) {
|
|
142
|
+
await writelnStderr(process, terminal, chalk.red('Error: --id is required for remove command'));
|
|
143
|
+
await writelnStdout(process, terminal, 'Usage: passkey remove --id <id>');
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
const passkeys = await kernel.users.getPasskeys(currentUid);
|
|
147
|
+
const passkey = passkeys.find(pk => pk.id === id);
|
|
148
|
+
if (!passkey) {
|
|
149
|
+
await writelnStderr(process, terminal, chalk.red(`Error: Passkey with ID ${id} not found`));
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
await kernel.users.removePasskey(currentUid, id);
|
|
153
|
+
await writelnStdout(process, terminal, chalk.green(`Passkey removed successfully${passkey.name ? `: ${passkey.name}` : ''}`));
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
case 'remove-all': {
|
|
157
|
+
const passkeys = await kernel.users.getPasskeys(currentUid);
|
|
158
|
+
if (passkeys.length === 0) {
|
|
159
|
+
await writelnStdout(process, terminal, 'No passkeys to remove.');
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
await kernel.users.savePasskeys(currentUid, []);
|
|
163
|
+
const passkeysPath = `${user.home}/.passkeys`;
|
|
164
|
+
try {
|
|
165
|
+
await kernel.filesystem.fs.unlink(passkeysPath);
|
|
166
|
+
}
|
|
167
|
+
catch { }
|
|
168
|
+
await writelnStdout(process, terminal, chalk.green(`Removed ${passkeys.length} passkey(s)`));
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
default:
|
|
172
|
+
await writelnStderr(process, terminal, chalk.red(`Error: Unknown subcommand: ${subcommand}`));
|
|
173
|
+
await writelnStdout(process, terminal, 'Run "passkey help" for usage information');
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
await writelnStderr(process, terminal, chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
179
|
+
return 1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=passkey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkey.js","sourceRoot":"","sources":["../../src/commands/passkey.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAG9D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAG9D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAwB5F,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,CAsBtH;AAGD,OAAO,EAAE,iBAAiB,IAAI,gBAAgB,EAAE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { createCommand as createStat } from './commands/stat.js';
|
|
|
18
18
|
import { createCommand as createTouch } from './commands/touch.js';
|
|
19
19
|
import { createCommand as createHex } from './commands/hex.js';
|
|
20
20
|
import { createCommand as createLess } from './commands/less.js';
|
|
21
|
+
import { createCommand as createPasskey } from './commands/passkey.js';
|
|
21
22
|
import { createCommand as createSed } from './commands/sed.js';
|
|
22
23
|
import { createCommand as createTee } from './commands/tee.js';
|
|
23
24
|
// Export individual command factories
|
|
@@ -61,6 +62,7 @@ export function createAllCommands(kernel, shell, terminal) {
|
|
|
61
62
|
touch: createTouch(kernel, shell, terminal),
|
|
62
63
|
hex: createHex(kernel, shell, terminal),
|
|
63
64
|
less: createLess(kernel, shell, terminal),
|
|
65
|
+
passkey: createPasskey(kernel, shell, terminal),
|
|
64
66
|
sed: createSed(kernel, shell, terminal),
|
|
65
67
|
tee: createTee(kernel, shell, terminal)
|
|
66
68
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecmaos/coreutils",
|
|
3
3
|
"description": "ecmaOS: Core utilities for the ecmaOS framework",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4",
|
|
5
5
|
"license": "MIT+Apache-2.0",
|
|
6
6
|
"homepage": "https://ecmaos.sh",
|
|
7
7
|
"repository": "https://github.com/ecmaos/ecmaos",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"command-line-args": "^6.0.0",
|
|
30
30
|
"command-line-usage": "^7.0.3",
|
|
31
31
|
"human-format": "^1.2.1",
|
|
32
|
-
"@ecmaos/types": "^0.4.
|
|
32
|
+
"@ecmaos/types": "^0.4.3"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/ansi-escape-sequences": "^4.0.4",
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import type { CommandLineOptions } from 'command-line-args'
|
|
3
|
+
import type { Kernel, Process, Shell, Terminal } from '@ecmaos/types'
|
|
4
|
+
import { TerminalCommand } from '../shared/terminal-command.js'
|
|
5
|
+
import { writelnStdout, writelnStderr } from '../shared/helpers.js'
|
|
6
|
+
|
|
7
|
+
export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal): TerminalCommand {
|
|
8
|
+
return new TerminalCommand({
|
|
9
|
+
command: 'passkey',
|
|
10
|
+
description: 'Manage passkey credentials for WebAuthn authentication',
|
|
11
|
+
kernel,
|
|
12
|
+
shell,
|
|
13
|
+
terminal,
|
|
14
|
+
options: [
|
|
15
|
+
{ name: 'help', type: Boolean, description: kernel.i18n.t('Display help') },
|
|
16
|
+
{ name: 'subcommand', type: String, defaultOption: true, description: 'Subcommand: register, list, remove, remove-all' },
|
|
17
|
+
{ name: 'name', type: String, description: 'Name/description for the passkey (used with register)' },
|
|
18
|
+
{ name: 'id', type: String, description: 'Passkey ID to remove (used with remove)' }
|
|
19
|
+
],
|
|
20
|
+
run: async (argv: CommandLineOptions, process?: Process) => {
|
|
21
|
+
if (!process) return 1
|
|
22
|
+
|
|
23
|
+
const currentUid = shell.credentials.uid
|
|
24
|
+
const user = kernel.users.get(currentUid)
|
|
25
|
+
if (!user) {
|
|
26
|
+
await writelnStderr(process, terminal, chalk.red('Error: Current user not found'))
|
|
27
|
+
return 1
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const subcommand = (argv.subcommand as string)?.toLowerCase()
|
|
31
|
+
|
|
32
|
+
if (!subcommand || subcommand === 'help' || argv.help) {
|
|
33
|
+
await writelnStdout(process, terminal, 'Usage: passkey <subcommand> [options]')
|
|
34
|
+
await writelnStdout(process, terminal, '')
|
|
35
|
+
await writelnStdout(process, terminal, 'Subcommands:')
|
|
36
|
+
await writelnStdout(process, terminal, ' register [--name <name>] Register a new passkey')
|
|
37
|
+
await writelnStdout(process, terminal, ' list List all registered passkeys')
|
|
38
|
+
await writelnStdout(process, terminal, ' remove --id <id> Remove a specific passkey')
|
|
39
|
+
await writelnStdout(process, terminal, ' remove-all Remove all passkeys')
|
|
40
|
+
return 0
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
switch (subcommand) {
|
|
45
|
+
case 'register': {
|
|
46
|
+
if (!kernel.auth.passkey.isSupported()) {
|
|
47
|
+
await writelnStderr(process, terminal, chalk.red('Error: WebAuthn is not supported in this browser'))
|
|
48
|
+
return 1
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const name = (argv.name as string) || undefined
|
|
52
|
+
const username = user.username
|
|
53
|
+
const userId = new TextEncoder().encode(username)
|
|
54
|
+
|
|
55
|
+
const challenge = crypto.getRandomValues(new Uint8Array(32))
|
|
56
|
+
const rpId = globalThis.location.hostname || 'localhost'
|
|
57
|
+
|
|
58
|
+
const createOptions: PublicKeyCredentialCreationOptions = {
|
|
59
|
+
challenge,
|
|
60
|
+
rp: {
|
|
61
|
+
name: kernel.name || 'ecmaOS',
|
|
62
|
+
id: rpId
|
|
63
|
+
},
|
|
64
|
+
user: {
|
|
65
|
+
id: userId,
|
|
66
|
+
name: username,
|
|
67
|
+
displayName: username
|
|
68
|
+
},
|
|
69
|
+
pubKeyCredParams: [
|
|
70
|
+
{ type: 'public-key', alg: -7 },
|
|
71
|
+
{ type: 'public-key', alg: -257 }
|
|
72
|
+
],
|
|
73
|
+
authenticatorSelection: {
|
|
74
|
+
userVerification: 'preferred'
|
|
75
|
+
},
|
|
76
|
+
timeout: 60000
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await writelnStdout(process, terminal, chalk.yellow('Please interact with your authenticator to register a passkey...'))
|
|
80
|
+
const credential = await kernel.auth.passkey.create(createOptions)
|
|
81
|
+
|
|
82
|
+
if (!credential || !(credential instanceof PublicKeyCredential)) {
|
|
83
|
+
await writelnStderr(process, terminal, chalk.red('Error: Failed to create passkey. Registration cancelled or failed.'))
|
|
84
|
+
return 1
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const publicKeyCredential = credential as PublicKeyCredential
|
|
88
|
+
const response = publicKeyCredential.response as AuthenticatorAttestationResponse
|
|
89
|
+
|
|
90
|
+
const credentialId = btoa(String.fromCharCode(...new Uint8Array(publicKeyCredential.rawId)))
|
|
91
|
+
|
|
92
|
+
let publicKeyArray: Uint8Array
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
if (typeof response.getPublicKey === 'function') {
|
|
96
|
+
try {
|
|
97
|
+
const publicKeyCrypto = response.getPublicKey()
|
|
98
|
+
|
|
99
|
+
if (publicKeyCrypto && publicKeyCrypto instanceof CryptoKey) {
|
|
100
|
+
const publicKeyJwk = await crypto.subtle.exportKey('jwk', publicKeyCrypto)
|
|
101
|
+
publicKeyArray = new TextEncoder().encode(JSON.stringify(publicKeyJwk))
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error('getPublicKey() did not return a valid CryptoKey')
|
|
104
|
+
}
|
|
105
|
+
} catch (exportError) {
|
|
106
|
+
await writelnStderr(process, terminal, chalk.yellow(`Warning: Could not extract public key via getPublicKey(): ${exportError instanceof Error ? exportError.message : String(exportError)}. Using attestationObject instead.`))
|
|
107
|
+
const attestationObject = response.attestationObject
|
|
108
|
+
publicKeyArray = new Uint8Array(attestationObject)
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
const attestationObject = response.attestationObject
|
|
112
|
+
publicKeyArray = new Uint8Array(attestationObject)
|
|
113
|
+
}
|
|
114
|
+
} catch (error) {
|
|
115
|
+
await writelnStderr(process, terminal, chalk.red(`Error processing credential data: ${error instanceof Error ? error.message : String(error)}`))
|
|
116
|
+
return 1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const passkey = {
|
|
120
|
+
id: crypto.randomUUID(),
|
|
121
|
+
credentialId,
|
|
122
|
+
publicKey: publicKeyArray,
|
|
123
|
+
createdAt: Date.now(),
|
|
124
|
+
name
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await kernel.users.addPasskey(currentUid, passkey)
|
|
128
|
+
await writelnStdout(process, terminal, chalk.green(`Passkey registered successfully${name ? `: ${name}` : ''}`))
|
|
129
|
+
await writelnStdout(process, terminal, `Passkey ID: ${passkey.id}`)
|
|
130
|
+
return 0
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
case 'list': {
|
|
134
|
+
const passkeys = await kernel.users.getPasskeys(currentUid)
|
|
135
|
+
|
|
136
|
+
if (passkeys.length === 0) {
|
|
137
|
+
await writelnStdout(process, terminal, 'No passkeys registered for this user.')
|
|
138
|
+
return 0
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
await writelnStdout(process, terminal, `Registered passkeys (${passkeys.length}):`)
|
|
142
|
+
await writelnStdout(process, terminal, '')
|
|
143
|
+
|
|
144
|
+
for (const pk of passkeys) {
|
|
145
|
+
const createdDate = new Date(pk.createdAt).toLocaleString()
|
|
146
|
+
const lastUsedDate = pk.lastUsed ? new Date(pk.lastUsed).toLocaleString() : 'Never'
|
|
147
|
+
await writelnStdout(process, terminal, ` ID: ${pk.id}`)
|
|
148
|
+
if (pk.name) {
|
|
149
|
+
await writelnStdout(process, terminal, ` Name: ${pk.name}`)
|
|
150
|
+
}
|
|
151
|
+
await writelnStdout(process, terminal, ` Created: ${createdDate}`)
|
|
152
|
+
await writelnStdout(process, terminal, ` Last used: ${lastUsedDate}`)
|
|
153
|
+
await writelnStdout(process, terminal, '')
|
|
154
|
+
}
|
|
155
|
+
return 0
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case 'remove': {
|
|
159
|
+
const id = argv.id as string
|
|
160
|
+
if (!id) {
|
|
161
|
+
await writelnStderr(process, terminal, chalk.red('Error: --id is required for remove command'))
|
|
162
|
+
await writelnStdout(process, terminal, 'Usage: passkey remove --id <id>')
|
|
163
|
+
return 1
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const passkeys = await kernel.users.getPasskeys(currentUid)
|
|
167
|
+
const passkey = passkeys.find(pk => pk.id === id)
|
|
168
|
+
|
|
169
|
+
if (!passkey) {
|
|
170
|
+
await writelnStderr(process, terminal, chalk.red(`Error: Passkey with ID ${id} not found`))
|
|
171
|
+
return 1
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await kernel.users.removePasskey(currentUid, id)
|
|
175
|
+
await writelnStdout(process, terminal, chalk.green(`Passkey removed successfully${passkey.name ? `: ${passkey.name}` : ''}`))
|
|
176
|
+
return 0
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
case 'remove-all': {
|
|
180
|
+
const passkeys = await kernel.users.getPasskeys(currentUid)
|
|
181
|
+
|
|
182
|
+
if (passkeys.length === 0) {
|
|
183
|
+
await writelnStdout(process, terminal, 'No passkeys to remove.')
|
|
184
|
+
return 0
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
await kernel.users.savePasskeys(currentUid, [])
|
|
188
|
+
const passkeysPath = `${user.home}/.passkeys`
|
|
189
|
+
try {
|
|
190
|
+
await kernel.filesystem.fs.unlink(passkeysPath)
|
|
191
|
+
} catch {}
|
|
192
|
+
|
|
193
|
+
await writelnStdout(process, terminal, chalk.green(`Removed ${passkeys.length} passkey(s)`))
|
|
194
|
+
return 0
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
default:
|
|
198
|
+
await writelnStderr(process, terminal, chalk.red(`Error: Unknown subcommand: ${subcommand}`))
|
|
199
|
+
await writelnStdout(process, terminal, 'Run "passkey help" for usage information')
|
|
200
|
+
return 1
|
|
201
|
+
}
|
|
202
|
+
} catch (error) {
|
|
203
|
+
await writelnStderr(process, terminal, chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`))
|
|
204
|
+
return 1
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { createCommand as createStat } from './commands/stat.js'
|
|
|
23
23
|
import { createCommand as createTouch } from './commands/touch.js'
|
|
24
24
|
import { createCommand as createHex } from './commands/hex.js'
|
|
25
25
|
import { createCommand as createLess } from './commands/less.js'
|
|
26
|
+
import { createCommand as createPasskey } from './commands/passkey.js'
|
|
26
27
|
import { createCommand as createSed } from './commands/sed.js'
|
|
27
28
|
import { createCommand as createTee } from './commands/tee.js'
|
|
28
29
|
|
|
@@ -68,6 +69,7 @@ export function createAllCommands(kernel: Kernel, shell: Shell, terminal: Termin
|
|
|
68
69
|
touch: createTouch(kernel, shell, terminal),
|
|
69
70
|
hex: createHex(kernel, shell, terminal),
|
|
70
71
|
less: createLess(kernel, shell, terminal),
|
|
72
|
+
passkey: createPasskey(kernel, shell, terminal),
|
|
71
73
|
sed: createSed(kernel, shell, terminal),
|
|
72
74
|
tee: createTee(kernel, shell, terminal)
|
|
73
75
|
}
|