@pellux/goodvibes-agent 0.1.80 → 0.1.82
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/CHANGELOG.md +11 -0
- package/package.json +3 -1
- package/src/agent/skill-registry.ts +255 -5
- package/src/cli/help.ts +4 -4
- package/src/cli/management.ts +54 -136
- package/src/cli/status.ts +10 -10
- package/src/input/agent-workspace-categories.ts +2 -0
- package/src/input/agent-workspace-setup.ts +6 -4
- package/src/input/agent-workspace-snapshot.ts +26 -3
- package/src/input/agent-workspace-types.ts +4 -0
- package/src/input/commands/agent-skills-runtime.ts +151 -3
- package/src/input/commands/health-runtime.ts +12 -14
- package/src/input/commands/platform-access-runtime.ts +8 -4
- package/src/input/commands.ts +0 -2
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/panels/builtin/operations.ts +0 -10
- package/src/panels/provider-health-domains.ts +9 -8
- package/src/renderer/agent-workspace.ts +9 -6
- package/src/runtime/onboarding/apply.ts +6 -154
- package/src/runtime/onboarding/derivation.ts +4 -4
- package/src/runtime/onboarding/types.ts +1 -11
- package/src/runtime/onboarding/verify.ts +3 -25
- package/src/version.ts +1 -1
- package/src/input/commands/local-auth-runtime.ts +0 -128
- package/src/panels/local-auth-panel.ts +0 -130
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
2
|
-
import { openCommandPanel, requireLocalUserAuthManager } from './runtime-services.ts';
|
|
3
|
-
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
4
|
-
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
5
|
-
|
|
6
|
-
function formatRoles(roles: readonly string[]): string {
|
|
7
|
-
return roles.length > 0 ? roles.join(', ') : '(none)';
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function handleLocalAuthCommand(args: string[], ctx: CommandContext): void {
|
|
11
|
-
const parsed = stripYesFlag(args);
|
|
12
|
-
const commandArgs = [...parsed.rest];
|
|
13
|
-
const sub = (commandArgs[0] ?? 'review').toLowerCase();
|
|
14
|
-
const auth = requireLocalUserAuthManager(ctx);
|
|
15
|
-
if (sub === 'panel' || sub === 'open') {
|
|
16
|
-
openCommandPanel(ctx, 'local-auth');
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (sub === 'add-user') {
|
|
21
|
-
const username = commandArgs[1];
|
|
22
|
-
const password = commandArgs[2];
|
|
23
|
-
const roles = commandArgs[3]?.split(',').map((value) => value.trim()).filter(Boolean) ?? ['admin'];
|
|
24
|
-
if (!username || !password) {
|
|
25
|
-
ctx.print('Usage: /auth local add-user <username> <password> [roles] --yes');
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (!parsed.yes) {
|
|
29
|
-
requireYesFlag(ctx, `add local auth user ${username}`, '/auth local add-user <username> <password> [roles] --yes');
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
const added = auth.addUser(username, password, roles);
|
|
34
|
-
ctx.print(`Added local auth user ${added.username} (${formatRoles(added.roles)}).`);
|
|
35
|
-
} catch (error) {
|
|
36
|
-
ctx.print(summarizeError(error));
|
|
37
|
-
}
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (sub === 'delete-user') {
|
|
42
|
-
const username = commandArgs[1];
|
|
43
|
-
if (!username) {
|
|
44
|
-
ctx.print('Usage: /auth local delete-user <username> --yes');
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (!parsed.yes) {
|
|
48
|
-
requireYesFlag(ctx, `delete local auth user ${username}`, '/auth local delete-user <username> --yes');
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
const deleted = auth.deleteUser(username);
|
|
53
|
-
ctx.print(deleted ? `Deleted local auth user ${username}.` : `Unknown local auth user: ${username}`);
|
|
54
|
-
} catch (error) {
|
|
55
|
-
ctx.print(summarizeError(error));
|
|
56
|
-
}
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (sub === 'rotate-password') {
|
|
61
|
-
const username = commandArgs[1];
|
|
62
|
-
const password = commandArgs[2];
|
|
63
|
-
if (!username || !password) {
|
|
64
|
-
ctx.print('Usage: /auth local rotate-password <username> <password> --yes');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (!parsed.yes) {
|
|
68
|
-
requireYesFlag(ctx, `rotate password for local auth user ${username}`, '/auth local rotate-password <username> <password> --yes');
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
auth.rotatePassword(username, password);
|
|
73
|
-
ctx.print(`Rotated password for ${username}. Existing sessions were revoked.`);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
ctx.print(summarizeError(error));
|
|
76
|
-
}
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (sub === 'revoke-session') {
|
|
81
|
-
const token = commandArgs[1];
|
|
82
|
-
if (!token) {
|
|
83
|
-
ctx.print('Usage: /auth local revoke-session <token-or-fingerprint> --yes');
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (!parsed.yes) {
|
|
87
|
-
requireYesFlag(ctx, 'revoke local auth session', '/auth local revoke-session <token-or-fingerprint> --yes');
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
ctx.print(auth.revokeSession(token) ? `Revoked session ${token.slice(0, 12)}…` : `Unknown session token or fingerprint: ${token}`);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (sub === 'clear-bootstrap-file') {
|
|
95
|
-
if (!parsed.yes) {
|
|
96
|
-
requireYesFlag(ctx, 'clear the local auth bootstrap credential file', '/auth local clear-bootstrap-file --yes');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
ctx.print(auth.clearBootstrapCredentialFile()
|
|
100
|
-
? 'Removed bootstrap credential file.'
|
|
101
|
-
: 'No bootstrap credential file was present.');
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const snapshot = auth.inspect();
|
|
106
|
-
ctx.print([
|
|
107
|
-
'Local Auth Review',
|
|
108
|
-
` user store: ${snapshot.userStorePath}`,
|
|
109
|
-
` bootstrap file: ${snapshot.bootstrapCredentialPath}`,
|
|
110
|
-
` bootstrap credentials: ${snapshot.bootstrapCredentialPresent ? 'present' : 'cleared'}`,
|
|
111
|
-
` users: ${snapshot.userCount}`,
|
|
112
|
-
` sessions: ${snapshot.sessionCount}`,
|
|
113
|
-
...snapshot.users.map((user) => ` user: ${user.username} roles=${formatRoles(user.roles)}`),
|
|
114
|
-
...snapshot.sessions.map((session) => ` session: ${session.username} expires=${new Date(session.expiresAt).toISOString()} fingerprint=${session.tokenFingerprint}`),
|
|
115
|
-
].join('\n'));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function registerLocalAuthRuntimeCommands(registry: CommandRegistry): void {
|
|
119
|
-
registry.register({
|
|
120
|
-
name: 'local-auth',
|
|
121
|
-
aliases: ['auth-local'],
|
|
122
|
-
description: 'Inspect and manage local runtime auth users, sessions, and bootstrap credentials',
|
|
123
|
-
usage: '[review|panel|add-user <username> <password> [roles] --yes|delete-user <username> --yes|rotate-password <username> <password> --yes|revoke-session <token-or-fingerprint> --yes|clear-bootstrap-file --yes]',
|
|
124
|
-
handler(args, ctx) {
|
|
125
|
-
handleLocalAuthCommand(args, ctx);
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { Line } from '../types/grid.ts';
|
|
2
|
-
import { createEmptyLine } from '../types/grid.ts';
|
|
3
|
-
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
4
|
-
import {
|
|
5
|
-
buildDetailBlock,
|
|
6
|
-
buildGuidanceLine,
|
|
7
|
-
buildPanelListRow,
|
|
8
|
-
buildPanelLine,
|
|
9
|
-
buildSummaryBlock,
|
|
10
|
-
buildPanelWorkspace,
|
|
11
|
-
DEFAULT_PANEL_PALETTE,
|
|
12
|
-
type PanelPalette,
|
|
13
|
-
} from './polish.ts';
|
|
14
|
-
import type { LocalAuthSnapshot } from '@pellux/goodvibes-sdk/platform/security';
|
|
15
|
-
import type { LocalAuthInspectionQuery } from '../runtime/ui-service-queries.ts';
|
|
16
|
-
|
|
17
|
-
const C = {
|
|
18
|
-
...DEFAULT_PANEL_PALETTE,
|
|
19
|
-
info: '#38bdf8',
|
|
20
|
-
warn: '#eab308',
|
|
21
|
-
error: '#ef4444',
|
|
22
|
-
selectBg: '#1e293b',
|
|
23
|
-
} as const;
|
|
24
|
-
|
|
25
|
-
function formatRoles(roles: readonly string[]): string {
|
|
26
|
-
return roles.length > 0 ? roles.join(', ') : '(none)';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
type LocalAuthUser = LocalAuthSnapshot['users'][number];
|
|
30
|
-
|
|
31
|
-
export class LocalAuthPanel extends ScrollableListPanel<LocalAuthUser> {
|
|
32
|
-
private readonly authManager: LocalAuthInspectionQuery;
|
|
33
|
-
|
|
34
|
-
public constructor(authManager: LocalAuthInspectionQuery) {
|
|
35
|
-
super('local-auth', 'Local Auth', 'U', 'monitoring');
|
|
36
|
-
this.showSelectionGutter = true; // I5: non-color selection affordance
|
|
37
|
-
this.authManager = authManager;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
protected override getPalette(): PanelPalette {
|
|
41
|
-
return C;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
protected getItems(): readonly LocalAuthUser[] {
|
|
45
|
-
return this.authManager.inspect().users;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
protected renderItem(user: LocalAuthUser, _index: number, selected: boolean, width: number): Line {
|
|
49
|
-
return buildPanelListRow(width, [
|
|
50
|
-
{ text: user.username.padEnd(20), fg: C.value },
|
|
51
|
-
{ text: ` roles=${formatRoles(user.roles)}`.slice(0, Math.max(0, width - 24)), fg: C.info },
|
|
52
|
-
], C, { selected });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
protected override getEmptyStateMessage(): string {
|
|
56
|
-
return ' No local auth users configured.';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public render(width: number, height: number): Line[] {
|
|
60
|
-
const intro = 'Review local runtime auth users, bootstrap state, and active sessions.';
|
|
61
|
-
const snapshot = this.authManager.inspect();
|
|
62
|
-
const users = this.getItems();
|
|
63
|
-
|
|
64
|
-
const issueMessages: string[] = [];
|
|
65
|
-
if (snapshot.bootstrapCredentialPresent) issueMessages.push('Bootstrap credential file still exists and should be cleared after password rotation.');
|
|
66
|
-
if (snapshot.userCount <= 1) issueMessages.push('Only one local auth user is configured.');
|
|
67
|
-
if (snapshot.sessionCount === 0) issueMessages.push('No active local auth sessions are currently tracked.');
|
|
68
|
-
|
|
69
|
-
const headerLines: Line[] = [
|
|
70
|
-
...buildSummaryBlock(width, 'Local auth posture', [
|
|
71
|
-
buildPanelLine(width, [
|
|
72
|
-
[' users ', C.label],
|
|
73
|
-
[String(snapshot.userCount), C.value],
|
|
74
|
-
[' sessions ', C.label],
|
|
75
|
-
[String(snapshot.sessionCount), snapshot.sessionCount > 0 ? C.info : C.dim],
|
|
76
|
-
[' bootstrap ', C.label],
|
|
77
|
-
[snapshot.bootstrapCredentialPresent ? 'present' : 'cleared', snapshot.bootstrapCredentialPresent ? C.warn : C.good],
|
|
78
|
-
]),
|
|
79
|
-
buildPanelLine(width, [[' user store ', C.label], [snapshot.userStorePath.slice(0, Math.max(0, width - 13)), C.dim]]),
|
|
80
|
-
buildPanelLine(width, [[' bootstrap file ', C.label], [snapshot.bootstrapCredentialPath.slice(0, Math.max(0, width - 18)), C.dim]]),
|
|
81
|
-
...(issueMessages.length > 0
|
|
82
|
-
? issueMessages.map((issue) => buildPanelLine(width, [[` issue: ${issue}`.slice(0, Math.max(0, width)), C.warn]]))
|
|
83
|
-
: [buildPanelLine(width, [[' local auth posture looks healthy.', C.good]])]),
|
|
84
|
-
buildGuidanceLine(width, '/auth local rotate-password <user> <password> --yes', 'rotate bootstrap/default credentials and revoke older sessions as needed', C),
|
|
85
|
-
], C),
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
if (users.length === 0) {
|
|
89
|
-
const workspace = buildPanelWorkspace(width, height, {
|
|
90
|
-
title: 'Local Auth Control Room',
|
|
91
|
-
intro,
|
|
92
|
-
sections: [{ lines: headerLines }],
|
|
93
|
-
palette: C,
|
|
94
|
-
});
|
|
95
|
-
while (workspace.length < height) workspace.push(createEmptyLine(width));
|
|
96
|
-
return workspace;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.clampSelection();
|
|
100
|
-
const selected = users[this.selectedIndex];
|
|
101
|
-
|
|
102
|
-
const footerLines: Line[] = [];
|
|
103
|
-
if (selected) {
|
|
104
|
-
footerLines.push(
|
|
105
|
-
...buildDetailBlock(width, 'Selected user', [
|
|
106
|
-
buildPanelLine(width, [[' username ', C.label], [selected.username, C.value], [' roles ', C.label], [formatRoles(selected.roles).slice(0, Math.max(0, width - 23)), C.info]]),
|
|
107
|
-
buildPanelLine(width, [[` next: /auth local rotate-password ${selected.username} <password> --yes`.slice(0, Math.max(0, width)), C.dim]]),
|
|
108
|
-
buildPanelLine(width, [[` next: /auth local delete-user ${selected.username} --yes`.slice(0, Math.max(0, width)), C.dim]]),
|
|
109
|
-
], C),
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (snapshot.sessions.length > 0) {
|
|
114
|
-
footerLines.push(
|
|
115
|
-
...snapshot.sessions.slice(0, 8).map((session) => buildPanelLine(width, [
|
|
116
|
-
[' ', C.label],
|
|
117
|
-
[session.username.padEnd(18), C.value],
|
|
118
|
-
[` expires ${new Date(session.expiresAt).toLocaleString()}`.slice(0, Math.max(0, width - 20)), C.dim],
|
|
119
|
-
])),
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
footerLines.push(buildPanelLine(width, [[' /auth local review mutations require --yes: add-user rotate-password revoke-session ', C.dim]]));
|
|
123
|
-
|
|
124
|
-
return this.renderList(width, height, {
|
|
125
|
-
title: 'Local Auth Control Room',
|
|
126
|
-
header: headerLines,
|
|
127
|
-
footer: footerLines,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|