@camstack/server 1.2.486 → 1.2.487

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 (36) hide show
  1. package/dist/agent/agent-mesh-join.js +80 -0
  2. package/dist/agent/main.js +61 -2
  3. package/dist/api/auth-whoami.js +1 -1
  4. package/dist/api/core/auth-admin-tokens.procedures.js +138 -0
  5. package/dist/api/core/auth-limits.js +77 -0
  6. package/dist/api/core/auth-reauth.procedures.js +108 -0
  7. package/dist/api/core/auth-sessions.procedures.js +166 -0
  8. package/dist/api/core/auth.router.js +281 -80
  9. package/dist/api/health/adaptive-probe.routes.js +1 -1
  10. package/dist/api/trpc/core-cap-bridge.js +47 -5
  11. package/dist/api/trpc/generated-cap-mounts.js +19 -1
  12. package/dist/api/trpc/generated-cap-routers.js +512 -205
  13. package/dist/api/trpc/trpc.context.js +86 -34
  14. package/dist/api/trpc/trpc.middleware.js +8 -11
  15. package/dist/api/trpc/trpc.router.js +6 -1
  16. package/dist/auth/auth-network-policy.js +75 -0
  17. package/dist/auth/auth-rate-limit.js +25 -20
  18. package/dist/auth/client-address.js +68 -0
  19. package/dist/auth/external-link-intents.js +12 -3
  20. package/dist/auth/hub-sessions.js +74 -0
  21. package/dist/auth/native-link-completions.js +68 -0
  22. package/dist/auth/native-return.js +33 -0
  23. package/dist/auth/session-lifetimes.js +46 -0
  24. package/dist/auth/session-mint.js +110 -13
  25. package/dist/auth/sso-finish-deps.js +56 -1
  26. package/dist/auth/sso-finish.js +132 -17
  27. package/dist/auth/sso-routes.js +95 -0
  28. package/dist/auth/used-bridge-ids.js +52 -0
  29. package/dist/core/addon/addon-registry.service.js +5 -0
  30. package/dist/core/agent/agent-registry.service.js +10 -0
  31. package/dist/core/auth/auth.service.js +50 -1
  32. package/dist/core/auth/handoff-code.service.js +9 -3
  33. package/dist/core/moleculer/hub-mesh-guard.js +132 -0
  34. package/dist/core/moleculer/moleculer.service.js +33 -0
  35. package/dist/main.js +92 -28
  36. package/package.json +13 -13
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RefreshResultSchema = exports.LoginSessionSchema = void 0;
4
+ exports.createSessionProcedures = createSessionProcedures;
5
+ const server_1 = require("@trpc/server");
6
+ const zod_1 = require("zod");
7
+ const hub_sessions_js_1 = require("../../auth/hub-sessions.js");
8
+ const session_mint_js_1 = require("../../auth/session-mint.js");
9
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
10
+ /** One login session as the UI lists it. */
11
+ exports.LoginSessionSchema = zod_1.z.object({
12
+ id: zod_1.z.string(),
13
+ userId: zod_1.z.string(),
14
+ method: zod_1.z.string(),
15
+ refreshable: zod_1.z.boolean(),
16
+ createdAt: zod_1.z.number(),
17
+ lastUsedAt: zod_1.z.number(),
18
+ expiresAt: zod_1.z.number(),
19
+ client: zod_1.z.string().nullable(),
20
+ ip: zod_1.z.string().nullable(),
21
+ /** The session this request was made with. */
22
+ current: zod_1.z.boolean(),
23
+ });
24
+ /** What a refresh returns: a new access token and the rotated refresh token. */
25
+ exports.RefreshResultSchema = zod_1.z.object({
26
+ token: zod_1.z.string(),
27
+ refreshToken: zod_1.z.string(),
28
+ expiresAt: zod_1.z.number(),
29
+ sessionId: zod_1.z.string(),
30
+ sessionExpiresAt: zod_1.z.number(),
31
+ user: zod_1.z.object({ id: zod_1.z.string(), username: zod_1.z.string(), isAdmin: zod_1.z.boolean() }),
32
+ });
33
+ function requireSessions(registry) {
34
+ const internal = registry === null ? null : (0, hub_sessions_js_1.userManagementInternal)(registry);
35
+ if (internal === null) {
36
+ throw new server_1.TRPCError({
37
+ code: 'PRECONDITION_FAILED',
38
+ message: 'Login sessions are not available',
39
+ });
40
+ }
41
+ return internal.sessions;
42
+ }
43
+ /** Real user sessions only — a scoped or share token has no login session to manage. */
44
+ function assertLoginSession(user) {
45
+ if (user.isScoped === true || user.shareView !== undefined || user.adminTokenId !== undefined) {
46
+ throw new server_1.TRPCError({ code: 'FORBIDDEN', message: 'Requires a signed-in user session' });
47
+ }
48
+ }
49
+ function createSessionProcedures(deps) {
50
+ const list = (userId, currentId) => {
51
+ const sessions = requireSessions(deps.registry);
52
+ const rows = userId === null ? sessions.listActive() : sessions.listForUser(userId);
53
+ return rows.map((row) => ({
54
+ id: row.id,
55
+ userId: row.userId,
56
+ method: row.method,
57
+ refreshable: row.refreshable,
58
+ createdAt: row.createdAt,
59
+ lastUsedAt: row.lastUsedAt,
60
+ expiresAt: row.expiresAt,
61
+ client: row.client,
62
+ ip: row.ip,
63
+ current: row.id === currentId,
64
+ }));
65
+ };
66
+ return {
67
+ /**
68
+ * PUBLIC — swap a refresh token for a new access token and a rotated
69
+ * refresh token; the session's expiry slides. A rotated-out token
70
+ * presented again (outside a short grace) is treated as stolen and ends
71
+ * the session. Any refusal is a 401: the client signs in again.
72
+ */
73
+ refreshSession: deps.credentialProcedure
74
+ .input(zod_1.z.object({ refreshToken: zod_1.z.string().min(1).max(512) }))
75
+ .output(exports.RefreshResultSchema)
76
+ .mutation(async ({ input }) => {
77
+ try {
78
+ const minted = await deps.minter.refresh(input.refreshToken);
79
+ if (minted.refreshToken === undefined ||
80
+ minted.sessionId === undefined ||
81
+ minted.expiresAt === undefined ||
82
+ minted.sessionExpiresAt === undefined) {
83
+ throw new session_mint_js_1.SessionRefreshRefusedError('unknown');
84
+ }
85
+ return {
86
+ token: minted.token,
87
+ refreshToken: minted.refreshToken,
88
+ expiresAt: minted.expiresAt,
89
+ sessionId: minted.sessionId,
90
+ sessionExpiresAt: minted.sessionExpiresAt,
91
+ user: minted.user,
92
+ };
93
+ }
94
+ catch (error) {
95
+ if (error instanceof session_mint_js_1.SessionRefreshRefusedError ||
96
+ error instanceof session_mint_js_1.SessionUserGoneError) {
97
+ throw new server_1.TRPCError({
98
+ code: 'UNAUTHORIZED',
99
+ message: 'Session expired — sign in again',
100
+ });
101
+ }
102
+ throw error;
103
+ }
104
+ }),
105
+ /**
106
+ * End the caller's session on the server (its access and refresh tokens
107
+ * stop working at once). `everywhere: true` ends every session of the
108
+ * user, and their pre-session tokens.
109
+ */
110
+ logout: trpc_middleware_js_1.protectedProcedure
111
+ .input(zod_1.z.object({ everywhere: zod_1.z.boolean().optional() }).optional())
112
+ .output(zod_1.z.object({ success: zod_1.z.literal(true), revoked: zod_1.z.number() }))
113
+ .mutation(async ({ ctx, input }) => {
114
+ assertLoginSession(ctx.user);
115
+ const sessions = requireSessions(deps.registry);
116
+ if (input?.everywhere === true) {
117
+ const revoked = await sessions.revokeAllForUser(ctx.user.id, {
118
+ reason: 'logout-everywhere',
119
+ });
120
+ return { success: true, revoked };
121
+ }
122
+ const sessionId = ctx.user.sessionId;
123
+ const revoked = sessionId === undefined ? false : await sessions.revoke(sessionId, 'logout');
124
+ return { success: true, revoked: revoked ? 1 : 0 };
125
+ }),
126
+ /** The caller's live sessions, newest first; `current` marks this one. */
127
+ listOwnSessions: trpc_middleware_js_1.protectedProcedure
128
+ .input(zod_1.z.void())
129
+ .output(zod_1.z.array(exports.LoginSessionSchema))
130
+ .query(({ ctx }) => {
131
+ assertLoginSession(ctx.user);
132
+ return list(ctx.user.id, ctx.user.sessionId);
133
+ }),
134
+ /** End one of the caller's own sessions (another device). */
135
+ revokeOwnSession: trpc_middleware_js_1.protectedProcedure
136
+ .input(zod_1.z.object({ id: zod_1.z.string().min(1) }))
137
+ .output(zod_1.z.object({ success: zod_1.z.boolean() }))
138
+ .mutation(async ({ ctx, input }) => {
139
+ assertLoginSession(ctx.user);
140
+ const sessions = requireSessions(deps.registry);
141
+ const check = sessions.check(input.id);
142
+ if (check.state !== 'active' || check.session.userId !== ctx.user.id) {
143
+ return { success: false };
144
+ }
145
+ return { success: await sessions.revoke(input.id, 'revoked-by-user') };
146
+ }),
147
+ /** ADMIN — live sessions of one user, or of everyone. */
148
+ listSessions: trpc_middleware_js_1.adminProcedure
149
+ .input(zod_1.z.object({ userId: zod_1.z.string().min(1).optional() }).optional())
150
+ .output(zod_1.z.array(exports.LoginSessionSchema))
151
+ .query(({ ctx, input }) => list(input?.userId ?? null, ctx.user.sessionId)),
152
+ /** ADMIN — end one session, or every session of a user. */
153
+ revokeSessions: trpc_middleware_js_1.adminProcedure
154
+ .input(zod_1.z.union([zod_1.z.object({ id: zod_1.z.string().min(1) }), zod_1.z.object({ userId: zod_1.z.string().min(1) })]))
155
+ .output(zod_1.z.object({ revoked: zod_1.z.number() }))
156
+ .mutation(async ({ input }) => {
157
+ const sessions = requireSessions(deps.registry);
158
+ if ('id' in input) {
159
+ return { revoked: (await sessions.revoke(input.id, 'revoked-by-admin')) ? 1 : 0 };
160
+ }
161
+ return {
162
+ revoked: await sessions.revokeAllForUser(input.userId, { reason: 'revoked-by-admin' }),
163
+ };
164
+ }),
165
+ };
166
+ }