@loom-framework/core 0.1.0-alpha.149 → 0.1.0-alpha.150
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/builtin-skills/app-skill/SKILL.md +12 -7
- package/builtin-skills/app-skill/references/auth.md +164 -0
- package/builtin-skills/app-skill/references/models.md +2 -0
- package/builtin-skills/loom/SKILL.md +35 -3
- package/dist/backend/ai/engine.d.ts.map +1 -1
- package/dist/backend/ai/engine.js +1 -0
- package/dist/backend/ai/engine.js.map +1 -1
- package/dist/backend/auth/jwt.d.ts +16 -0
- package/dist/backend/auth/jwt.d.ts.map +1 -0
- package/dist/backend/auth/jwt.js +57 -0
- package/dist/backend/auth/jwt.js.map +1 -0
- package/dist/backend/auth/password.d.ts +10 -0
- package/dist/backend/auth/password.d.ts.map +1 -0
- package/dist/backend/auth/password.js +19 -0
- package/dist/backend/auth/password.js.map +1 -0
- package/dist/backend/auth/rbac.d.ts +34 -0
- package/dist/backend/auth/rbac.d.ts.map +1 -0
- package/dist/backend/auth/rbac.js +124 -0
- package/dist/backend/auth/rbac.js.map +1 -0
- package/dist/backend/auth/service-token.d.ts +11 -0
- package/dist/backend/auth/service-token.d.ts.map +1 -0
- package/dist/backend/auth/service-token.js +13 -0
- package/dist/backend/auth/service-token.js.map +1 -0
- package/dist/backend/auth/token-store.d.ts +27 -0
- package/dist/backend/auth/token-store.d.ts.map +1 -0
- package/dist/backend/auth/token-store.js +84 -0
- package/dist/backend/auth/token-store.js.map +1 -0
- package/dist/backend/auth/user-store.d.ts +41 -0
- package/dist/backend/auth/user-store.d.ts.map +1 -0
- package/dist/backend/auth/user-store.js +112 -0
- package/dist/backend/auth/user-store.js.map +1 -0
- package/dist/backend/index.d.ts +8 -0
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +48 -2
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/routes/auth-routes.d.ts +26 -0
- package/dist/backend/routes/auth-routes.d.ts.map +1 -0
- package/dist/backend/routes/auth-routes.js +301 -0
- package/dist/backend/routes/auth-routes.js.map +1 -0
- package/dist/backend/routes/chat.d.ts.map +1 -1
- package/dist/backend/routes/chat.js +1 -0
- package/dist/backend/routes/chat.js.map +1 -1
- package/dist/backend/routes/data.d.ts.map +1 -1
- package/dist/backend/routes/data.js +8 -0
- package/dist/backend/routes/data.js.map +1 -1
- package/dist/backend/routes/index.d.ts +2 -0
- package/dist/backend/routes/index.d.ts.map +1 -1
- package/dist/backend/routes/index.js +1 -0
- package/dist/backend/routes/index.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +11 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +203 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/data.d.ts +5 -1
- package/dist/cli/commands/data.d.ts.map +1 -1
- package/dist/cli/commands/data.js +182 -40
- package/dist/cli/commands/data.js.map +1 -1
- package/dist/cli/commands/generate-system-settings.d.ts +2 -2
- package/dist/cli/commands/generate-system-settings.d.ts.map +1 -1
- package/dist/cli/commands/generate-system-settings.js +14 -6
- package/dist/cli/commands/generate-system-settings.js.map +1 -1
- package/dist/cli/commands/init.js +26 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/role.d.ts +9 -0
- package/dist/cli/commands/role.d.ts.map +1 -0
- package/dist/cli/commands/role.js +81 -0
- package/dist/cli/commands/role.js.map +1 -0
- package/dist/cli/commands/user-cmd.d.ts +9 -0
- package/dist/cli/commands/user-cmd.d.ts.map +1 -0
- package/dist/cli/commands/user-cmd.js +204 -0
- package/dist/cli/commands/user-cmd.js.map +1 -0
- package/dist/cli/generators/capability-generator.d.ts.map +1 -1
- package/dist/cli/generators/capability-generator.js +67 -6
- package/dist/cli/generators/capability-generator.js.map +1 -1
- package/dist/cli/helpers/app-tsx-wiring.d.ts +7 -0
- package/dist/cli/helpers/app-tsx-wiring.d.ts.map +1 -1
- package/dist/cli/helpers/app-tsx-wiring.js +44 -0
- package/dist/cli/helpers/app-tsx-wiring.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/credentials.d.ts +27 -0
- package/dist/cli/lib/credentials.d.ts.map +1 -0
- package/dist/cli/lib/credentials.js +112 -0
- package/dist/cli/lib/credentials.js.map +1 -0
- package/dist/cli/templates/auth-wiring.d.ts +17 -0
- package/dist/cli/templates/auth-wiring.d.ts.map +1 -0
- package/dist/cli/templates/auth-wiring.js +31 -0
- package/dist/cli/templates/auth-wiring.js.map +1 -0
- package/dist/cli/templates/index.d.ts +2 -0
- package/dist/cli/templates/index.d.ts.map +1 -1
- package/dist/cli/templates/index.js +2 -0
- package/dist/cli/templates/index.js.map +1 -1
- package/dist/cli/templates/login-page.d.ts +5 -0
- package/dist/cli/templates/login-page.d.ts.map +1 -0
- package/dist/cli/templates/login-page.js +13 -0
- package/dist/cli/templates/login-page.js.map +1 -0
- package/dist/cli/templates/loom-config.d.ts.map +1 -1
- package/dist/cli/templates/loom-config.js +13 -0
- package/dist/cli/templates/loom-config.js.map +1 -1
- package/dist/cli/templates/model-management-page.d.ts.map +1 -1
- package/dist/cli/templates/model-management-page.js +6 -5
- package/dist/cli/templates/model-management-page.js.map +1 -1
- package/dist/cli/templates/user-management-page.d.ts +9 -0
- package/dist/cli/templates/user-management-page.d.ts.map +1 -0
- package/dist/cli/templates/user-management-page.js +236 -0
- package/dist/cli/templates/user-management-page.js.map +1 -0
- package/dist/config.d.ts +249 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +28 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/ai.d.ts +2 -0
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/auth.d.ts +64 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +5 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Token management
|
|
3
|
+
*
|
|
4
|
+
* Issues service tokens for Process automation and CLI auth.
|
|
5
|
+
* Service tokens are long-lived (30d), not affected by password changes.
|
|
6
|
+
* Returned via API response on user creation — caller is responsible for storage.
|
|
7
|
+
*/
|
|
8
|
+
import { signServiceToken } from './jwt.js';
|
|
9
|
+
/** Issue a service token for the given user (does not persist to file) */
|
|
10
|
+
export function issueServiceToken(userId, username, role, config) {
|
|
11
|
+
return signServiceToken({ userId, username, role }, config);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=service-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-token.js","sourceRoot":"","sources":["../../../src/backend/auth/service-token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,QAAgB,EAChB,IAAY,EACZ,MAAkB;IAElB,OAAO,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refresh token server-side storage
|
|
3
|
+
*
|
|
4
|
+
* Used for token revocation on logout.
|
|
5
|
+
* Logout deletes the refresh token so it cannot be used again.
|
|
6
|
+
*/
|
|
7
|
+
interface StoredToken {
|
|
8
|
+
token: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
expiresAt: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class TokenStore {
|
|
13
|
+
private tokens;
|
|
14
|
+
private dataDir;
|
|
15
|
+
private filePath;
|
|
16
|
+
private dirty;
|
|
17
|
+
constructor(projectRoot: string);
|
|
18
|
+
initialize(): Promise<void>;
|
|
19
|
+
private persist;
|
|
20
|
+
store(token: string, userId: string, expiresAt: string): Promise<void>;
|
|
21
|
+
find(token: string): Promise<StoredToken | null>;
|
|
22
|
+
delete(token: string): Promise<boolean>;
|
|
23
|
+
deleteByUserId(userId: string): Promise<number>;
|
|
24
|
+
cleanExpired(): Promise<number>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/backend/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,WAAW,EAAE,MAAM;IAKzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAanB,OAAO;IAOf,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAIhD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASvC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe/C,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;CAetC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refresh token server-side storage
|
|
3
|
+
*
|
|
4
|
+
* Used for token revocation on logout.
|
|
5
|
+
* Logout deletes the refresh token so it cannot be used again.
|
|
6
|
+
*/
|
|
7
|
+
import { promises as fs } from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
export class TokenStore {
|
|
10
|
+
tokens = new Map();
|
|
11
|
+
dataDir;
|
|
12
|
+
filePath;
|
|
13
|
+
dirty = false;
|
|
14
|
+
constructor(projectRoot) {
|
|
15
|
+
this.dataDir = path.join(projectRoot, '.loom', 'auth');
|
|
16
|
+
this.filePath = path.join(this.dataDir, 'tokens.json');
|
|
17
|
+
}
|
|
18
|
+
async initialize() {
|
|
19
|
+
await fs.mkdir(this.dataDir, { recursive: true });
|
|
20
|
+
try {
|
|
21
|
+
const data = await fs.readFile(this.filePath, 'utf-8');
|
|
22
|
+
const tokens = JSON.parse(data);
|
|
23
|
+
for (const token of tokens) {
|
|
24
|
+
this.tokens.set(token.token, token);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// File doesn't exist yet, start empty
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async persist() {
|
|
32
|
+
if (!this.dirty)
|
|
33
|
+
return;
|
|
34
|
+
const data = Array.from(this.tokens.values());
|
|
35
|
+
await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
36
|
+
this.dirty = false;
|
|
37
|
+
}
|
|
38
|
+
async store(token, userId, expiresAt) {
|
|
39
|
+
this.tokens.set(token, { token, userId, expiresAt });
|
|
40
|
+
this.dirty = true;
|
|
41
|
+
await this.persist();
|
|
42
|
+
}
|
|
43
|
+
async find(token) {
|
|
44
|
+
return this.tokens.get(token) ?? null;
|
|
45
|
+
}
|
|
46
|
+
async delete(token) {
|
|
47
|
+
const deleted = this.tokens.delete(token);
|
|
48
|
+
if (deleted) {
|
|
49
|
+
this.dirty = true;
|
|
50
|
+
await this.persist();
|
|
51
|
+
}
|
|
52
|
+
return deleted;
|
|
53
|
+
}
|
|
54
|
+
async deleteByUserId(userId) {
|
|
55
|
+
let count = 0;
|
|
56
|
+
for (const [key, stored] of this.tokens) {
|
|
57
|
+
if (stored.userId === userId) {
|
|
58
|
+
this.tokens.delete(key);
|
|
59
|
+
count++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (count > 0) {
|
|
63
|
+
this.dirty = true;
|
|
64
|
+
await this.persist();
|
|
65
|
+
}
|
|
66
|
+
return count;
|
|
67
|
+
}
|
|
68
|
+
async cleanExpired() {
|
|
69
|
+
const now = Date.now();
|
|
70
|
+
let count = 0;
|
|
71
|
+
for (const [key, stored] of this.tokens) {
|
|
72
|
+
if (new Date(stored.expiresAt).getTime() < now) {
|
|
73
|
+
this.tokens.delete(key);
|
|
74
|
+
count++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (count > 0) {
|
|
78
|
+
this.dirty = true;
|
|
79
|
+
await this.persist();
|
|
80
|
+
}
|
|
81
|
+
return count;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=token-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../../src/backend/auth/token-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Independent user storage module
|
|
3
|
+
*
|
|
4
|
+
* NOT using DataAdapter — users get their own storage and API routes.
|
|
5
|
+
* Write hashes password, read hides password.
|
|
6
|
+
*/
|
|
7
|
+
import type { AuthUser } from '../../types/auth.js';
|
|
8
|
+
interface StoredUser {
|
|
9
|
+
userId: string;
|
|
10
|
+
username: string;
|
|
11
|
+
password: string;
|
|
12
|
+
role: string;
|
|
13
|
+
createdAt: string;
|
|
14
|
+
updatedAt: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class UserStore {
|
|
17
|
+
private users;
|
|
18
|
+
private dataDir;
|
|
19
|
+
private filePath;
|
|
20
|
+
private dirty;
|
|
21
|
+
constructor(projectRoot: string);
|
|
22
|
+
initialize(): Promise<void>;
|
|
23
|
+
private persist;
|
|
24
|
+
createUser(input: {
|
|
25
|
+
username: string;
|
|
26
|
+
password: string;
|
|
27
|
+
role: string;
|
|
28
|
+
}): Promise<AuthUser>;
|
|
29
|
+
readUser(id: string): Promise<AuthUser | null>;
|
|
30
|
+
findByUsername(username: string): Promise<StoredUser | null>;
|
|
31
|
+
verifyCredentials(username: string, password: string): Promise<AuthUser | null>;
|
|
32
|
+
updateUser(id: string, updates: Partial<{
|
|
33
|
+
username: string;
|
|
34
|
+
password: string;
|
|
35
|
+
role: string;
|
|
36
|
+
}>): Promise<AuthUser | null>;
|
|
37
|
+
deleteUser(id: string): Promise<boolean>;
|
|
38
|
+
listUsers(): Promise<AuthUser[]>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=user-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-store.d.ts","sourceRoot":"","sources":["../../../src/backend/auth/user-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,qBAAqB,CAAC;AAIhE,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,WAAW,EAAE,MAAM;IAKzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAanB,OAAO;IAOf,UAAU,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IA0B1F,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAK9C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAO5D,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAO/E,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAgBxH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;CAGvC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Independent user storage module
|
|
3
|
+
*
|
|
4
|
+
* NOT using DataAdapter — users get their own storage and API routes.
|
|
5
|
+
* Write hashes password, read hides password.
|
|
6
|
+
*/
|
|
7
|
+
import { promises as fs } from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { generateId } from '../../utils/id.js';
|
|
10
|
+
import { hashPassword, verifyPassword } from './password.js';
|
|
11
|
+
function hidePassword(user) {
|
|
12
|
+
const { password: _, ...safe } = user;
|
|
13
|
+
return safe;
|
|
14
|
+
}
|
|
15
|
+
export class UserStore {
|
|
16
|
+
users = new Map();
|
|
17
|
+
dataDir;
|
|
18
|
+
filePath;
|
|
19
|
+
dirty = false;
|
|
20
|
+
constructor(projectRoot) {
|
|
21
|
+
this.dataDir = path.join(projectRoot, '.loom', 'auth');
|
|
22
|
+
this.filePath = path.join(this.dataDir, 'users.json');
|
|
23
|
+
}
|
|
24
|
+
async initialize() {
|
|
25
|
+
await fs.mkdir(this.dataDir, { recursive: true });
|
|
26
|
+
try {
|
|
27
|
+
const data = await fs.readFile(this.filePath, 'utf-8');
|
|
28
|
+
const users = JSON.parse(data);
|
|
29
|
+
for (const user of users) {
|
|
30
|
+
this.users.set(user.userId, user);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// File doesn't exist yet, start empty
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async persist() {
|
|
38
|
+
if (!this.dirty)
|
|
39
|
+
return;
|
|
40
|
+
const data = Array.from(this.users.values());
|
|
41
|
+
await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
42
|
+
this.dirty = false;
|
|
43
|
+
}
|
|
44
|
+
async createUser(input) {
|
|
45
|
+
// Check unique username
|
|
46
|
+
for (const user of this.users.values()) {
|
|
47
|
+
if (user.username === input.username) {
|
|
48
|
+
throw new Error(`Username '${input.username}' already exists`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const now = new Date().toISOString();
|
|
52
|
+
const hashedPassword = await hashPassword(input.password);
|
|
53
|
+
const user = {
|
|
54
|
+
userId: generateId('usr'),
|
|
55
|
+
username: input.username,
|
|
56
|
+
password: hashedPassword,
|
|
57
|
+
role: input.role,
|
|
58
|
+
createdAt: now,
|
|
59
|
+
updatedAt: now,
|
|
60
|
+
};
|
|
61
|
+
this.users.set(user.userId, user);
|
|
62
|
+
this.dirty = true;
|
|
63
|
+
await this.persist();
|
|
64
|
+
return hidePassword(user);
|
|
65
|
+
}
|
|
66
|
+
async readUser(id) {
|
|
67
|
+
const user = this.users.get(id);
|
|
68
|
+
return user ? hidePassword(user) : null;
|
|
69
|
+
}
|
|
70
|
+
async findByUsername(username) {
|
|
71
|
+
for (const user of this.users.values()) {
|
|
72
|
+
if (user.username === username)
|
|
73
|
+
return user;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
async verifyCredentials(username, password) {
|
|
78
|
+
const user = await this.findByUsername(username);
|
|
79
|
+
if (!user)
|
|
80
|
+
return null;
|
|
81
|
+
const valid = await verifyPassword(password, user.password);
|
|
82
|
+
return valid ? hidePassword(user) : null;
|
|
83
|
+
}
|
|
84
|
+
async updateUser(id, updates) {
|
|
85
|
+
const user = this.users.get(id);
|
|
86
|
+
if (!user)
|
|
87
|
+
return null;
|
|
88
|
+
if (updates.username !== undefined)
|
|
89
|
+
user.username = updates.username;
|
|
90
|
+
if (updates.role !== undefined)
|
|
91
|
+
user.role = updates.role;
|
|
92
|
+
if (updates.password !== undefined) {
|
|
93
|
+
user.password = await hashPassword(updates.password);
|
|
94
|
+
}
|
|
95
|
+
user.updatedAt = new Date().toISOString();
|
|
96
|
+
this.dirty = true;
|
|
97
|
+
await this.persist();
|
|
98
|
+
return hidePassword(user);
|
|
99
|
+
}
|
|
100
|
+
async deleteUser(id) {
|
|
101
|
+
const deleted = this.users.delete(id);
|
|
102
|
+
if (deleted) {
|
|
103
|
+
this.dirty = true;
|
|
104
|
+
await this.persist();
|
|
105
|
+
}
|
|
106
|
+
return deleted;
|
|
107
|
+
}
|
|
108
|
+
async listUsers() {
|
|
109
|
+
return Array.from(this.users.values()).map(hidePassword);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=user-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-store.js","sourceRoot":"","sources":["../../../src/backend/auth/user-store.ts"],"names":[],"mappings":"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"}
|
package/dist/backend/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ import Fastify from 'fastify';
|
|
|
11
11
|
import type { LoomConfig, ServerConfig } from '../types/config.js';
|
|
12
12
|
import type { AIEngine } from '../types/ai.js';
|
|
13
13
|
import type { DataAdapter } from '../types/adapter.js';
|
|
14
|
+
import { UserStore } from './auth/user-store.js';
|
|
15
|
+
import { TokenStore } from './auth/token-store.js';
|
|
14
16
|
export interface LoomServerOptions {
|
|
15
17
|
/** Project root directory containing loom.config.ts */
|
|
16
18
|
projectRoot: string;
|
|
@@ -30,6 +32,8 @@ export declare class LoomServer {
|
|
|
30
32
|
private sessionManager;
|
|
31
33
|
private interactionLogger;
|
|
32
34
|
private fastify;
|
|
35
|
+
private userStore?;
|
|
36
|
+
private tokenStore?;
|
|
33
37
|
private projectRoot;
|
|
34
38
|
private options;
|
|
35
39
|
constructor(options: LoomServerOptions);
|
|
@@ -51,6 +55,10 @@ export declare class LoomServer {
|
|
|
51
55
|
getConfig(): LoomConfig;
|
|
52
56
|
/** Expose adapter for testing */
|
|
53
57
|
getAdapter(): DataAdapter;
|
|
58
|
+
/** Expose user store for testing */
|
|
59
|
+
getUserStore(): UserStore | undefined;
|
|
60
|
+
/** Expose token store for testing */
|
|
61
|
+
getTokenStore(): TokenStore | undefined;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
64
|
* Create and start a LoomServer from a project root
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiIjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,0CAA0C;IAC1C,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC;IAIxC,gCAAgC;IAChC,SAAS,IAAI,UAAU;IAIvB,iCAAiC;IACjC,UAAU,IAAI,WAAW;IAIzB,oCAAoC;IACpC,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC,qCAAqC;IACrC,aAAa,IAAI,UAAU,GAAG,SAAS;CAGxC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK1E"}
|
package/dist/backend/index.js
CHANGED
|
@@ -16,7 +16,11 @@ import { createAdapter } from '../adapters/factory.js';
|
|
|
16
16
|
import { ClaudeCodeEngine } from './ai/engine.js';
|
|
17
17
|
import { SessionManager } from './ai/session-manager.js';
|
|
18
18
|
import { AIInteractionLogger } from './observe/index.js';
|
|
19
|
-
import { registerDataRoutes, registerHealthRoute, registerUploadRoutes, registerChatRoutes, registerSkillRoutes, registerAIConfigRoutes } from './routes/index.js';
|
|
19
|
+
import { registerDataRoutes, registerHealthRoute, registerUploadRoutes, registerChatRoutes, registerSkillRoutes, registerAIConfigRoutes, registerAuthRoutes } from './routes/index.js';
|
|
20
|
+
import { createAuthMiddleware } from './auth/rbac.js';
|
|
21
|
+
import { issueServiceToken } from './auth/service-token.js';
|
|
22
|
+
import { UserStore } from './auth/user-store.js';
|
|
23
|
+
import { TokenStore } from './auth/token-store.js';
|
|
20
24
|
export class LoomServer {
|
|
21
25
|
config;
|
|
22
26
|
engine;
|
|
@@ -24,6 +28,8 @@ export class LoomServer {
|
|
|
24
28
|
sessionManager;
|
|
25
29
|
interactionLogger;
|
|
26
30
|
fastify;
|
|
31
|
+
userStore;
|
|
32
|
+
tokenStore;
|
|
27
33
|
projectRoot;
|
|
28
34
|
options;
|
|
29
35
|
constructor(options) {
|
|
@@ -76,7 +82,39 @@ export class LoomServer {
|
|
|
76
82
|
await this.interactionLogger.initialize();
|
|
77
83
|
// Register plugins
|
|
78
84
|
if (serverConfig.cors !== false) {
|
|
79
|
-
|
|
85
|
+
const corsOptions = { origin: true };
|
|
86
|
+
if (this.config.auth) {
|
|
87
|
+
corsOptions.allowedHeaders = ['Authorization', 'Content-Type'];
|
|
88
|
+
}
|
|
89
|
+
await this.fastify.register(cors, corsOptions);
|
|
90
|
+
}
|
|
91
|
+
// Auth setup (before business routes)
|
|
92
|
+
if (this.config.auth) {
|
|
93
|
+
this.userStore = new UserStore(this.projectRoot);
|
|
94
|
+
await this.userStore.initialize();
|
|
95
|
+
this.tokenStore = new TokenStore(this.projectRoot);
|
|
96
|
+
await this.tokenStore.initialize();
|
|
97
|
+
// Create default admin user if no users exist
|
|
98
|
+
const users = await this.userStore.listUsers();
|
|
99
|
+
if (users.length === 0) {
|
|
100
|
+
const adminUser = await this.userStore.createUser({
|
|
101
|
+
username: 'admin',
|
|
102
|
+
password: 'admin123',
|
|
103
|
+
role: this.config.auth.roles[0]?.role ?? 'admin',
|
|
104
|
+
});
|
|
105
|
+
const adminServiceToken = issueServiceToken(adminUser.userId, adminUser.username, adminUser.role, this.config.auth);
|
|
106
|
+
this.fastify.log.warn('⚠ Default admin user created with password "admin123" — change this immediately!');
|
|
107
|
+
this.fastify.log.info(`Admin service token: ${adminServiceToken}`);
|
|
108
|
+
}
|
|
109
|
+
// Register auth middleware
|
|
110
|
+
const authMiddleware = createAuthMiddleware({ config: this.config.auth });
|
|
111
|
+
this.fastify.addHook('preHandler', authMiddleware);
|
|
112
|
+
// Register auth routes (before business routes so exempt paths are matched first)
|
|
113
|
+
registerAuthRoutes(this.fastify, {
|
|
114
|
+
config: this.config.auth,
|
|
115
|
+
userStore: this.userStore,
|
|
116
|
+
tokenStore: this.tokenStore,
|
|
117
|
+
});
|
|
80
118
|
}
|
|
81
119
|
// Static file serving in production
|
|
82
120
|
if (serverConfig.staticDir) {
|
|
@@ -141,6 +179,14 @@ export class LoomServer {
|
|
|
141
179
|
getAdapter() {
|
|
142
180
|
return this.adapter;
|
|
143
181
|
}
|
|
182
|
+
/** Expose user store for testing */
|
|
183
|
+
getUserStore() {
|
|
184
|
+
return this.userStore;
|
|
185
|
+
}
|
|
186
|
+
/** Expose token store for testing */
|
|
187
|
+
getTokenStore() {
|
|
188
|
+
return this.tokenStore;
|
|
189
|
+
}
|
|
144
190
|
}
|
|
145
191
|
/**
|
|
146
192
|
* Create and start a LoomServer from a project root
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAC3C,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Routes
|
|
3
|
+
*
|
|
4
|
+
* POST /api/v1/auth/login - Login with username/password
|
|
5
|
+
* POST /api/v1/auth/register - Register new user (admin only)
|
|
6
|
+
* POST /api/v1/auth/logout - Logout (revoke refresh token)
|
|
7
|
+
* POST /api/v1/auth/refresh - Refresh access token
|
|
8
|
+
* GET /api/v1/auth/whoami - Current user info
|
|
9
|
+
* GET /api/v1/auth/roles - List roles + permissions
|
|
10
|
+
* GET /api/v1/auth/users - List users (admin only)
|
|
11
|
+
* POST /api/v1/auth/users - Create user (admin only)
|
|
12
|
+
* GET /api/v1/auth/users/:id - Get user
|
|
13
|
+
* PUT /api/v1/auth/users/:id - Update user (admin only)
|
|
14
|
+
* DELETE /api/v1/auth/users/:id - Delete user (admin only)
|
|
15
|
+
*/
|
|
16
|
+
import type { FastifyInstance } from 'fastify';
|
|
17
|
+
import type { AuthConfig } from '../../types/auth.js';
|
|
18
|
+
import type { UserStore } from '../auth/user-store.js';
|
|
19
|
+
import type { TokenStore } from '../auth/token-store.js';
|
|
20
|
+
export interface AuthRouteOptions {
|
|
21
|
+
config: AuthConfig;
|
|
22
|
+
userStore: UserStore;
|
|
23
|
+
tokenStore: TokenStore;
|
|
24
|
+
}
|
|
25
|
+
export declare function registerAuthRoutes(fastify: FastifyInstance, options: AuthRouteOptions): void;
|
|
26
|
+
//# sourceMappingURL=auth-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-routes.d.ts","sourceRoot":"","sources":["../../../src/backend/routes/auth-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAMzD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAuU5F"}
|